/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" #include #include #include "datwin.hxx" #include #include #ifndef GCC #endif #include #include using namespace ::com::sun::star::datatransfer; #define getDataWindow() ((BrowserDataWin*)pDataWin) //=================================================================== DBG_NAMEEX(BrowseBox) //=================================================================== extern const char* BrowseBoxCheckInvariants( const void * pVoid ); DECLARE_LIST( BrowserColumns, BrowserColumn* ) //=================================================================== 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 ); } //=================================================================== bool BrowseBox::IsInCommandEvent() const { return getDataWindow()->bInCommand; } //=================================================================== 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; // muss zuerst gesetzt werden! 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 cols calc their new widths and adjust the header bar for ( sal_uInt16 nPos = 0; nPos < pCols->Count(); ++nPos ) { pCols->GetObject(nPos)->ZoomChanged(GetZoom()); if ( pHeaderBar ) pHeaderBar->SetItemSize( pCols->GetObject(nPos)->GetId(), pCols->GetObject(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->Count() && (0 == pCols->GetObject(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); //((Control*)pDataWin)->HideFocus(); 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; // fuer den CFront // Handle-Column nicht highlighten BrowserColumn *pFirstCol = pCols->GetObject(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.Count() && nLastRowInRect == ( nRow - 1 ) ) aHighlightList.First()->Union( aAddRect ); else aHighlightList.Insert( new Rectangle( aAddRect ), (sal_uLong) 0 ); nLastRowInRect = nRow; } // unhighlight the old selection (if any) while ( aHighlightList.Count() ) { Rectangle *pRect = aHighlightList.Remove( aHighlightList.Count() - 1 ); pDataWin->Invalidate( *pRect ); delete pRect; } // 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->GetObject(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 ); // keine Cursor auf Handle-Column if ( nCurColId == 0 ) nCurColId = GetColumnId(1); // Cursor-Rechteck berechnen Rectangle aCursor; if ( bColumnCursor ) { aCursor = GetFieldRectPixel( nCurRow, nCurColId, sal_False ); //! --aCursor.Bottom(); aCursor.Left() -= MIN_COLUMNWIDTH; aCursor.Right() += 1; aCursor.Bottom() += 1; } else aCursor = Rectangle( Point( ( pCols->Count() && pCols->GetObject(0)->GetId() == 0 ) ? pCols->GetObject(0)->Width() : 0, (nCurRow - nTopRow) * GetDataRowHeight() + 1 ), Size( pDataWin->GetOutputSizePixel().Width() + 1, GetDataRowHeight() - 2 ) ); if ( bHLines ) { if ( !bMultiSelection ) --aCursor.Top(); --aCursor.Bottom(); } //!mi_mac pDataWin->Update(); if (m_aCursorColor == COL_TRANSPARENT) { // auf diesem Plattformen funktioniert der StarView-Focus richtig 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->Count() ) return 0; return pCols->GetObject(nItemPos)->Width(); } //------------------------------------------------------------------- sal_uInt16 BrowseBox::GetColumnId( sal_uInt16 nPos ) const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( nPos >= pCols->Count() ) return 0; return pCols->GetObject(nPos)->GetId(); } //------------------------------------------------------------------- sal_uInt16 BrowseBox::GetColumnPos( sal_uInt16 nId ) const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); for ( sal_uInt16 nPos = 0; nPos < pCols->Count(); ++nPos ) if ( pCols->GetObject(nPos)->GetId() == nId ) return nPos; return BROWSER_INVALIDID; } //------------------------------------------------------------------- sal_Bool BrowseBox::IsFrozen( sal_uInt16 nColumnId ) const { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); for ( sal_uInt16 nPos = 0; nPos < pCols->Count(); ++nPos ) if ( pCols->GetObject(nPos)->GetId() == nColumnId ) return pCols->GetObject(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 - dont put these statemants together! SelectRow( aSelRange.Max(), bSelectThis, sal_True ); --aSelRange.Max(); } while ( rEvt.GetRow() > aSelRange.Max() ) { // ZTC/Mac bug - dont put these statemants 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 - dont put these statemants together! --aSelRange.Max(); if ( !IsRowSelected( aSelRange.Max() ) ) { SelectRow( aSelRange.Max(), bSelectThis, sal_True ); bSelect = sal_True; } } while ( rEvt.GetRow() > aSelRange.Max() ) { // ZTC/Mac bug - dont put these statemants 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->Count() ) { 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 = (sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1); // did we need a horiz. scroll bar oder gibt es eine Control Area? if ( !getDataWindow()->bNoHScroll && ( ( pCols->Count() - 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 = (sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1); // TopRow ist unveraendert, aber die Anzahl sichtbarer Zeilen hat sich // geaendert 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 ) { // Handle-Column beruecksichtigen BrowserColumn *pFirstCol = pCols->GetObject(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->Count() ) return; BrowserColumn *pFirstCol = pCols->GetObject(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 // Wenn es eine Handle Column gibt und die Headerbar verfuegbar ist, dann nur // die HandleColumn // Handle-Column beruecksichtigen if ( nTitleLines && (!bHeaderBar || bHandleCol) ) { // iterate through columns to redraw long nX = 0; sal_uInt16 nCol; for ( nCol = 0; nCol < pCols->Count() && nX < rRect.Right(); ++nCol ) { // skip invisible colums between frozen and scrollable area if ( nCol < nFirstCol && !pCols->GetObject(nCol)->IsFrozen() ) nCol = nFirstCol; // nur die HandleCol ? if (bHeaderBar && bHandleCol && nCol > 0) break; BrowserColumn *pCol = pCols->GetObject(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, 0 != (BROWSER_COLUMN_TITLEABBREVATION&pCol->Flags()), !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->Count() ) { 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); // aOldLineColor ); oj 09.02.00 seems to be a copy&paste bug SetLineColor( aOldLineColor); // aOldFillColor ); } } } //------------------------------------------------------------------- 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 sal_uInt16 nPos; for ( nPos = 0; nPos < pCols->Count(); ++nPos ) { BrowserColumn* pCurrent = pCols->GetObject(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->Count() ? pCols->GetObject(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, 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->Count(); ++nPos ) { BrowserColumn* pCurrent = pCols->GetObject(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 = _bForeignDevice ? 0 : ((sal_uLong)_rRect.Top() / nDataRowHeigt); sal_uLong nRelBottomRow = (sal_uLong)(_bForeignDevice ? aOverallAreaSize.Height() : _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->GetObject(0)->GetId() ? pCols->GetObject(0)->Width() : 0; nHLineX += aOverallAreaPos.X(); Color aDelimiterLineColor( ::svtools::ColorConfig().GetColorValue( ::svtools::CALCGRID ).nColor ); // redraw the invalid fields sal_Bool bRetouching = sal_False; for ( sal_uLong nRelRow = nRelTopRow; nRelRow <= nRelBottomRow && (sal_uLong)nTopRow+nRelRow < (sal_uLong)nRowCount; ++nRelRow, aPos.Y() += nDataRowHeigt ) { // get row // Zur Sicherheit auf zul"assigen Bereich abfragen: 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) ) { DBG_ERROR("BrowseBox::ImplPaintData: SeekRow gescheitert"); } _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 sal_uInt16 nCol; for ( nCol = 0; nCol < pCols->Count(); ++nCol ) { // get column BrowserColumn *pCol = pCols->GetObject(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 = pCols->GetObject(nCol); if (!pCol) { // FS - 21.05.99 - 66325 // ist zwar eigentlich woanders (an der richtigen Stelle) gefixt, aber sicher ist sicher ... DBG_ERROR("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 // #63864#, Sonst wird auch etwas gezeichnet, bsp 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(); } if ( nCol == pCols->Count() ) bRetouching = sal_True; // 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->Count() && ( pCols->GetObject(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->GetObject(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 ( sal_uInt16 nCol = 0; nCol < pCols->Count(); ++nCol ) { // get column BrowserColumn *pCol = pCols->GetObject(nCol); // skip invisible colums between frozen and scrollable area if ( nCol < nFirstCol && !pCol->IsFrozen() ) { nCol = nFirstCol; pCol = pCols->GetObject(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->Count() || !rWin.IsUpdateMode() ) return; if ( getDataWindow()->bResizeOnPaint ) Resize(); // MI: wer war das denn? Window::Update(); ImplPaintData(rWin, rRect, sal_False, sal_True); } //------------------------------------------------------------------- void BrowseBox::UpdateScrollbars() { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); if ( !bBootstrapped || !IsUpdateMode() ) return; // Rekursionsschutz 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()); // needs VScroll? long nMaxRows = (pDataWin->GetSizePixel().Height()) / GetDataRowHeight(); sal_Bool 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->Count() ) : !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 ) ); // Scrollable Columns insgesamt short nScrollCols = short(pCols->Count()) - (short)nFrozenCols; /*short nVisibleHSize= std::max(nLastCol == BROWSER_INVALIDID ? pCols->Count() - nFirstCol -1 : nLastCol - nFirstCol - 1, 0); aHScroll.SetVisibleSize( nVisibleHSize ); aHScroll.SetRange( Range( 0, Max( std::min(nScrollCols, nVisibleHSize), (short)0 ) ) ); if ( bNeedsHScroll && !aHScroll.IsVisible() ) aHScroll.Show();*/ // Sichtbare Columns short nVisibleHSize = nLastCol == BROWSER_INVALIDID ? (short)( pCols->Count() - 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; DBG_ERROR("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()) ); if ( nRowCount < long( aDataWinSize.Height() / GetDataRowHeight() ) ) 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 ); // ggf. Headerbar mitscrollen if ( getDataWindow()->pHeaderBar ) { long nWidth = 0; for ( sal_uInt16 nCol = 0; nCol < pCols->Count() && nCol < nFirstCol; ++nCol ) { // HandleColumn nicht if ( pCols->GetObject(nCol)->GetId() ) nWidth += pCols->GetObject(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 ); // OV // Wenn an der BrowseBox WB_CLIPCHILDREN gesetzt ist (wg. Flackerminimierung), // wird das Datenfenster nicht von SetUpdateMode invalidiert. 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 ( sal_uInt16 nCol = 0; nCol < pCols->Count() && pCols->GetObject(nCol)->IsFrozen(); ++nCol ) nWidth += pCols->GetObject(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->Count() && pCols->GetObject(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( BrowseBox,EndScrollHdl,ScrollBar*, EMPTYARG ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); // kein Focus grabben! /// GrabFocus(); if ( /*pBar->GetDelta() <= 0 &&*/ getDataWindow()->bNoScrollBack ) { // UpdateScrollbars(); EndScroll(); return 0; } return 0; } //------------------------------------------------------------------- IMPL_LINK( BrowseBox, StartDragHdl, HeaderBar*, pBar ) { pBar->SetDragSize( pDataWin->GetOutputSizePixel().Height() ); return 0; } //------------------------------------------------------------------- // MI: es wurde immer nur die 1. Spalte resized #ifdef _MSC_VER #pragma optimize("",off) #endif void BrowseBox::MouseButtonDown( const MouseEvent& rEvt ) { DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants); GrabFocus(); // onl< 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 ( sal_uInt16 nCol = 0; nCol < pCols->Count() && nX < nWidth; ++nCol ) { // is this column visible? BrowserColumn *pCol = pCols->GetObject(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); DBG_TRACE( "BrowseBox::MouseMove( MouseEvent )" ); Pointer aNewPointer; sal_uInt16 nX = 0; for ( sal_uInt16 nCol = 0; nCol < sal_uInt16(pCols->Count()) && ( nX + pCols->GetObject(nCol)->Width() ) < sal_uInt16(GetOutputSizePixel().Width()); ++nCol ) // is this column visible? if ( pCols->GetObject(nCol)->IsFrozen() || nCol >= nFirstCol ) { // compute right end of column BrowserColumn *pCol = pCols->GetObject(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 ) { // alte Hilfslinie loeschen pDataWin->HideTracking() ; // erlaubte breite abholen und neues 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; // neue Hilfslinie zeichnen 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 ) { // Hilfslinie loeschen pDataWin->HideTracking(); // width changed? nDragX = Max( rEvt.GetPosPixel().X(), nMinResizeX ); if ( (nDragX - nResizeX) != (long)pCols->GetObject(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->Count() ) 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 ) { // Zeilenselektion? if ( rEvt.GetColumnId() == 0 || !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() ) ) { // auf Drag&Drop warten 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() == 0 ) { // toggle all-selection if ( uRow.pSel->GetSelectCount() > ( GetRowCount() / 2 ) ) SetNoSelection(); else SelectAll(); } else SelectColumnId( rEvt.GetColumnId(), sal_True, sal_False ); } // ggf. Cursor wieder an 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 != 0) && 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 != 0) // Am Zeilenende ? bDone = GoToColumnId( nNewId ); else { sal_uInt16 nColId = ( GetColumnId(0) == 0 ) ? GetColumnId(1) : GetColumnId(0); 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 != 0) && 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 != 0) 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