1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
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
;
112 pHeaderBar
->EnableRTL( IsRTLEnabled() );
113 aHScroll
->EnableRTL( IsRTLEnabled() );
115 pVScroll
->EnableRTL( IsRTLEnabled() );
118 else if ( StateChangedType::InitShow
== nStateChange
)
120 bBootstrapped
= true; // must be set first!
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
)
133 bSelectionIsVisible
= true;
137 AutoSizeLastColumn();
140 else if (StateChangedType::Zoom
== nStateChange
)
142 pDataWin
->SetZoom(GetZoom());
143 HeaderBar
* pHeaderBar
= pDataWin
->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());
152 pHeaderBar
->SetItemSize( pCol
->GetId(), pCol
->Width() );
155 // all our controls have to be repositioned
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
);
170 // we draw the text in our header bar in a color dependent on the enabled state. So if this state changed
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()
224 void BrowseBox::EndScroll()
227 AutoSizeLastColumn();
232 void BrowseBox::ToggleSelection()
235 // selection highlight-toggling allowed?
238 if ( bNotToggleSel
|| !IsUpdateMode() || !bSelectionIsVisible
)
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
)
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
);
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(),
289 aRect
.AdjustLeft( -(MIN_COLUMNWIDTH
) );
290 aRect
.AdjustRight(MIN_COLUMNWIDTH
);
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() )
308 else if ( bHideCursor
== TRISTATE_TRUE
)
313 bReallyHide
|= !bSelectionIsVisible
|| !IsUpdateMode() || bScrolling
|| nCurRow
< 0;
315 if (PaintCursorIfHiddenOnce())
316 bReallyHide
|= ( GetCursorHideCount() > 1 );
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
;
328 aCursor
= GetFieldRectPixel( nCurRow
, nCurColId
, false );
329 aCursor
.AdjustLeft( -(MIN_COLUMNWIDTH
) );
330 aCursor
.AdjustRight(1 );
331 aCursor
.AdjustBottom(1 );
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 ) );
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
351 static_cast<Control
*>(pDataWin
.get())->HideFocus();
353 static_cast<Control
*>(pDataWin
.get())->ShowFocus( aCursor
);
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() )
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
)
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();
406 void BrowseBox::ExpandRowSelection( const BrowserMouseEvent
& rEvt
)
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() ) )
421 while ( rEvt
.GetRow() < aSelRange
.Max() )
422 { // ZTC/Mac bug - don't put these statements together!
423 SelectRow( aSelRange
.Max(), bSelectThis
);
426 while ( rEvt
.GetRow() > aSelRange
.Max() )
427 { // ZTC/Mac bug - don't put these statements together!
428 SelectRow( aSelRange
.Max(), bSelectThis
);
435 bool bOldSelecting
= bSelecting
;
437 while ( rEvt
.GetRow() < aSelRange
.Max() )
438 { // ZTC/Mac bug - don't put these statements together!
440 if ( !IsRowSelected( aSelRange
.Max() ) )
442 SelectRow( aSelRange
.Max(), bSelectThis
);
446 while ( rEvt
.GetRow() > aSelRange
.Max() )
447 { // ZTC/Mac bug - don't put these statements together!
449 if ( !IsRowSelected( aSelRange
.Max() ) )
451 SelectRow( aSelRange
.Max(), bSelectThis
);
455 bSelecting
= bOldSelecting
;
461 if (!IsRowSelected(rEvt
.GetRow()))
462 SelectRow( rEvt
.GetRow() );
464 GoToRow( rEvt
.GetRow(), false );
469 void BrowseBox::Resize()
471 if ( !bBootstrapped
&& IsReallyVisible() )
472 BrowseBox::StateChanged( StateChangedType::InitShow
);
473 if ( mvCols
.empty() )
475 pDataWin
->bResizeOnPaint
= true;
478 pDataWin
->bResizeOnPaint
= false;
480 // calc the size of the scrollbars
481 tools::Long nSBHeight
= GetBarHeight();
482 tools::Long nSBWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
485 nSBHeight
= static_cast<tools::Long
>(nSBHeight
* static_cast<double>(GetZoom()));
486 nSBWidth
= static_cast<tools::Long
>(nSBWidth
* static_cast<double>(GetZoom()));
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 ) )
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
);
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
;
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
548 void BrowseBox::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
551 if (!bBootstrapped
&& IsReallyVisible())
552 BrowseBox::StateChanged(StateChangedType::InitShow
);
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()));
570 rRenderContext
.DrawLine(Point(0, GetTitleHeight() - 1),
571 Point(GetOutputSizePixel().Width(), GetTitleHeight() - 1));
575 rRenderContext
.DrawLine(Point(0, GetTitleHeight() - 1),
576 Point(pFirstCol
->Width(), GetTitleHeight() - 1));
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
)))
586 // iterate through columns to redraw
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())
595 // only the handle column?
596 if (bHeaderBar
&& bHandleCol
&& nCol
> 0)
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));
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();
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 ...
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
665 pDev
->SetFont( aFont
);
666 if (nFlags
& SystemTextColorFlags::Mono
)
667 pDev
->SetTextColor(COL_BLACK
);
669 pDev
->SetTextColor(pDataWin
->GetTextColor());
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
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());
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
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 ) );
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();
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());
788 pBar
->SetItemSize( pCurrent
->GetId(), pCurrent
->Width() );
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
) )
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
)
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
);
855 _rOut
.SetTextColor( rHighlightTextColor
);
856 _rOut
.SetFillColor( rHighlightFillColor
);
857 _rOut
.SetLineColor();
858 _rOut
.DrawRect( aRowRect
);
861 // iterate through columns to redraw
863 for ( nCol
= 0; nCol
< mvCols
.size(); ++nCol
)
866 BrowserColumn
*pCol
= mvCols
[ nCol
].get();
868 // at end of invalid area
869 if ( aPos
.X() >= _rRect
.Right() )
872 // skip invisible columns between frozen and scrollable area
873 if ( nCol
< nFirstCol
&& !pCol
->IsFrozen() )
876 pCol
= (nCol
< mvCols
.size() ) ? mvCols
[ nCol
].get() : nullptr;
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 !");
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()))
903 // draw a single field.
904 // else something is drawn to, e.g. handle column
907 // clip the column's output to the field area
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)
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
);
928 _rOut
.SetClipRegion();
931 // reset Column-auto-highlight
932 if ( bColAutoHighlight
)
934 _rOut
.SetTextColor( aOldTextColor
);
935 _rOut
.SetFillColor( aOldFillColor
);
936 _rOut
.SetLineColor( aOldLineColor
);
940 aPos
.AdjustX(pCol
->Width() );
943 // reset auto-highlight
946 _rOut
.SetTextColor( aOldTextColor
);
947 _rOut
.SetFillColor( aOldFillColor
);
948 _rOut
.SetLineColor( aOldLineColor
);
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
),
961 ? std::min(tools::Long(aPos
.X() - 1), aOverallAreaBRPos
.X())
962 : aOverallAreaBRPos
.X(),
968 if (aPos
.Y() > aOverallAreaBRPos
.Y() + 1)
969 aPos
.setY( aOverallAreaBRPos
.Y() + 1 );
970 // needed for some of the following drawing
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
995 : aOverallAreaBRPos
.Y() ) );
997 // draw vertical delimitational lines?
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
)
1006 BrowserColumn
*pCol
= mvCols
[ nCol
].get();
1008 // skip invisible columns between frozen and scrollable area
1009 if ( nCol
< nFirstCol
&& !pCol
->IsFrozen() )
1012 pCol
= mvCols
[ nCol
].get();
1016 aVertPos
.AdjustX(pCol
->Width() );
1018 // at end of invalid area
1019 // invalid area is first reached when X > Right
1021 if ( aVertPos
.X() > _rRect
.Right() )
1024 // draw a single line
1025 if ( pCol
->GetId() != 0 )
1026 _rOut
.DrawLine( aVertPos
, Point( aVertPos
.X(),
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
);
1042 if (mvCols
.empty() || !rWin
.IsUpdateMode())
1044 if (pDataWin
->bResizeOnPaint
)
1046 // MI: who was that? Window::Update();
1048 ImplPaintData(rRenderContext
, rRect
, false);
1051 void BrowseBox::UpdateScrollbars()
1054 if ( !bBootstrapped
|| !IsUpdateMode() )
1057 // protect against recursion
1058 if ( pDataWin
->bInUpdateScrollbars
)
1060 pDataWin
->bHadRecursion
= true;
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();
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())
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() )
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
;
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() )
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
);
1139 short nVisibleHSize
= nLastCol
== BROWSER_INVALIDID
1140 ? static_cast<short>( mvCols
.size() - nFirstCol
)
1141 : static_cast<short>( nLastCol
- nFirstCol
);
1145 short nRange
= std::max( nScrollCols
, short(0) );
1146 aHScroll
->SetVisibleSize( nVisibleHSize
);
1147 aHScroll
->SetRange( Range( 0, nRange
));
1151 // ensure scrollbar is shown as fully filled
1152 aHScroll
->SetVisibleSize(1);
1153 aHScroll
->SetRange(Range(0, 1));
1155 if ( bNeedsHScroll
&& !aHScroll
->IsVisible() )
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() )
1181 pDataWin
->SetPosSizePixel(
1182 Point( 0, GetTitleHeight() ),
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
;
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;
1225 void BrowseBox::SetUpdateMode( bool bUpdate
)
1228 bool bWasUpdate
= IsUpdateMode();
1229 if ( bWasUpdate
== bUpdate
)
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.
1236 pDataWin
->Invalidate();
1237 pDataWin
->SetUpdateMode( bUpdate
);
1242 if ( bBootstrapped
)
1245 AutoSizeLastColumn();
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();
1268 nWidth
+= mvCols
[ nCol
]->Width();
1272 void BrowseBox::ColumnInserted( sal_uInt16 nPos
)
1275 pColSel
->Insert( nPos
);
1279 sal_uInt16
BrowseBox::FrozenColCount() const
1283 nCol
< mvCols
.size() && mvCols
[ nCol
]->IsFrozen();
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
);
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();
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
)
1327 // only mouse events in the title-line are supported
1328 const Point
&rEvtPos
= rEvt
.GetPosPixel();
1329 if ( rEvtPos
.Y() >= GetTitleHeight() )
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
1349 nDragX
= nResizeX
= rEvtPos
.X();
1350 SetPointer( PointerStyle::HSplit
);
1352 pDataWin
->GetOutDev()->DrawLine( Point( nDragX
, 0 ),
1353 Point( nDragX
, pDataWin
->GetSizePixel().Height() ) );
1354 nMinResizeX
= nX
+ MIN_COLUMNWIDTH
;
1357 else if ( nX
< rEvtPos
.X() && nR
> rEvtPos
.X() )
1359 MouseButtonDown( BrowserMouseEvent(
1360 this, rEvt
, -1, nCol
, pCol
->GetId(), tools::Rectangle() ) );
1367 // event occurred out of data area
1368 if ( rEvt
.IsRight() )
1370 CommandEvent( Point( 1, LONG_MAX
), CommandEventId::ContextMenu
, true ) );
1376 void BrowseBox::MouseMove( const MouseEvent
& rEvt
)
1378 SAL_INFO("svtools", "BrowseBox::MouseMove( MouseEvent )" );
1380 PointerStyle aNewPointer
= PointerStyle::Arrow
;
1383 for ( size_t nCol
= 0;
1384 nCol
< mvCols
.size() &&
1385 ( nX
+ mvCols
[ nCol
]->Width() ) < GetOutputSizePixel().Width();
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
;
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
);
1422 SetPointer( aNewPointer
);
1426 void BrowseBox::MouseButtonUp( const MouseEvent
& rEvt
)
1431 // delete auxiliary line
1432 pDataWin
->HideTracking();
1435 nDragX
= std::max( rEvt
.GetPosPixel().X(), nMinResizeX
);
1436 if ( (nDragX
- nResizeX
) != mvCols
[ nResizeCol
]->Width() )
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
);
1448 SetPointer( PointerStyle::Arrow
);
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
)
1469 // adjust selection while and after double-click
1470 if ( rEvt
.GetClicks() == 2 )
1473 if ( rEvt
.GetRow() >= 0 )
1475 GoToRow( rEvt
.GetRow() );
1476 SelectRow( rEvt
.GetRow(), true, false );
1480 if ( bColumnCursor
&& rEvt
.GetColumn() != 0 )
1482 if ( rEvt
.GetColumn() < mvCols
.size() )
1483 SelectColumnPos( rEvt
.GetColumn(), true, false);
1486 DoubleClick( rEvt
);
1489 else if ( ( rEvt
.GetMode() & ( MouseEventModifiers::SELECT
| MouseEventModifiers::SIMPLECLICK
) ) &&
1490 ( bColumnCursor
|| rEvt
.GetRow() >= 0 ) )
1492 if ( rEvt
.GetClicks() == 1 )
1497 // selection out of range?
1498 if ( rEvt
.GetRow() >= nRowCount
||
1499 rEvt
.GetColumnId() == BROWSER_INVALIDID
)
1505 // while selecting, no cursor
1510 if ( rEvt
.GetRow() >= 0 )
1513 if ( rEvt
.GetColumnId() == HandleColumnId
|| !bColumnCursor
)
1515 if ( bMultiSelection
)
1517 // remove column-selection, if exists
1518 if ( pColSel
&& pColSel
->GetSelectCount() )
1521 if ( bMultiSelection
)
1522 uRow
.pSel
->SelectAll(false);
1524 uRow
.nSel
= BROWSER_ENDOFSELECTION
;
1526 pColSel
->SelectAll(false);
1531 if ( rEvt
.GetMode() & MouseEventModifiers::RANGESELECT
)
1533 // select the further touched rows too
1535 ExpandRowSelection( rEvt
);
1539 // click in the selected area?
1540 else if ( IsRowSelected( rEvt
.GetRow() ) )
1542 // wait for Drag&Drop
1544 bExtendedMode
= bool( rEvt
.GetMode() & MouseEventModifiers::MULTISELECT
);
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() ) );
1563 GoToRow( rEvt
.GetRow() );
1564 SelectRow( rEvt
.GetRow() );
1565 aSelRange
= Range( rEvt
.GetRow(), rEvt
.GetRow() );
1568 else // Column/Field-Selection
1570 // click in selected column
1571 if ( IsColumnSelected( rEvt
.GetColumn() ) ||
1572 IsRowSelected( rEvt
.GetRow() ) )
1580 GoToRowColumnId( rEvt
.GetRow(), rEvt
.GetColumnId() );
1586 if ( bMultiSelection
&& rEvt
.GetColumnId() == HandleColumnId
)
1588 // toggle all-selection
1589 if ( uRow
.pSel
->GetSelectCount() > ( GetRowCount() / 2 ) )
1595 SelectColumnPos( GetColumnPos(rEvt
.GetColumnId()), true, false);
1598 // turn cursor on again, if necessary
1608 void BrowseBox::MouseButtonUp( const BrowserMouseEvent
&rEvt
)
1611 // D&D was possible, but did not occur
1614 aSelRange
= Range( rEvt
.GetRow(), rEvt
.GetRow() );
1615 if ( bExtendedMode
)
1616 SelectRow( rEvt
.GetRow(), false );
1621 GoToRowColumnId( rEvt
.GetRow(), rEvt
.GetColumnId() );
1624 GoToRow( rEvt
.GetRow() );
1625 SelectRow( rEvt
.GetRow() );
1629 bExtendedMode
= false;
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
)
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;
1671 if ( !bColumnCursor
)
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
)
1683 case KEY_PAGEDOWN
: nId
= BROWSER_CURSORPAGEDOWN
; break;
1684 case KEY_PAGEUP
: nId
= BROWSER_CURSORPAGEUP
; break;
1688 if ( !bAlt
&& !bCtrl
&& bShift
)
1691 case KEY_DOWN
: nId
= BROWSER_SELECTDOWN
; break;
1692 case KEY_UP
: nId
= BROWSER_SELECTUP
; break;
1694 if ( !bColumnCursor
)
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
)
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
)
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();
1736 case BROWSER_SELECTCOLUMN
:
1738 SelectColumnId( GetCurColumnId() );
1741 case BROWSER_CURSORDOWN
:
1742 if ( ( GetCurRow() + 1 ) < nRowCount
)
1743 GoToRow( GetCurRow() + 1, false );
1745 case BROWSER_CURSORUP
:
1746 if ( GetCurRow() > 0 )
1747 GoToRow( GetCurRow() - 1, false );
1749 case BROWSER_SELECTHOME
:
1750 if ( GetRowCount() )
1753 for ( sal_Int32 nRow
= GetCurRow(); nRow
>= 0; --nRow
)
1759 case BROWSER_SELECTEND
:
1760 if ( GetRowCount() )
1763 sal_Int32 nRows
= GetRowCount();
1764 for ( sal_Int32 nRow
= GetCurRow(); nRow
< nRows
; ++nRow
)
1766 GoToRow( GetRowCount() - 1, true );
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 );
1782 SelectRow( GetCurRow() );
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 );
1799 SelectRow( GetCurRow() );
1802 case BROWSER_CURSORPAGEDOWN
:
1803 ScrollRows( nRowsOnPage
);
1805 case BROWSER_CURSORPAGEUP
:
1806 ScrollRows( -nRowsOnPage
);
1808 case BROWSER_CURSOREND
:
1809 if ( bColumnCursor
)
1811 sal_uInt16 nNewId
= GetColumnId(ColCount() -1);
1812 nNewId
!= HandleColumnId
&& GoToColumnId( nNewId
);
1816 case BROWSER_CURSORENDOFFILE
:
1817 GoToRow( nRowCount
- 1, false );
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
);
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
);
1845 case BROWSER_CURSORHOME
:
1846 if ( bColumnCursor
)
1848 sal_uInt16 nNewId
= GetColumnId(1);
1849 if (nNewId
!= HandleColumnId
)
1851 GoToColumnId( nNewId
);
1856 case BROWSER_CURSORTOPOFFILE
:
1857 GoToRow( 0, false );
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
);
1868 if ( GetRowCount() )
1872 GoToRowColumnId(nCurRow
- 1, GetColumnId(ColCount() -1));
1875 else if ( ColCount() )
1876 GoToColumnId( GetColumnId(ColCount() -1) );
1880 ScrollColumns( -1 );
1882 case BROWSER_ENHANCESELECTION
:
1883 if ( GetRowCount() )
1884 SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ) );
1886 case BROWSER_SELECT
:
1887 if ( GetRowCount() )
1888 SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ), false );
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 )
1903 bMoveAllowed
= true;
1905 else if ( BROWSER_MOVECOLUMNRIGHT
== nId
&& nNewPos
< (ColCount()-1) )
1908 bMoveAllowed
= true;
1913 SetColumnPos( nColId
, nNewPos
);
1914 ColumnMoved( nColId
);
1915 MakeFieldVisible(GetCurRow(), nColId
);
1916 if ( bColumnSelected
)
1917 SelectColumnId(nColId
);
1926 void BrowseBox::SetCursorColor(const Color
& _rCol
)
1928 if (_rCol
== m_aCursorColor
)
1931 // ensure the cursor is hidden
1933 if (!m_bFocusOnlyCursor
)
1936 m_aCursorColor
= _rCol
;
1938 if (!m_bFocusOnlyCursor
)
1943 tools::Rectangle
BrowseBox::calcHeaderRect(bool _bIsColumnBar
, bool _bOnScreen
)
1945 vcl::Window
* pParent
= nullptr;
1947 pParent
= GetAccessibleParentWindow();
1951 tools::Long nHeight
;
1952 if ( _bIsColumnBar
)
1954 nWidth
= pDataWin
->GetOutputSizePixel().Width();
1955 nHeight
= GetDataRowHeight();
1959 aTopLeft
.setY( GetDataRowHeight() );
1960 nWidth
= GetColumnWidth(0);
1962 nHeight
= GetWindowExtentsRelative( *pParent
).GetHeight() - aTopLeft
.Y() - GetControlArea().GetSize().Height();
1964 nHeight
= GetWindowExtentsAbsolute().GetHeight() - aTopLeft
.Y() - GetControlArea().GetSize().Height();
1967 aTopLeft
+= GetWindowExtentsRelative( *pParent
).TopLeft();
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;
1977 pParent
= GetAccessibleParentWindow();
1979 tools::Rectangle aRect
;
1981 aRect
= GetWindowExtentsRelative( *pParent
);
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;
1997 pParent
= GetAccessibleParentWindow();
1999 tools::Rectangle aRect
= GetFieldRectPixel(_nRowId
,_nColId
,_bOnScreen
);
2001 Point aTopLeft
= aRect
.TopLeft();
2003 aTopLeft
+= GetWindowExtentsRelative( *pParent
).TopLeft();
2005 aTopLeft
+= Point(GetWindowExtentsAbsolute().TopLeft());
2007 return tools::Rectangle(aTopLeft
,aRect
.GetSize());
2010 // ------------------------------------------------------------------------- EOF
2012 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */