/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include #include #include "datwin.hxx" #include #include #include #include using namespace ::com::sun::star::datatransfer; #define getDataWindow() ((BrowserDataWin*)pDataWin) //=================================================================== DBG_NAMEEX(BrowseBox) //=================================================================== extern const char* BrowseBoxCheckInvariants( const void * pVoid ); //=================================================================== void BrowseBox::StartDrag( sal_Int8 /* _nAction */, const Point& /* _rPosPixel */ ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); // not interested in this event } //=================================================================== sal_Int8 BrowseBox::AcceptDrop( const AcceptDropEvent& _rEvt ) { BrowserDataWin* pDataWindow = static_cast(pDataWin); AcceptDropEvent aTransformed( _rEvt ); aTransformed.maPosPixel = pDataWindow->ScreenToOutputPixel( OutputToScreenPixel( _rEvt.maPosPixel ) ); return pDataWindow->AcceptDrop( aTransformed ); } //=================================================================== sal_Int8 BrowseBox::ExecuteDrop( const ExecuteDropEvent& _rEvt ) { BrowserDataWin* pDataWindow = static_cast(pDataWin); ExecuteDropEvent aTransformed( _rEvt ); aTransformed.maPosPixel = pDataWindow->ScreenToOutputPixel( OutputToScreenPixel( _rEvt.maPosPixel ) ); return pDataWindow->ExecuteDrop( aTransformed ); } //=================================================================== sal_Int8 BrowseBox::AcceptDrop( const BrowserAcceptDropEvent& ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); // not interested in this event return DND_ACTION_NONE; } //=================================================================== sal_Int8 BrowseBox::ExecuteDrop( const BrowserExecuteDropEvent& ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); // not interested in this event return DND_ACTION_NONE; } //=================================================================== void* BrowseBox::implGetDataFlavors() const { if (static_cast(pDataWin)->bCallingDropCallback) return &static_cast(pDataWin)->GetDataFlavorExVector(); return &GetDataFlavorExVector(); } //=================================================================== sal_Bool BrowseBox::IsDropFormatSupported( SotFormatStringId _nFormat ) { if ( static_cast< BrowserDataWin* >( pDataWin )->bCallingDropCallback ) return static_cast< BrowserDataWin* >( pDataWin )->IsDropFormatSupported( _nFormat ); return DropTargetHelper::IsDropFormatSupported( _nFormat ); } //=================================================================== sal_Bool BrowseBox::IsDropFormatSupported( SotFormatStringId _nFormat ) const { return const_cast< BrowseBox* >( this )->IsDropFormatSupported( _nFormat ); } //=================================================================== sal_Bool BrowseBox::IsDropFormatSupported( const DataFlavor& _rFlavor ) { if ( static_cast< BrowserDataWin* >( pDataWin )->bCallingDropCallback ) return static_cast< BrowserDataWin* >( pDataWin )->IsDropFormatSupported( _rFlavor ); return DropTargetHelper::IsDropFormatSupported( _rFlavor ); } //=================================================================== sal_Bool BrowseBox::IsDropFormatSupported( const DataFlavor& _rFlavor ) const { return const_cast< BrowseBox* >( this )->IsDropFormatSupported( _rFlavor ); } //=================================================================== void BrowseBox::Command( const CommandEvent& rEvt ) { if ( !getDataWindow()->bInCommand ) Control::Command( rEvt ); } //=================================================================== void BrowseBox::StateChanged( StateChangedType nStateChange ) { Control::StateChanged( nStateChange ); if ( STATE_CHANGE_MIRRORING == nStateChange ) { getDataWindow()->EnableRTL( IsRTLEnabled() ); HeaderBar* pHeaderBar = getDataWindow()->pHeaderBar; if ( pHeaderBar ) pHeaderBar->EnableRTL( IsRTLEnabled() ); aHScroll.EnableRTL( IsRTLEnabled() ); if( pVScroll ) pVScroll->EnableRTL( IsRTLEnabled() ); Resize(); } else if ( STATE_CHANGE_INITSHOW == nStateChange ) { bBootstrapped = sal_True; // must be set first! Resize(); if ( bMultiSelection ) uRow.pSel->SetTotalRange( Range( 0, nRowCount - 1 ) ); if ( nRowCount == 0 ) nCurRow = BROWSER_ENDOFSELECTION; else if ( nCurRow == BROWSER_ENDOFSELECTION ) nCurRow = 0; if ( HasFocus() ) { bSelectionIsVisible = sal_True; bHasFocus = sal_True; } UpdateScrollbars(); AutoSizeLastColumn(); CursorMoved(); } else if (STATE_CHANGE_ZOOM == nStateChange) { pDataWin->SetZoom(GetZoom()); HeaderBar* pHeaderBar = getDataWindow()->pHeaderBar; if (pHeaderBar) pHeaderBar->SetZoom(GetZoom()); // let the columns calculate their new widths and adjust the header bar for ( size_t nPos = 0; nPos < pCols->size(); ++nPos ) { (*pCols)[ nPos ]->ZoomChanged(GetZoom()); if ( pHeaderBar ) pHeaderBar->SetItemSize( (*pCols)[ nPos ]->GetId(), (*pCols)[ nPos ]->Width() ); } // all our controls have to be repositioned Resize(); } else if (STATE_CHANGE_ENABLE == nStateChange) { // do we have a handle column? sal_Bool bHandleCol = !pCols->empty() && (0 == (*pCols)[ 0 ]->GetId()); // do we have a header bar? sal_Bool bHeaderBar = (NULL != static_cast(GetDataWindow()).pHeaderBar); if ( nTitleLines && ( !bHeaderBar || bHandleCol ) ) // we draw the text in our header bar in a color dependent on the enabled state. So if this state changed // -> redraw Invalidate(Rectangle(Point(0, 0), Size(GetOutputSizePixel().Width(), GetTitleHeight() - 1))); } } //=================================================================== void BrowseBox::Select() { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); } //------------------------------------------------------------------- void BrowseBox::DoubleClick( const BrowserMouseEvent & ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); } //------------------------------------------------------------------- long BrowseBox::QueryMinimumRowHeight() { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); return CalcZoom( 5 ); } //------------------------------------------------------------------- void BrowseBox::ImplStartTracking() { DBG_CHKTHIS( BrowseBox, BrowseBoxCheckInvariants ); } //------------------------------------------------------------------- void BrowseBox::ImplTracking() { DBG_CHKTHIS( BrowseBox, BrowseBoxCheckInvariants ); } //------------------------------------------------------------------- void BrowseBox::ImplEndTracking() { DBG_CHKTHIS( BrowseBox, BrowseBoxCheckInvariants ); } //------------------------------------------------------------------- void BrowseBox::RowHeightChanged() { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); } //------------------------------------------------------------------- long BrowseBox::QueryColumnResize( sal_uInt16, long nWidth ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); return nWidth; } //------------------------------------------------------------------- void BrowseBox::ColumnResized( sal_uInt16 ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); } //------------------------------------------------------------------- void BrowseBox::ColumnMoved( sal_uInt16 ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); } //------------------------------------------------------------------- void BrowseBox::StartScroll() { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); DoHideCursor( "StartScroll" ); } //------------------------------------------------------------------- void BrowseBox::EndScroll() { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); UpdateScrollbars(); AutoSizeLastColumn(); DoShowCursor( "EndScroll" ); } //------------------------------------------------------------------- #ifdef _MSC_VER #pragma optimize( "", off ) #endif void BrowseBox::ToggleSelection( sal_Bool bForce ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); // selection highlight-toggling allowed? if ( bHideSelect ) return; if ( !bForce && ( bNotToggleSel || !IsUpdateMode() || !bSelectionIsVisible ) ) return; // only highlight painted areas! bNotToggleSel = sal_True; if ( sal_False && !getDataWindow()->bInPaint ) pDataWin->Update(); // accumulate areas of rows to highlight RectangleList aHighlightList; long nLastRowInRect = 0; // for the CFront // don't highlight handle column BrowserColumn *pFirstCol = pCols->empty() ? NULL : (*pCols)[ 0 ]; long nOfsX = (!pFirstCol || pFirstCol->GetId()) ? 0 : pFirstCol->Width(); // accumulate old row selection long nBottomRow = nTopRow + pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight(); if ( nBottomRow > GetRowCount() && GetRowCount() ) nBottomRow = GetRowCount(); for ( long nRow = bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel; nRow != BROWSER_ENDOFSELECTION && nRow <= nBottomRow; nRow = bMultiSelection ? uRow.pSel->NextSelected() : BROWSER_ENDOFSELECTION ) { if ( nRow < nTopRow ) continue; Rectangle aAddRect( Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ), Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) ); if ( aHighlightList.size() && nLastRowInRect == ( nRow - 1 ) ) aHighlightList[ 0 ]->Union( aAddRect ); else aHighlightList.insert( aHighlightList.begin(), new Rectangle( aAddRect ) ); nLastRowInRect = nRow; } // unhighlight the old selection (if any) for ( size_t i = aHighlightList.size(); i > 0; ) { Rectangle *pRect = aHighlightList[ --i ]; pDataWin->Invalidate( *pRect ); delete pRect; } aHighlightList.clear(); // unhighlight old column selection (if any) for ( long nColId = pColSel ? pColSel->FirstSelected() : BROWSER_ENDOFSELECTION; nColId != BROWSER_ENDOFSELECTION; nColId = pColSel->NextSelected() ) { Rectangle aRect( GetFieldRectPixel(nCurRow, (*pCols)[ nColId ]->GetId(), sal_False ) ); aRect.Left() -= MIN_COLUMNWIDTH; aRect.Right() += MIN_COLUMNWIDTH; aRect.Top() = 0; aRect.Bottom() = pDataWin->GetOutputSizePixel().Height(); pDataWin->Invalidate( aRect ); } bNotToggleSel = sal_False; } #ifdef _MSC_VER #pragma optimize( "", on ) #endif //------------------------------------------------------------------- void BrowseBox::DrawCursor() { sal_Bool bReallyHide = sal_False; if ( SMART_CURSOR_HIDE == bHideCursor ) { if ( !GetSelectRowCount() && !GetSelectColumnCount() ) bReallyHide = sal_True; } else if ( HARD_CURSOR_HIDE == bHideCursor ) { bReallyHide = sal_True; } bReallyHide |= !bSelectionIsVisible || !IsUpdateMode() || bScrolling || nCurRow < 0; if (PaintCursorIfHiddenOnce()) bReallyHide |= ( GetCursorHideCount() > 1 ); else bReallyHide |= ( GetCursorHideCount() > 0 ); // no cursor on handle column if ( nCurColId == HandleColumnId ) nCurColId = GetColumnId(1); // calculate cursor rectangle Rectangle aCursor; if ( bColumnCursor ) { aCursor = GetFieldRectPixel( nCurRow, nCurColId, sal_False ); aCursor.Left() -= MIN_COLUMNWIDTH; aCursor.Right() += 1; aCursor.Bottom() += 1; } else aCursor = Rectangle( Point( ( !pCols->empty() && (*pCols)[ 0 ]->GetId() == 0 ) ? (*pCols)[ 0 ]->Width() : 0, (nCurRow - nTopRow) * GetDataRowHeight() + 1 ), Size( pDataWin->GetOutputSizePixel().Width() + 1, GetDataRowHeight() - 2 ) ); if ( bHLines ) { if ( !bMultiSelection ) --aCursor.Top(); --aCursor.Bottom(); } if (m_aCursorColor == COL_TRANSPARENT) { // on these platforms, the StarView focus works correctly if ( bReallyHide ) ((Control*)pDataWin)->HideFocus(); else ((Control*)pDataWin)->ShowFocus( aCursor ); } else { Color rCol = bReallyHide ? pDataWin->GetFillColor() : m_aCursorColor; Color aOldFillColor = pDataWin->GetFillColor(); Color aOldLineColor = pDataWin->GetLineColor(); pDataWin->SetFillColor(); pDataWin->SetLineColor( rCol ); pDataWin->DrawRect( aCursor ); pDataWin->SetLineColor( aOldLineColor ); pDataWin->SetFillColor( aOldFillColor ); } } //------------------------------------------------------------------- sal_uLong BrowseBox::GetColumnWidth( sal_uInt16 nId ) const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); sal_uInt16 nItemPos = GetColumnPos( nId ); if ( nItemPos >= pCols->size() ) return 0; return (*pCols)[ nItemPos ]->Width(); } //------------------------------------------------------------------- sal_uInt16 BrowseBox::GetColumnId( sal_uInt16 nPos ) const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( nPos >= pCols->size() ) return BROWSER_INVALIDID; return (*pCols)[ nPos ]->GetId(); } //------------------------------------------------------------------- sal_uInt16 BrowseBox::GetColumnPos( sal_uInt16 nId ) const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); for ( sal_uInt16 nPos = 0; nPos < pCols->size(); ++nPos ) if ( (*pCols)[ nPos ]->GetId() == nId ) return nPos; return BROWSER_INVALIDID; } //------------------------------------------------------------------- sal_Bool BrowseBox::IsFrozen( sal_uInt16 nColumnId ) const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); for ( size_t nPos = 0; nPos < pCols->size(); ++nPos ) if ( (*pCols)[ nPos ]->GetId() == nColumnId ) return (*pCols)[ nPos ]->IsFrozen(); return sal_False; } //------------------------------------------------------------------- void BrowseBox::ExpandRowSelection( const BrowserMouseEvent& rEvt ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); DoHideCursor( "ExpandRowSelection" ); // expand the last selection if ( bMultiSelection ) { Range aJustifiedRange( aSelRange ); aJustifiedRange.Justify(); sal_Bool bSelectThis = ( bSelect != aJustifiedRange.IsInside( rEvt.GetRow() ) ); if ( aJustifiedRange.IsInside( rEvt.GetRow() ) ) { // down and up while ( rEvt.GetRow() < aSelRange.Max() ) { // ZTC/Mac bug - don't put these statements together! SelectRow( aSelRange.Max(), bSelectThis, sal_True ); --aSelRange.Max(); } while ( rEvt.GetRow() > aSelRange.Max() ) { // ZTC/Mac bug - don't put these statements together! SelectRow( aSelRange.Max(), bSelectThis, sal_True ); ++aSelRange.Max(); } } else { // up and down sal_Bool bOldSelecting = bSelecting; bSelecting = sal_True; while ( rEvt.GetRow() < aSelRange.Max() ) { // ZTC/Mac bug - don't put these statements together! --aSelRange.Max(); if ( !IsRowSelected( aSelRange.Max() ) ) { SelectRow( aSelRange.Max(), bSelectThis, sal_True ); bSelect = sal_True; } } while ( rEvt.GetRow() > aSelRange.Max() ) { // ZTC/Mac bug - don't put these statements together! ++aSelRange.Max(); if ( !IsRowSelected( aSelRange.Max() ) ) { SelectRow( aSelRange.Max(), bSelectThis, sal_True ); bSelect = sal_True; } } bSelecting = bOldSelecting; if ( bSelect ) Select(); } } else if ( !bMultiSelection || !IsRowSelected( rEvt.GetRow() ) ) SelectRow( rEvt.GetRow(), sal_True ); GoToRow( rEvt.GetRow(), sal_False ); DoShowCursor( "ExpandRowSelection" ); } //------------------------------------------------------------------- void BrowseBox::Resize() { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( !bBootstrapped && IsReallyVisible() ) BrowseBox::StateChanged( STATE_CHANGE_INITSHOW ); if ( pCols->empty() ) { getDataWindow()->bResizeOnPaint = sal_True; return; } getDataWindow()->bResizeOnPaint = sal_False; // calc the size of the scrollbars // (we can't ask the scrollbars for their widths cause if we're zoomed they still have to be // resized - which is done in UpdateScrollbars) sal_uLong nSBSize = GetSettings().GetStyleSettings().GetScrollBarSize(); if (IsZoom()) nSBSize = (sal_uLong)(nSBSize * (double)GetZoom()); DoHideCursor( "Resize" ); sal_uInt16 nOldVisibleRows = 0; //fdo#42694, post #i111125# GetDataRowHeight() can be 0 if (GetDataRowHeight()) nOldVisibleRows = (sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1); // did we need a horizontal scroll bar or is there a Control Area? if ( !getDataWindow()->bNoHScroll && ( ( pCols->size() - FrozenColCount() ) > 1 ) ) aHScroll.Show(); else aHScroll.Hide(); // calculate the size of the data window long nDataHeight = GetOutputSizePixel().Height() - GetTitleHeight(); if ( aHScroll.IsVisible() || ( nControlAreaWidth != USHRT_MAX ) ) nDataHeight -= nSBSize; long nDataWidth = GetOutputSizePixel().Width(); if ( pVScroll->IsVisible() ) nDataWidth -= nSBSize; // adjust position and size of data window pDataWin->SetPosSizePixel( Point( 0, GetTitleHeight() ), Size( nDataWidth, nDataHeight ) ); sal_uInt16 nVisibleRows = 0; if (GetDataRowHeight()) nVisibleRows = (sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1); // TopRow is unchanged, but the number of visible lines has changed. if ( nVisibleRows != nOldVisibleRows ) VisibleRowsChanged(nTopRow, nVisibleRows); UpdateScrollbars(); // Control-Area Rectangle aInvalidArea( GetControlArea() ); aInvalidArea.Right() = GetOutputSizePixel().Width(); aInvalidArea.Left() = 0; Invalidate( aInvalidArea ); // external header-bar HeaderBar* pHeaderBar = getDataWindow()->pHeaderBar; if ( pHeaderBar ) { // take the handle column into account BrowserColumn *pFirstCol = (*pCols)[ 0 ]; long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width(); pHeaderBar->SetPosSizePixel( Point( nOfsX, 0 ), Size( GetOutputSizePixel().Width() - nOfsX, GetTitleHeight() ) ); } AutoSizeLastColumn(); // adjust last column width DoShowCursor( "Resize" ); } //------------------------------------------------------------------- void BrowseBox::Paint( const Rectangle& rRect ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); // initializations if ( !bBootstrapped && IsReallyVisible() ) BrowseBox::StateChanged( STATE_CHANGE_INITSHOW ); if ( pCols->empty() ) return; BrowserColumn *pFirstCol = (*pCols)[ 0 ]; sal_Bool bHandleCol = pFirstCol && pFirstCol->GetId() == 0; sal_Bool bHeaderBar = getDataWindow()->pHeaderBar != NULL; // draw delimitational lines if ( !getDataWindow()->bNoHScroll ) DrawLine( Point( 0, aHScroll.GetPosPixel().Y() ), Point( GetOutputSizePixel().Width(), aHScroll.GetPosPixel().Y() ) ); if ( nTitleLines ) { if ( !bHeaderBar ) DrawLine( Point( 0, GetTitleHeight() - 1 ), Point( GetOutputSizePixel().Width(), GetTitleHeight() - 1 ) ); else if ( bHandleCol ) DrawLine( Point( 0, GetTitleHeight() - 1 ), Point( pFirstCol->Width(), GetTitleHeight() - 1 ) ); } // Title Bar // If there is a handle column and if the header bar is available, only // take the HandleColumn into account if ( nTitleLines && (!bHeaderBar || bHandleCol) ) { // iterate through columns to redraw long nX = 0; size_t nCol; for ( nCol = 0; nCol < pCols->size() && nX < rRect.Right(); ++nCol ) { // skip invisible columns between frozen and scrollable area if ( nCol < nFirstCol && !(*pCols)[ nCol ]->IsFrozen() ) nCol = nFirstCol; // only the handle column? if (bHeaderBar && bHandleCol && nCol > 0) break; BrowserColumn *pCol = (*pCols)[ nCol ]; // draw the column and increment position if ( pCol->Width() > 4 ) { ButtonFrame aButtonFrame( Point( nX, 0 ), Size( pCol->Width()-1, GetTitleHeight()-1 ), pCol->Title(), sal_False, sal_False, !IsEnabled()); aButtonFrame.Draw( *this ); DrawLine( Point( nX + pCol->Width() - 1, 0 ), Point( nX + pCol->Width() - 1, GetTitleHeight()-1 ) ); } else { Color aOldFillColor = GetFillColor(); SetFillColor( Color( COL_BLACK ) ); DrawRect( Rectangle( Point( nX, 0 ), Size( pCol->Width(), GetTitleHeight() - 1 ) ) ); SetFillColor( aOldFillColor ); } // skip column nX += pCol->Width(); } // retouching if ( !bHeaderBar && nCol == pCols->size() ) { const StyleSettings &rSettings = GetSettings().GetStyleSettings(); Color aColFace( rSettings.GetFaceColor() ); Color aOldFillColor = GetFillColor(); Color aOldLineColor = GetLineColor(); SetFillColor( aColFace ); SetLineColor( aColFace ); DrawRect( Rectangle( Point( nX, 0 ), Point( rRect.Right(), GetTitleHeight() - 2 ) ) ); SetFillColor( aOldFillColor); SetLineColor( aOldLineColor); } } } //------------------------------------------------------------------- void BrowseBox::PaintRow( OutputDevice&, const Rectangle& ) { } //------------------------------------------------------------------- void BrowseBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) { sal_Bool bDrawSelection = (nFlags & WINDOW_DRAW_NOSELECTION) == 0; // we need pixel coordinates Size aRealSize = pDev->LogicToPixel(rSize); Point aRealPos = pDev->LogicToPixel(rPos); if ((rSize.Width() < 3) || (rSize.Height() < 3)) // we want to have two pixels frame ... return; Font aFont = GetDataWindow().GetDrawPixelFont( pDev ); // the 'normal' painting uses always the data window as device to output to, so we have to calc the new font // relative to the data wins current settings pDev->Push(); pDev->SetMapMode(); pDev->SetFont( aFont ); // draw a frame const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); pDev->SetLineColor(rStyleSettings.GetDarkShadowColor()); pDev->DrawLine(Point(aRealPos.X(), aRealPos.Y()), Point(aRealPos.X(), aRealPos.Y() + aRealSize.Height() - 1)); pDev->DrawLine(Point(aRealPos.X(), aRealPos.Y()), Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y())); pDev->SetLineColor(rStyleSettings.GetShadowColor()); pDev->DrawLine(Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + 1), Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + aRealSize.Height() - 1)); pDev->DrawLine(Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + aRealSize.Height() - 1), Point(aRealPos.X() + 1, aRealPos.Y() + aRealSize.Height() - 1)); HeaderBar* pBar = getDataWindow()->pHeaderBar; // we're drawing onto a foreign device, so we have to fake the DataRowHeight for the subsequent ImplPaintData // (as it is based on the settings of our data window, not the foreign device) if (!nDataRowHeight) ImpGetDataRowHeight(); long nHeightLogic = PixelToLogic(Size(0, nDataRowHeight), MAP_10TH_MM).Height(); long nForeignHeightPixel = pDev->LogicToPixel(Size(0, nHeightLogic), MAP_10TH_MM).Height(); long nOriginalHeight = nDataRowHeight; nDataRowHeight = nForeignHeightPixel; // this counts for the column widths, too size_t nPos; for ( nPos = 0; nPos < pCols->size(); ++nPos ) { BrowserColumn* pCurrent = (*pCols)[ nPos ]; long nWidthLogic = PixelToLogic(Size(pCurrent->Width(), 0), MAP_10TH_MM).Width(); long nForeignWidthPixel = pDev->LogicToPixel(Size(nWidthLogic, 0), MAP_10TH_MM).Width(); pCurrent->SetWidth(nForeignWidthPixel, GetZoom()); if ( pBar ) pBar->SetItemSize( pCurrent->GetId(), pCurrent->Width() ); } // a smaller area for the content ++aRealPos.X(); ++aRealPos.Y(); aRealSize.Width() -= 2; aRealSize.Height() -= 2; // let the header bar draw itself if ( pBar ) { // the title height with respect to the font set for the given device long nTitleHeight = PixelToLogic(Size(0, GetTitleHeight()), MAP_10TH_MM).Height(); nTitleHeight = pDev->LogicToPixel(Size(0, nTitleHeight), MAP_10TH_MM).Height(); BrowserColumn* pFirstCol = !pCols->empty() ? (*pCols)[ 0 ] : NULL; Point aHeaderPos(pFirstCol && (pFirstCol->GetId() == 0) ? pFirstCol->Width() : 0, 0); Size aHeaderSize(aRealSize.Width() - aHeaderPos.X(), nTitleHeight); aHeaderPos += aRealPos; // do this before converting to logics ! // the header's draw expects logic coordinates, again aHeaderPos = pDev->PixelToLogic(aHeaderPos); aHeaderSize = pDev->PixelToLogic(aHeaderSize); pBar->Draw(pDev, aHeaderPos, aHeaderSize, nFlags); // draw the "upper left cell" (the intersection between the header bar and the handle column) if (( pFirstCol->GetId() == 0 ) && ( pFirstCol->Width() > 4 )) { ButtonFrame aButtonFrame( aRealPos, Size( pFirstCol->Width()-1, nTitleHeight-1 ), pFirstCol->Title(), sal_False, sal_False, !IsEnabled()); aButtonFrame.Draw( *pDev ); pDev->Push( PUSH_LINECOLOR ); pDev->SetLineColor( Color( COL_BLACK ) ); pDev->DrawLine( Point( aRealPos.X(), aRealPos.Y() + nTitleHeight-1 ), Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() + nTitleHeight-1 ) ); pDev->DrawLine( Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() ), Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() + nTitleHeight-1 ) ); pDev->Pop(); } aRealPos.Y() += aHeaderSize.Height(); aRealSize.Height() -= aHeaderSize.Height(); } // draw our own content (with clipping) Region aRegion(Rectangle(aRealPos, aRealSize)); pDev->SetClipRegion( pDev->PixelToLogic( aRegion ) ); // do we have to paint the background sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && GetDataWindow().IsControlBackground(); if ( bBackground ) { Rectangle aRect( aRealPos, aRealSize ); pDev->SetFillColor( GetDataWindow().GetControlBackground() ); pDev->DrawRect( aRect ); } ImplPaintData( *pDev, Rectangle( aRealPos, aRealSize ), sal_True, bDrawSelection ); // restore the column widths/data row height nDataRowHeight = nOriginalHeight; for ( nPos = 0; nPos < pCols->size(); ++nPos ) { BrowserColumn* pCurrent = (*pCols)[ nPos ]; long nForeignWidthLogic = pDev->PixelToLogic(Size(pCurrent->Width(), 0), MAP_10TH_MM).Width(); long nWidthPixel = LogicToPixel(Size(nForeignWidthLogic, 0), MAP_10TH_MM).Width(); pCurrent->SetWidth(nWidthPixel, GetZoom()); if ( pBar ) pBar->SetItemSize( pCurrent->GetId(), pCurrent->Width() ); } pDev->Pop(); } //------------------------------------------------------------------- void BrowseBox::ImplPaintData(OutputDevice& _rOut, const Rectangle& _rRect, sal_Bool _bForeignDevice, sal_Bool _bDrawSelections) { Point aOverallAreaPos = _bForeignDevice ? _rRect.TopLeft() : Point(0,0); Size aOverallAreaSize = _bForeignDevice ? _rRect.GetSize() : GetDataWindow().GetOutputSizePixel(); Point aOverallAreaBRPos = _bForeignDevice ? _rRect.BottomRight() : Point( aOverallAreaSize.Width(), aOverallAreaSize.Height() ); long nDataRowHeigt = GetDataRowHeight(); // compute relative rows to redraw sal_uLong nRelTopRow = 0; sal_uLong nRelBottomRow = aOverallAreaSize.Height(); if (!_bForeignDevice && nDataRowHeigt) { nRelTopRow = ((sal_uLong)_rRect.Top() / nDataRowHeigt); nRelBottomRow = (sal_uLong)(_rRect.Bottom()) / nDataRowHeigt; } // cache frequently used values Point aPos( aOverallAreaPos.X(), nRelTopRow * nDataRowHeigt + aOverallAreaPos.Y() ); _rOut.SetLineColor( Color( COL_WHITE ) ); const AllSettings& rAllSets = _rOut.GetSettings(); const StyleSettings &rSettings = rAllSets.GetStyleSettings(); const Color &rHighlightTextColor = rSettings.GetHighlightTextColor(); const Color &rHighlightFillColor = rSettings.GetHighlightColor(); Color aOldTextColor = _rOut.GetTextColor(); Color aOldFillColor = _rOut.GetFillColor(); Color aOldLineColor = _rOut.GetLineColor(); long nHLineX = 0 == (*pCols)[ 0 ]->GetId() ? (*pCols)[ 0 ]->Width() : 0; nHLineX += aOverallAreaPos.X(); Color aDelimiterLineColor( ::svtools::ColorConfig().GetColorValue( ::svtools::CALCGRID ).nColor ); // redraw the invalid fields for ( sal_uLong nRelRow = nRelTopRow; nRelRow <= nRelBottomRow && (sal_uLong)nTopRow+nRelRow < (sal_uLong)nRowCount; ++nRelRow, aPos.Y() += nDataRowHeigt ) { // get row // check valid area, to be on the safe side: DBG_ASSERT( (sal_uInt16)(nTopRow+nRelRow) < nRowCount, "BrowseBox::ImplPaintData: invalid seek" ); if ( (nTopRow+long(nRelRow)) < 0 || (sal_uInt16)(nTopRow+nRelRow) >= nRowCount ) continue; // prepare row sal_uLong nRow = nTopRow+nRelRow; if ( !SeekRow( nRow) ) { OSL_FAIL("BrowseBox::ImplPaintData: SeekRow failed"); } _rOut.SetClipRegion(); aPos.X() = aOverallAreaPos.X(); // #73325# don't paint the row outside the painting rectangle (DG) // prepare auto-highlight Rectangle aRowRect( Point( _rRect.TopLeft().X(), aPos.Y() ), Size( _rRect.GetSize().Width(), nDataRowHeigt ) ); PaintRow( _rOut, aRowRect ); sal_Bool bRowSelected = _bDrawSelections && !bHideSelect && IsRowSelected( nRow ); if ( bRowSelected ) { _rOut.SetTextColor( rHighlightTextColor ); _rOut.SetFillColor( rHighlightFillColor ); _rOut.SetLineColor(); _rOut.DrawRect( aRowRect ); } // iterate through columns to redraw size_t nCol; for ( nCol = 0; nCol < pCols->size(); ++nCol ) { // get column BrowserColumn *pCol = (*pCols)[ nCol ]; // at end of invalid area if ( aPos.X() >= _rRect.Right() ) break; // skip invisible colums between frozen and scrollable area if ( nCol < nFirstCol && !pCol->IsFrozen() ) { nCol = nFirstCol; pCol = (nCol < pCols->size() ) ? (*pCols)[ nCol ] : NULL; if (!pCol) { // FS - 21.05.99 - 66325 // actually this has been fixed elsewhere (in the right place), // but let's make sure... OSL_FAIL("BrowseBox::PaintData : nFirstCol is probably invalid !"); break; } } // prepare Column-AutoHighlight sal_Bool bColAutoHighlight = _bDrawSelections && bColumnCursor && IsColumnSelected( pCol->GetId() ); if ( bColAutoHighlight ) { _rOut.SetClipRegion(); _rOut.SetTextColor( rHighlightTextColor ); _rOut.SetFillColor( rHighlightFillColor ); _rOut.SetLineColor(); Rectangle aFieldRect( aPos, Size( pCol->Width(), nDataRowHeigt ) ); _rOut.DrawRect( aFieldRect ); } if (!m_bFocusOnlyCursor && (pCol->GetId() == GetCurColumnId()) && (nRow == (sal_uLong)GetCurRow())) DrawCursor(); // draw a single field. // else something is drawn to, e.g. handle column if (pCol->Width()) { // clip the column's output to the field area if (_bForeignDevice) { // (not necessary if painting onto the data window) Size aFieldSize(pCol->Width(), nDataRowHeigt); if (aPos.X() + aFieldSize.Width() > aOverallAreaBRPos.X()) aFieldSize.Width() = aOverallAreaBRPos.X() - aPos.X(); if (aPos.Y() + aFieldSize.Height() > aOverallAreaBRPos.Y() + 1) { // for non-handle cols we don't clip vertically : we just don't draw the cell if the line isn't completely visible if (pCol->GetId() != 0) continue; aFieldSize.Height() = aOverallAreaBRPos.Y() + 1 - aPos.Y(); } Region aClipToField(Rectangle(aPos, aFieldSize)); _rOut.SetClipRegion(aClipToField); } pCol->Draw( *this, _rOut, aPos, sal_False ); if (_bForeignDevice) _rOut.SetClipRegion(); } // reset Column-auto-highlight if ( bColAutoHighlight ) { _rOut.SetTextColor( aOldTextColor ); _rOut.SetFillColor( aOldFillColor ); _rOut.SetLineColor( aOldLineColor ); } // skip column aPos.X() += pCol->Width(); } // reset auto-highlight if ( bRowSelected ) { _rOut.SetTextColor( aOldTextColor ); _rOut.SetFillColor( aOldFillColor ); _rOut.SetLineColor( aOldLineColor ); } if ( bHLines ) { // draw horizontal delimitation lines _rOut.SetClipRegion(); _rOut.Push( PUSH_LINECOLOR ); _rOut.SetLineColor( aDelimiterLineColor ); long nY = aPos.Y() + nDataRowHeigt - 1; if (nY <= aOverallAreaBRPos.Y()) _rOut.DrawLine( Point( nHLineX, nY ), Point( bVLines ? std::min(long(long(aPos.X()) - 1), aOverallAreaBRPos.X()) : aOverallAreaBRPos.X(), nY ) ); _rOut.Pop(); } } if (aPos.Y() > aOverallAreaBRPos.Y() + 1) aPos.Y() = aOverallAreaBRPos.Y() + 1; // needed for some of the following drawing // retouching _rOut.SetClipRegion(); aOldLineColor = _rOut.GetLineColor(); aOldFillColor = _rOut.GetFillColor(); _rOut.SetFillColor( rSettings.GetFaceColor() ); if ( !pCols->empty() && ( (*pCols)[ 0 ]->GetId() == 0 ) && ( aPos.Y() <= _rRect.Bottom() ) ) { // fill rectangle gray below handle column // DG: fill it only until the end of the drawing rect and not to the end, as this may overpaint handle columns _rOut.SetLineColor( Color( COL_BLACK ) ); _rOut.DrawRect( Rectangle( Point( aOverallAreaPos.X() - 1, aPos.Y() - 1 ), Point( aOverallAreaPos.X() + (*pCols)[ 0 ]->Width() - 1, _rRect.Bottom() + 1) ) ); } _rOut.SetFillColor( aOldFillColor ); // draw vertical delimitational line between frozen and scrollable cols _rOut.SetLineColor( COL_BLACK ); long nFrozenWidth = GetFrozenWidth()-1; _rOut.DrawLine( Point( aOverallAreaPos.X() + nFrozenWidth, aPos.Y() ), Point( aOverallAreaPos.X() + nFrozenWidth, bHLines ? aPos.Y() - 1 : aOverallAreaBRPos.Y() ) ); // draw vertical delimitational lines? if ( bVLines ) { _rOut.SetLineColor( aDelimiterLineColor ); Point aVertPos( aOverallAreaPos.X() - 1, aOverallAreaPos.Y() ); long nDeltaY = aOverallAreaBRPos.Y(); for ( size_t nCol = 0; nCol < pCols->size(); ++nCol ) { // get column BrowserColumn *pCol = (*pCols)[ nCol ]; // skip invisible columns between frozen and scrollable area if ( nCol < nFirstCol && !pCol->IsFrozen() ) { nCol = nFirstCol; pCol = (*pCols)[ nCol ]; } // skip column aVertPos.X() += pCol->Width(); // at end of invalid area // invalid area is first reached when X > Right // and not >= if ( aVertPos.X() > _rRect.Right() ) break; // draw a single line if ( pCol->GetId() != 0 ) _rOut.DrawLine( aVertPos, Point( aVertPos.X(), bHLines ? aPos.Y() - 1 : aPos.Y() + nDeltaY ) ); } } _rOut.SetLineColor( aOldLineColor ); } //------------------------------------------------------------------- void BrowseBox::PaintData( Window& rWin, const Rectangle& rRect ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( !bBootstrapped && IsReallyVisible() ) BrowseBox::StateChanged( STATE_CHANGE_INITSHOW ); // initializations if ( !pCols || pCols->empty() || !rWin.IsUpdateMode() ) return; if ( getDataWindow()->bResizeOnPaint ) Resize(); // MI: who was that? Window::Update(); ImplPaintData(rWin, rRect, sal_False, sal_True); } //------------------------------------------------------------------- void BrowseBox::UpdateScrollbars() { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( !bBootstrapped || !IsUpdateMode() ) return; // protect against recursion BrowserDataWin *pBDW = (BrowserDataWin*) pDataWin; if ( pBDW->bInUpdateScrollbars ) { pBDW->bHadRecursion = sal_True; return; } pBDW->bInUpdateScrollbars = sal_True; // the size of the corner window (and the width of the VSB/height of the HSB) sal_uLong nCornerSize = GetSettings().GetStyleSettings().GetScrollBarSize(); if (IsZoom()) nCornerSize = (sal_uLong)(nCornerSize * (double)GetZoom()); sal_Bool bNeedsVScroll = sal_False; long nMaxRows = 0; if (GetDataRowHeight()) { // needs VScroll? nMaxRows = (pDataWin->GetSizePixel().Height()) / GetDataRowHeight(); bNeedsVScroll = getDataWindow()->bAutoVScroll ? nTopRow || ( nRowCount > nMaxRows ) : !getDataWindow()->bNoVScroll; } Size aDataWinSize = pDataWin->GetSizePixel(); if ( !bNeedsVScroll ) { if ( pVScroll->IsVisible() ) { pVScroll->Hide(); Size aNewSize( aDataWinSize ); aNewSize.Width() = GetOutputSizePixel().Width(); aDataWinSize = aNewSize; } } else if ( !pVScroll->IsVisible() ) { Size aNewSize( aDataWinSize ); aNewSize.Width() = GetOutputSizePixel().Width() - nCornerSize; aDataWinSize = aNewSize; } // needs HScroll? sal_uLong nLastCol = GetColumnAtXPosPixel( aDataWinSize.Width() - 1 ); sal_uInt16 nFrozenCols = FrozenColCount(); sal_Bool bNeedsHScroll = getDataWindow()->bAutoHScroll ? ( nFirstCol > nFrozenCols ) || ( nLastCol <= pCols->size() ) : !getDataWindow()->bNoHScroll; if ( !bNeedsHScroll ) { if ( aHScroll.IsVisible() ) { aHScroll.Hide(); } aDataWinSize.Height() = GetOutputSizePixel().Height() - GetTitleHeight(); if ( nControlAreaWidth != USHRT_MAX ) aDataWinSize.Height() -= nCornerSize; } else if ( !aHScroll.IsVisible() ) { Size aNewSize( aDataWinSize ); aNewSize.Height() = GetOutputSizePixel().Height() - GetTitleHeight() - nCornerSize; aDataWinSize = aNewSize; } // adjust position and Width of horizontal scrollbar sal_uLong nHScrX = nControlAreaWidth == USHRT_MAX ? 0 : nControlAreaWidth; aHScroll.SetPosSizePixel( Point( nHScrX, GetOutputSizePixel().Height() - nCornerSize ), Size( aDataWinSize.Width() - nHScrX, nCornerSize ) ); // total scrollable columns short nScrollCols = short(pCols->size()) - (short)nFrozenCols; // visible columns short nVisibleHSize = nLastCol == BROWSER_INVALIDID ? (short)( pCols->size() - nFirstCol ) : (short)( nLastCol - nFirstCol ); short nRange = Max( nScrollCols, (short)0 ); aHScroll.SetVisibleSize( nVisibleHSize ); aHScroll.SetRange( Range( 0, nRange )); if ( bNeedsHScroll && !aHScroll.IsVisible() ) aHScroll.Show(); // adjust position and height of vertical scrollbar pVScroll->SetPageSize( nMaxRows ); if ( nTopRow > nRowCount ) { nTopRow = nRowCount - 1; OSL_FAIL("BrowseBox: nTopRow > nRowCount"); } if ( pVScroll->GetThumbPos() != nTopRow ) pVScroll->SetThumbPos( nTopRow ); long nVisibleSize = Min( Min( nRowCount, nMaxRows ), long(nRowCount-nTopRow) ); pVScroll->SetVisibleSize( nVisibleSize ? nVisibleSize : 1 ); pVScroll->SetRange( Range( 0, nRowCount ) ); pVScroll->SetPosSizePixel( Point( aDataWinSize.Width(), GetTitleHeight() ), Size( nCornerSize, aDataWinSize.Height()) ); long nLclDataRowHeight = GetDataRowHeight(); if ( nLclDataRowHeight > 0 && nRowCount < long( aDataWinSize.Height() / nLclDataRowHeight ) ) ScrollRows( -nTopRow ); if ( bNeedsVScroll && !pVScroll->IsVisible() ) pVScroll->Show(); pDataWin->SetPosSizePixel( Point( 0, GetTitleHeight() ), aDataWinSize ); // needs corner-window? // (do that AFTER positioning BOTH scrollbars) sal_uLong nActualCorderWidth = 0; if (aHScroll.IsVisible() && pVScroll && pVScroll->IsVisible() ) { // if we have both scrollbars, the corner window fills the point of intersection of these two nActualCorderWidth = nCornerSize; } else if ( !aHScroll.IsVisible() && ( nControlAreaWidth != USHRT_MAX ) ) { // if we have no horizontal scrollbar, but a control area, we need the corner window to // fill the space between the control are and the right border nActualCorderWidth = GetOutputSizePixel().Width() - nControlAreaWidth; } if ( nActualCorderWidth ) { if ( !getDataWindow()->pCornerWin ) getDataWindow()->pCornerWin = new ScrollBarBox( this, 0 ); getDataWindow()->pCornerWin->SetPosSizePixel( Point( GetOutputSizePixel().Width() - nActualCorderWidth, aHScroll.GetPosPixel().Y() ), Size( nActualCorderWidth, nCornerSize ) ); getDataWindow()->pCornerWin->Show(); } else DELETEZ( getDataWindow()->pCornerWin ); // scroll headerbar, if necessary if ( getDataWindow()->pHeaderBar ) { long nWidth = 0; for ( size_t nCol = 0; nCol < pCols->size() && nCol < nFirstCol; ++nCol ) { // not the handle column if ( (*pCols)[ nCol ]->GetId() ) nWidth += (*pCols)[ nCol ]->Width(); } getDataWindow()->pHeaderBar->SetOffset( nWidth ); } pBDW->bInUpdateScrollbars = sal_False; if ( pBDW->bHadRecursion ) { pBDW->bHadRecursion = sal_False; UpdateScrollbars(); } } //------------------------------------------------------------------- void BrowseBox::SetUpdateMode( sal_Bool bUpdate ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); sal_Bool bWasUpdate = IsUpdateMode(); if ( bWasUpdate == bUpdate ) return; Control::SetUpdateMode( bUpdate ); // If WB_CLIPCHILDREN is st at the BrowseBox (to minimize flicker), // the data window is not invalidated by SetUpdateMode. if( bUpdate ) getDataWindow()->Invalidate(); getDataWindow()->SetUpdateMode( bUpdate ); if ( bUpdate ) { if ( bBootstrapped ) { UpdateScrollbars(); AutoSizeLastColumn(); } DoShowCursor( "SetUpdateMode" ); } else DoHideCursor( "SetUpdateMode" ); } //------------------------------------------------------------------- sal_Bool BrowseBox::GetUpdateMode() const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); return getDataWindow()->IsUpdateMode(); } //------------------------------------------------------------------- long BrowseBox::GetFrozenWidth() const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); long nWidth = 0; for ( size_t nCol = 0; nCol < pCols->size() && (*pCols)[ nCol ]->IsFrozen(); ++nCol ) nWidth += (*pCols)[ nCol ]->Width(); return nWidth; } //------------------------------------------------------------------- void BrowseBox::ColumnInserted( sal_uInt16 nPos ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( pColSel ) pColSel->Insert( nPos ); UpdateScrollbars(); } //------------------------------------------------------------------- sal_uInt16 BrowseBox::FrozenColCount() const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); sal_uInt16 nCol; for ( nCol = 0; nCol < pCols->size() && (*pCols)[ nCol ]->IsFrozen(); ++nCol ) /* empty loop */; return nCol; } //------------------------------------------------------------------- IMPL_LINK(BrowseBox,ScrollHdl,ScrollBar*,pBar) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( pBar->GetDelta() == 0 ) return 0; if ( pBar->GetDelta() < 0 && getDataWindow()->bNoScrollBack ) { UpdateScrollbars(); return 0; } if ( pBar == &aHScroll ) ScrollColumns( aHScroll.GetDelta() ); if ( pBar == pVScroll ) ScrollRows( pVScroll->GetDelta() ); return 0; } //------------------------------------------------------------------- IMPL_LINK_NOARG(BrowseBox, EndScrollHdl) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( getDataWindow()->bNoScrollBack ) { EndScroll(); return 0; } return 0; } //------------------------------------------------------------------- IMPL_LINK( BrowseBox, StartDragHdl, HeaderBar*, pBar ) { pBar->SetDragSize( pDataWin->GetOutputSizePixel().Height() ); return 0; } //------------------------------------------------------------------- // usually only the first column was resized #ifdef _MSC_VER #pragma optimize("",off) #endif void BrowseBox::MouseButtonDown( const MouseEvent& rEvt ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); GrabFocus(); // only mouse events in the title-line are supported const Point &rEvtPos = rEvt.GetPosPixel(); if ( rEvtPos.Y() >= GetTitleHeight() ) return; long nX = 0; long nWidth = GetOutputSizePixel().Width(); for ( size_t nCol = 0; nCol < pCols->size() && nX < nWidth; ++nCol ) { // is this column visible? BrowserColumn *pCol = (*pCols)[ nCol ]; if ( pCol->IsFrozen() || nCol >= nFirstCol ) { // compute right end of column long nR = nX + pCol->Width() - 1; // at the end of a column (and not handle column)? if ( pCol->GetId() && Abs( nR - rEvtPos.X() ) < 2 ) { // start resizing the column bResizing = sal_True; nResizeCol = nCol; nDragX = nResizeX = rEvtPos.X(); SetPointer( Pointer( POINTER_HSPLIT ) ); CaptureMouse(); pDataWin->DrawLine( Point( nDragX, 0 ), Point( nDragX, pDataWin->GetSizePixel().Height() ) ); nMinResizeX = nX + MIN_COLUMNWIDTH; return; } else if ( nX < rEvtPos.X() && nR > rEvtPos.X() ) { MouseButtonDown( BrowserMouseEvent( this, rEvt, -1, nCol, pCol->GetId(), Rectangle() ) ); return; } nX = nR + 1; } } // event occurred out of data area if ( rEvt.IsRight() ) pDataWin->Command( CommandEvent( Point( 1, LONG_MAX ), COMMAND_CONTEXTMENU, sal_True ) ); else SetNoSelection(); } #ifdef _MSC_VER #pragma optimize("",on) #endif //------------------------------------------------------------------- void BrowseBox::MouseMove( const MouseEvent& rEvt ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); OSL_TRACE( "BrowseBox::MouseMove( MouseEvent )" ); Pointer aNewPointer; sal_uInt16 nX = 0; for ( size_t nCol = 0; nCol < pCols->size() && ( nX + (*pCols)[ nCol ]->Width() ) < sal_uInt16(GetOutputSizePixel().Width()); ++nCol ) // is this column visible? if ( (*pCols)[ nCol ]->IsFrozen() || nCol >= nFirstCol ) { // compute right end of column BrowserColumn *pCol = (*pCols)[ nCol ]; sal_uInt16 nR = (sal_uInt16)(nX + pCol->Width() - 1); // show resize-pointer? if ( bResizing || ( pCol->GetId() && Abs( ((long) nR ) - rEvt.GetPosPixel().X() ) < MIN_COLUMNWIDTH ) ) { aNewPointer = Pointer( POINTER_HSPLIT ); if ( bResizing ) { // delete old auxiliary line pDataWin->HideTracking() ; // check allowed width and new delta nDragX = Max( rEvt.GetPosPixel().X(), nMinResizeX ); long nDeltaX = nDragX - nResizeX; sal_uInt16 nId = GetColumnId(nResizeCol); sal_uLong nOldWidth = GetColumnWidth(nId); nDragX = QueryColumnResize( GetColumnId(nResizeCol), nOldWidth + nDeltaX ) + nResizeX - nOldWidth; // draw new auxiliary line pDataWin->ShowTracking( Rectangle( Point( nDragX, 0 ), Size( 1, pDataWin->GetSizePixel().Height() ) ), SHOWTRACK_SPLIT|SHOWTRACK_WINDOW ); } } nX = nR + 1; } SetPointer( aNewPointer ); } //------------------------------------------------------------------- void BrowseBox::MouseButtonUp( const MouseEvent & rEvt ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( bResizing ) { // delete auxiliary line pDataWin->HideTracking(); // width changed? nDragX = Max( rEvt.GetPosPixel().X(), nMinResizeX ); if ( (nDragX - nResizeX) != (long)(*pCols)[ nResizeCol ]->Width() ) { // resize column long nMaxX = pDataWin->GetSizePixel().Width(); nDragX = Min( nDragX, nMaxX ); long nDeltaX = nDragX - nResizeX; sal_uInt16 nId = GetColumnId(nResizeCol); SetColumnWidth( GetColumnId(nResizeCol), GetColumnWidth(nId) + nDeltaX ); ColumnResized( nId ); } // end action SetPointer( Pointer() ); ReleaseMouse(); bResizing = sal_False; } else MouseButtonUp( BrowserMouseEvent( (BrowserDataWin*)pDataWin, MouseEvent( Point( rEvt.GetPosPixel().X(), rEvt.GetPosPixel().Y() - pDataWin->GetPosPixel().Y() ), rEvt.GetClicks(), rEvt.GetMode(), rEvt.GetButtons(), rEvt.GetModifier() ) ) ); } //------------------------------------------------------------------- sal_Bool bExtendedMode = sal_False; sal_Bool bFieldMode = sal_False; void BrowseBox::MouseButtonDown( const BrowserMouseEvent& rEvt ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); GrabFocus(); // adjust selection while and after double-click if ( rEvt.GetClicks() == 2 ) { SetNoSelection(); if ( rEvt.GetRow() >= 0 ) { GoToRow( rEvt.GetRow() ); SelectRow( rEvt.GetRow(), sal_True, sal_False ); } else { if ( bColumnCursor && rEvt.GetColumn() != 0 ) { if ( rEvt.GetColumn() < pCols->size() ) SelectColumnPos( rEvt.GetColumn(), sal_True, sal_False); } } DoubleClick( rEvt ); } // selections else if ( ( rEvt.GetMode() & ( MOUSE_SELECT | MOUSE_SIMPLECLICK ) ) && ( bColumnCursor || rEvt.GetRow() >= 0 ) ) { if ( rEvt.GetClicks() == 1 ) { // initialise flags bHit = sal_False; a1stPoint = a2ndPoint = PixelToLogic( rEvt.GetPosPixel() ); // selection out of range? if ( rEvt.GetRow() >= nRowCount || rEvt.GetColumnId() == BROWSER_INVALIDID ) { SetNoSelection(); return; } // while selecting, no cursor bSelecting = sal_True; DoHideCursor( "MouseButtonDown" ); // DataRow? if ( rEvt.GetRow() >= 0 ) { // line selection? if ( rEvt.GetColumnId() == HandleColumnId || !bColumnCursor ) { if ( bMultiSelection ) { // remove column-selection, if exists if ( pColSel && pColSel->GetSelectCount() ) { ToggleSelection(); if ( bMultiSelection ) uRow.pSel->SelectAll(sal_False); else uRow.nSel = BROWSER_ENDOFSELECTION; if ( pColSel ) pColSel->SelectAll(sal_False); bSelect = sal_True; } // expanding mode? if ( rEvt.GetMode() & MOUSE_RANGESELECT ) { // select the further touched rows too bSelect = sal_True; ExpandRowSelection( rEvt ); return; } // click in the selected area? else if ( IsRowSelected( rEvt.GetRow() ) ) { // wait for Drag&Drop bHit = sal_True; bExtendedMode = MOUSE_MULTISELECT == ( rEvt.GetMode() & MOUSE_MULTISELECT ); return; } // extension mode? else if ( rEvt.GetMode() & MOUSE_MULTISELECT ) { // determine the new selection range // and selection/deselection aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() ); SelectRow( rEvt.GetRow(), !uRow.pSel->IsSelected( rEvt.GetRow() ) ); bSelect = sal_True; return; } } // select directly SetNoSelection(); GoToRow( rEvt.GetRow() ); SelectRow( rEvt.GetRow(), sal_True ); aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() ); bSelect = sal_True; } else // Column/Field-Selection { // click in selected column if ( IsColumnSelected( rEvt.GetColumn() ) || IsRowSelected( rEvt.GetRow() ) ) { bHit = sal_True; bFieldMode = sal_True; return; } SetNoSelection(); GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() ); bSelect = sal_True; } } else { if ( bMultiSelection && rEvt.GetColumnId() == HandleColumnId ) { // toggle all-selection if ( uRow.pSel->GetSelectCount() > ( GetRowCount() / 2 ) ) SetNoSelection(); else SelectAll(); } else SelectColumnId( rEvt.GetColumnId(), sal_True, sal_False ); } // turn cursor on again, if necessary bSelecting = sal_False; DoShowCursor( "MouseButtonDown" ); if ( bSelect ) Select(); } } } //------------------------------------------------------------------- void BrowseBox::MouseMove( const BrowserMouseEvent& ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); } //------------------------------------------------------------------- void BrowseBox::MouseButtonUp( const BrowserMouseEvent &rEvt ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); // D&D was possible, but did not occur if ( bHit ) { aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() ); if ( bExtendedMode ) SelectRow( rEvt.GetRow(), sal_False ); else { SetNoSelection(); if ( bFieldMode ) GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() ); else { GoToRow( rEvt.GetRow() ); SelectRow( rEvt.GetRow(), sal_True ); } } bSelect = sal_True; bExtendedMode = sal_False; bFieldMode = sal_False; bHit = sal_False; } // activate cursor if ( bSelecting ) { bSelecting = sal_False; DoShowCursor( "MouseButtonUp" ); if ( bSelect ) Select(); } } //------------------------------------------------------------------- void BrowseBox::KeyInput( const KeyEvent& rEvt ) { if ( !ProcessKey( rEvt ) ) Control::KeyInput( rEvt ); } //------------------------------------------------------------------- sal_Bool BrowseBox::ProcessKey( const KeyEvent& rEvt ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); sal_uInt16 nCode = rEvt.GetKeyCode().GetCode(); sal_Bool bShift = rEvt.GetKeyCode().IsShift(); sal_Bool bCtrl = rEvt.GetKeyCode().IsMod1(); sal_Bool bAlt = rEvt.GetKeyCode().IsMod2(); sal_uInt16 nId = BROWSER_NONE; if ( !bAlt && !bCtrl && !bShift ) { switch ( nCode ) { case KEY_DOWN: nId = BROWSER_CURSORDOWN; break; case KEY_UP: nId = BROWSER_CURSORUP; break; case KEY_HOME: nId = BROWSER_CURSORHOME; break; case KEY_END: nId = BROWSER_CURSOREND; break; case KEY_TAB: if ( !bColumnCursor ) break; case KEY_RIGHT: nId = BROWSER_CURSORRIGHT; break; case KEY_LEFT: nId = BROWSER_CURSORLEFT; break; case KEY_SPACE: nId = BROWSER_SELECT; break; } if ( BROWSER_NONE != nId ) SetNoSelection(); switch ( nCode ) { case KEY_PAGEDOWN: nId = BROWSER_CURSORPAGEDOWN; break; case KEY_PAGEUP: nId = BROWSER_CURSORPAGEUP; break; } } if ( !bAlt && !bCtrl && bShift ) switch ( nCode ) { case KEY_DOWN: nId = BROWSER_SELECTDOWN; break; case KEY_UP: nId = BROWSER_SELECTUP; break; case KEY_TAB: if ( !bColumnCursor ) break; nId = BROWSER_CURSORLEFT; break; case KEY_HOME: nId = BROWSER_SELECTHOME; break; case KEY_END: nId = BROWSER_SELECTEND; break; } if ( !bAlt && bCtrl && !bShift ) switch ( nCode ) { case KEY_DOWN: nId = BROWSER_CURSORDOWN; break; case KEY_UP: nId = BROWSER_CURSORUP; break; case KEY_PAGEDOWN: nId = BROWSER_CURSORENDOFFILE; break; case KEY_PAGEUP: nId = BROWSER_CURSORTOPOFFILE; break; case KEY_HOME: nId = BROWSER_CURSORTOPOFSCREEN; break; case KEY_END: nId = BROWSER_CURSORENDOFSCREEN; break; case KEY_SPACE: nId = BROWSER_ENHANCESELECTION; break; case KEY_LEFT: nId = BROWSER_MOVECOLUMNLEFT; break; case KEY_RIGHT: nId = BROWSER_MOVECOLUMNRIGHT; break; } if ( nId != BROWSER_NONE ) Dispatch( nId ); return nId != BROWSER_NONE; } //------------------------------------------------------------------- void BrowseBox::Dispatch( sal_uInt16 nId ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); long nRowsOnPage = pDataWin->GetSizePixel().Height() / GetDataRowHeight(); sal_Bool bDone = sal_False; switch ( nId ) { case BROWSER_SELECTCOLUMN: if ( ColCount() ) SelectColumnId( GetCurColumnId() ); break; case BROWSER_CURSORDOWN: if ( ( GetCurRow() + 1 ) < nRowCount ) bDone = GoToRow( GetCurRow() + 1, sal_False ); break; case BROWSER_CURSORUP: if ( GetCurRow() > 0 ) bDone = GoToRow( GetCurRow() - 1, sal_False ); break; case BROWSER_SELECTHOME: if ( GetRowCount() ) { DoHideCursor( "BROWSER_SELECTHOME" ); for ( long nRow = GetCurRow(); nRow >= 0; --nRow ) SelectRow( nRow ); GoToRow( 0, sal_True ); DoShowCursor( "BROWSER_SELECTHOME" ); } break; case BROWSER_SELECTEND: if ( GetRowCount() ) { DoHideCursor( "BROWSER_SELECTEND" ); long nRows = GetRowCount(); for ( long nRow = GetCurRow(); nRow < nRows; ++nRow ) SelectRow( nRow ); GoToRow( GetRowCount() - 1, sal_True ); DoShowCursor( "BROWSER_SELECTEND" ); } break; case BROWSER_SELECTDOWN: { if ( GetRowCount() && ( GetCurRow() + 1 ) < nRowCount ) { // deselect the current row, if it isn't the first // and there is no other selected row above long nRow = GetCurRow(); sal_Bool bLocalSelect = ( !IsRowSelected( nRow ) || GetSelectRowCount() == 1 || IsRowSelected( nRow - 1 ) ); SelectRow( nRow, bLocalSelect, sal_True ); bDone = GoToRow( GetCurRow() + 1 , sal_False ); if ( bDone ) SelectRow( GetCurRow(), sal_True, sal_True ); } else bDone = ScrollRows( 1 ) != 0; break; } case BROWSER_SELECTUP: if ( GetRowCount() ) { // deselect the current row, if it isn't the first // and there is no other selected row under long nRow = GetCurRow(); sal_Bool bLocalSelect = ( !IsRowSelected( nRow ) || GetSelectRowCount() == 1 || IsRowSelected( nRow + 1 ) ); SelectRow( nCurRow, bLocalSelect, sal_True ); bDone = GoToRow( nRow - 1 , sal_False ); if ( bDone ) SelectRow( GetCurRow(), sal_True, sal_True ); } break; case BROWSER_CURSORPAGEDOWN: bDone = (sal_Bool)ScrollRows( nRowsOnPage ); break; case BROWSER_CURSORPAGEUP: bDone = (sal_Bool)ScrollRows( -nRowsOnPage ); break; case BROWSER_CURSOREND: if ( bColumnCursor ) { sal_uInt16 nNewId = GetColumnId(ColCount() -1); bDone = nNewId != HandleColumnId && GoToColumnId( nNewId ); break; } case BROWSER_CURSORENDOFFILE: bDone = GoToRow( nRowCount - 1, sal_False ); break; case BROWSER_CURSORRIGHT: if ( bColumnCursor ) { sal_uInt16 nNewPos = GetColumnPos( GetCurColumnId() ) + 1; sal_uInt16 nNewId = GetColumnId( nNewPos ); if (nNewId != BROWSER_INVALIDID) // At end of row ? bDone = GoToColumnId( nNewId ); else { sal_uInt16 nColId = GetColumnId(0); if ( nColId == BROWSER_INVALIDID || nColId == HandleColumnId ) nColId = GetColumnId(1); if ( GetRowCount() ) bDone = ( nCurRow < GetRowCount() - 1 ) && GoToRowColumnId( nCurRow + 1, nColId ); else if ( ColCount() ) GoToColumnId( nColId ); } } else bDone = ScrollColumns( 1 ) != 0; break; case BROWSER_CURSORHOME: if ( bColumnCursor ) { sal_uInt16 nNewId = GetColumnId(1); bDone = (nNewId != HandleColumnId) && GoToColumnId( nNewId ); break; } case BROWSER_CURSORTOPOFFILE: bDone = GoToRow( 0, sal_False ); break; case BROWSER_CURSORLEFT: if ( bColumnCursor ) { sal_uInt16 nNewPos = GetColumnPos( GetCurColumnId() ) - 1; sal_uInt16 nNewId = GetColumnId( nNewPos ); if (nNewId != HandleColumnId) bDone = GoToColumnId( nNewId ); else { if ( GetRowCount() ) bDone = (nCurRow > 0) && GoToRowColumnId(nCurRow - 1, GetColumnId(ColCount() -1)); else if ( ColCount() ) GoToColumnId( GetColumnId(ColCount() -1) ); } } else bDone = ScrollColumns( -1 ) != 0; break; case BROWSER_ENHANCESELECTION: if ( GetRowCount() ) SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ), sal_True ); bDone = sal_True; break; case BROWSER_SELECT: if ( GetRowCount() ) SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ), sal_False ); bDone = sal_True; break; case BROWSER_MOVECOLUMNLEFT: case BROWSER_MOVECOLUMNRIGHT: { // check if column moving is allowed BrowserHeader* pHeaderBar = getDataWindow()->pHeaderBar; if ( pHeaderBar && pHeaderBar->IsDragable() ) { sal_uInt16 nColId = GetCurColumnId(); sal_Bool bColumnSelected = IsColumnSelected(nColId); sal_uInt16 nNewPos = GetColumnPos(nColId); sal_Bool bMoveAllowed = sal_False; if ( BROWSER_MOVECOLUMNLEFT == nId && nNewPos > 1 ) --nNewPos,bMoveAllowed = sal_True; else if ( BROWSER_MOVECOLUMNRIGHT == nId && nNewPos < (ColCount()-1) ) ++nNewPos,bMoveAllowed = sal_True; if ( bMoveAllowed ) { SetColumnPos( nColId, nNewPos ); ColumnMoved( nColId ); MakeFieldVisible(GetCurRow(),nColId,sal_True); if ( bColumnSelected ) SelectColumnId(nColId); } } } break; } //! return bDone; } //------------------------------------------------------------------- void BrowseBox::SetCursorColor(const Color& _rCol) { if (_rCol == m_aCursorColor) return; // ensure the cursor is hidden DoHideCursor("SetCursorColor"); if (!m_bFocusOnlyCursor) DoHideCursor("SetCursorColor - force"); m_aCursorColor = _rCol; if (!m_bFocusOnlyCursor) DoShowCursor("SetCursorColor - force"); DoShowCursor("SetCursorColor"); } // ----------------------------------------------------------------------------- Rectangle BrowseBox::calcHeaderRect(sal_Bool _bIsColumnBar,sal_Bool _bOnScreen) { Window* pParent = NULL; if ( !_bOnScreen ) pParent = GetAccessibleParentWindow(); Point aTopLeft; long nWidth; long nHeight; if ( _bIsColumnBar ) { nWidth = GetDataWindow().GetOutputSizePixel().Width(); nHeight = GetDataRowHeight(); } else { aTopLeft.Y() = GetDataRowHeight(); nWidth = GetColumnWidth(0); nHeight = GetWindowExtentsRelative( pParent ).GetHeight() - aTopLeft.Y() - GetControlArea().GetSize().B(); } aTopLeft += GetWindowExtentsRelative( pParent ).TopLeft(); return Rectangle(aTopLeft,Size(nWidth,nHeight)); } // ----------------------------------------------------------------------------- Rectangle BrowseBox::calcTableRect(sal_Bool _bOnScreen) { Window* pParent = NULL; if ( !_bOnScreen ) pParent = GetAccessibleParentWindow(); Rectangle aRect( GetWindowExtentsRelative( pParent ) ); Rectangle aRowBar = calcHeaderRect(sal_False,pParent == NULL); long nX = aRowBar.Right() - aRect.Left(); long nY = aRowBar.Top() - aRect.Top(); Size aSize(aRect.GetSize()); return Rectangle(aRowBar.TopRight(), Size(aSize.A() - nX, aSize.B() - nY - aHScroll.GetSizePixel().Height()) ); } // ----------------------------------------------------------------------------- Rectangle BrowseBox::GetFieldRectPixelAbs( sal_Int32 _nRowId,sal_uInt16 _nColId, sal_Bool /*_bIsHeader*/, sal_Bool _bOnScreen ) { Window* pParent = NULL; if ( !_bOnScreen ) pParent = GetAccessibleParentWindow(); Rectangle aRect = GetFieldRectPixel(_nRowId,_nColId,_bOnScreen); Point aTopLeft = aRect.TopLeft(); aTopLeft += GetWindowExtentsRelative( pParent ).TopLeft(); return Rectangle(aTopLeft,aRect.GetSize()); } // ------------------------------------------------------------------------- EOF /* vim:set shiftwidth=4 softtabstop=4 expandtab: */