summaryrefslogtreecommitdiff
path: root/sc/source/ui/dbgui/fieldwnd.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/dbgui/fieldwnd.cxx')
-rw-r--r--sc/source/ui/dbgui/fieldwnd.cxx1191
1 files changed, 661 insertions, 530 deletions
diff --git a/sc/source/ui/dbgui/fieldwnd.cxx b/sc/source/ui/dbgui/fieldwnd.cxx
index 8016c20eff34..02bf712e59fb 100644
--- a/sc/source/ui/dbgui/fieldwnd.cxx
+++ b/sc/source/ui/dbgui/fieldwnd.cxx
@@ -28,749 +28,880 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
-#include <vcl/virdev.hxx>
+#include "fieldwnd.hxx"
+
+#include <tools/debug.hxx>
#include <vcl/decoview.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/mnemonic.hxx>
#include <vcl/help.hxx>
-#include <tools/debug.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
-#include "fieldwnd.hxx"
#include "pvlaydlg.hxx"
-#include "pvglob.hxx"
#include "AccessibleDataPilotControl.hxx"
#include "scresid.hxx"
#include "sc.hrc"
-const size_t INVALID_INDEX = static_cast< size_t >( -1 );
-
-//===================================================================
-
-ScDPFieldWindow::ScDPFieldWindow(
- ScDPLayoutDlg* pDialog,
- const ResId& rResId,
- ScDPFieldType eFieldType,
- FixedText* pFtFieldCaption ) :
- Control( pDialog, rResId ),
- pDlg( pDialog ),
- pFtCaption( pFtFieldCaption ),
- eType( eFieldType ),
- nFieldSelected( 0 ),
- pAccessible( NULL )
-{
- Init();
- if (eType != TYPE_SELECT && pFtCaption)
- aName = MnemonicGenerator::EraseAllMnemonicChars( pFtCaption->GetText() );
-}
-
-ScDPFieldWindow::ScDPFieldWindow(
- ScDPLayoutDlg* pDialog,
- const ResId& rResId,
- ScDPFieldType eFieldType,
- const String& rName ) :
- Control( pDialog, rResId ),
- aName(rName),
- pDlg( pDialog ),
- pFtCaption( NULL ),
- eType( eFieldType ),
- nFieldSelected( 0 ),
- pAccessible( NULL )
-{
- Init();
-}
+// ============================================================================
-void ScDPFieldWindow::Init()
-{
- aWndRect = Rectangle( GetPosPixel(), GetSizePixel() );
- nFieldSize = (eType == TYPE_SELECT) ? PAGE_SIZE : ((eType == TYPE_PAGE) ? MAX_PAGEFIELDS : MAX_FIELDS);
+using namespace ::com::sun::star;
+using ::rtl::OUString;
- if( pFtCaption )
- {
- Size aWinSize( aWndRect.GetSize() );
- Size aTextSize( GetTextWidth( pFtCaption->GetText() ), GetTextHeight() );
- aTextPos.X() = (aWinSize.Width() - aTextSize.Width()) / 2;
- aTextPos.Y() = (aWinSize.Height() - aTextSize.Height()) / 2;
- }
+// ============================================================================
- GetStyleSettings();
-}
+namespace {
-__EXPORT ScDPFieldWindow::~ScDPFieldWindow()
-{
- if (pAccessible)
- {
- com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xTempAcc = xAccessible;
- if (xTempAcc.is())
- pAccessible->dispose();
- }
-}
+/** Line width for insertion cursor in pixels. */
+const long CURSOR_WIDTH = 3;
-//-------------------------------------------------------------------
+/** Number of tracking events before auto scrolling starts. */
+const size_t INITIAL_TRACKING_DELAY = 20;
-void ScDPFieldWindow::GetStyleSettings()
-{
- const StyleSettings& rStyleSet = GetSettings().GetStyleSettings();
- aFaceColor = rStyleSet.GetFaceColor();
- aWinColor = rStyleSet.GetWindowColor();
- aTextColor = rStyleSet.GetButtonTextColor();
- aWinTextColor = rStyleSet.GetWindowTextColor();
-}
+} // namespace
-//-------------------------------------------------------------------
+// ============================================================================
-Point ScDPFieldWindow::GetFieldPosition( size_t nIndex ) const
+ScPivotFieldWindow::ScPivotWindowField::ScPivotWindowField( const ScDPLabelData& rLabelData ) :
+ maFuncData( rLabelData.mnCol, rLabelData.mnFuncMask ),
+ maFieldName( rLabelData.getDisplayName() )
{
- Point aPos;
- switch( eType )
- {
- case TYPE_PAGE:
- aPos.X() = OWIDTH * (nIndex % (MAX_PAGEFIELDS / 2));
- aPos.Y() = OHEIGHT * (nIndex / (MAX_PAGEFIELDS / 2));
- break;
- case TYPE_COL:
- aPos.X() = OWIDTH * (nIndex % (MAX_FIELDS / 2));
- aPos.Y() = OHEIGHT * (nIndex / (MAX_FIELDS / 2));
- break;
- case TYPE_ROW:
- case TYPE_DATA:
- aPos.X() = 0;
- aPos.Y() = OHEIGHT * nIndex;
- break;
- case TYPE_SELECT:
- aPos.X() = (OWIDTH + SSPACE) * (nIndex / LINE_SIZE);
- aPos.Y() = (OHEIGHT + SSPACE) * (nIndex % LINE_SIZE);
- break;
- }
- return aPos;
}
-Size ScDPFieldWindow::GetFieldSize() const
+ScPivotFieldWindow::ScPivotWindowField::ScPivotWindowField( ScPivotLayoutDlg& rDialog, const ScPivotField& rField, bool bDataWindow ) :
+ maFuncData( rField.nCol, rField.nFuncMask, rField.maFieldRef )
{
- return Size( (eType == TYPE_DATA) ? GetSizePixel().Width() : OWIDTH, OHEIGHT );
+ InitFieldName( rDialog, bDataWindow );
}
-Point ScDPFieldWindow::GetLastPosition() const
+ScPivotFieldWindow::ScPivotWindowField::ScPivotWindowField( ScPivotLayoutDlg& rDialog, const ScPivotFuncData& rFuncData, bool bDataWindow ) :
+ maFuncData( rFuncData )
{
- return OutputToScreenPixel( GetFieldPosition( nFieldSize - 1 ) );
+ InitFieldName( rDialog, bDataWindow );
}
-bool ScDPFieldWindow::GetFieldIndex( const Point& rPos, size_t& rnIndex ) const
+void ScPivotFieldWindow::ScPivotWindowField::InitFieldName( ScPivotLayoutDlg& rDialog, bool bDataWindow )
{
- rnIndex = INVALID_INDEX;
- if( (rPos.X() >= 0) && (rPos.Y() >= 0) )
+ if( maFuncData.mnCol != PIVOT_DATA_FIELD )
{
- switch( eType )
+ ScDPLabelData* pLabelData = rDialog.GetLabelData( maFuncData.mnCol );
+ DBG_ASSERT( pLabelData, "ScPivotWindowField::InitFieldName - no label data found" );
+ if( pLabelData )
{
- case TYPE_ROW:
- case TYPE_DATA:
- rnIndex = rPos.Y() / OHEIGHT;
- break;
- case TYPE_PAGE:
- {
- size_t nRow = rPos.Y() / OHEIGHT;
- size_t nCol = rPos.X() / OWIDTH;
- rnIndex = nRow * MAX_PAGEFIELDS / 2 + nCol;
- }
- break;
- case TYPE_COL:
- {
- size_t nRow = rPos.Y() / OHEIGHT;
- size_t nCol = rPos.X() / OWIDTH;
- rnIndex = nRow * MAX_FIELDS / 2 + nCol;
- }
- break;
- case TYPE_SELECT:
+ if( bDataWindow )
{
- size_t nRow = rPos.Y() / (OHEIGHT + SSPACE);
- size_t nCol = rPos.X() / (OWIDTH + SSPACE);
- // is not between controls?
- if( (rPos.Y() % (OHEIGHT + SSPACE) < OHEIGHT) && (rPos.X() % (OWIDTH + SSPACE) < OWIDTH) )
- rnIndex = nCol * LINE_SIZE + nRow;
+ // write original nFuncMask to label data
+ pLabelData->mnFuncMask = maFuncData.mnFuncMask;
+ // GetFuncString() modifies nFuncMask (e.g. auto to sum or count)
+ maFieldName = rDialog.GetFuncString( maFuncData.mnFuncMask, pLabelData->mbIsValue );
}
- break;
+ maFieldName += pLabelData->getDisplayName();
}
}
- return IsValidIndex( rnIndex );
}
-//-------------------------------------------------------------------
-
-void ScDPFieldWindow::DrawBackground( OutputDevice& rDev )
-{
- Point aPos0;
- Size aSize( GetSizePixel() );
+// ============================================================================
- if ( eType == TYPE_SELECT )
- {
- rDev.SetLineColor();
- rDev.SetFillColor( aFaceColor );
- rDev.DrawRect( Rectangle( aPos0, aSize ) );
+ScPivotFieldWindow::ScPivotFieldWindow( ScPivotLayoutDlg* pDialog, const ResId& rResId,
+ ScrollBar& rScrollBar, FixedText* pFtCaption, const OUString& rName,
+ ScPivotFieldType eFieldType, const sal_Char* pcHelpId, PointerStyle eDropPointer,
+ size_t nColCount, size_t nRowCount, long nFieldWidthFactor, long nSpaceSize ) :
+ Control( pDialog, rResId ),
+ mpDialog( pDialog ),
+ mpAccessible( 0 ),
+ mrScrollBar( rScrollBar ),
+ mpFtCaption( pFtCaption ),
+ maName( rName ),
+ meFieldType( eFieldType ),
+ meDropPointer( eDropPointer ),
+ mnColCount( nColCount ),
+ mnRowCount( nRowCount ),
+ mnFirstVisIndex( 0 ),
+ mnSelectIndex( 0 ),
+ mnInsCursorIndex( PIVOTFIELD_INVALID ),
+ mnOldFirstVisIndex( 0 ),
+ mnAutoScrollDelay( 0 ),
+ mbVertical( eFieldType == PIVOTFIELDTYPE_SELECT ),
+ mbIsTrackingSource( false )
+{
+ SetHelpId( pcHelpId );
+
+ mnLineSize = mbVertical ? mnRowCount : mnColCount;
+ mnPageSize = mnColCount * mnRowCount;
+
+ // a single field is 36x12 appfont units
+ maFieldSize = LogicToPixel( Size( 36, 12 ), MapMode( MAP_APPFONT ) );
+ maFieldSize.Width() *= nFieldWidthFactor;
+ maSpaceSize = LogicToPixel( Size( nSpaceSize, nSpaceSize ), MapMode( MAP_APPFONT ) );
+
+ // set window size
+ long nWinWidth = static_cast< long >( mnColCount * maFieldSize.Width() + (mnColCount - 1) * maSpaceSize.Width() );
+ long nWinHeight = static_cast< long >( mnRowCount * maFieldSize.Height() + (mnRowCount - 1) * maSpaceSize.Height() );
+ SetSizePixel( Size( nWinWidth, nWinHeight ) );
+
+ // scroll bar
+ Point aScrollBarPos = GetPosPixel();
+ Size aScrollBarSize( nWinWidth, nWinHeight );
+ if( mbVertical )
+ {
+ aScrollBarPos.Y() += nWinHeight + maSpaceSize.Height();
+ aScrollBarSize.Height() = GetSettings().GetStyleSettings().GetScrollBarSize();
}
else
{
- rDev.SetLineColor( aWinTextColor );
- rDev.SetFillColor( aWinColor );
- rDev.DrawRect( Rectangle( aPos0, aSize ) );
-
- rDev.SetTextColor( aWinTextColor );
-
- /* Draw the caption text. This needs some special handling, because we
- support hard line breaks here. This part will draw each line of the
- text for itself. */
-
- xub_StrLen nTokenCnt = GetText().GetTokenCount( '\n' );
- long nY = (aSize.Height() - nTokenCnt * rDev.GetTextHeight()) / 2;
- for( xub_StrLen nToken = 0, nStringIx = 0; nToken < nTokenCnt; ++nToken )
- {
- String aLine( GetText().GetToken( 0, '\n', nStringIx ) );
- Point aLinePos( (aSize.Width() - rDev.GetCtrlTextWidth( aLine )) / 2, nY );
- rDev.DrawCtrlText( aLinePos, aLine );
- nY += rDev.GetTextHeight();
- }
+ aScrollBarPos.X() += nWinWidth + maSpaceSize.Width();
+ aScrollBarSize.Width() = GetSettings().GetStyleSettings().GetScrollBarSize();
}
+ mrScrollBar.SetPosSizePixel( aScrollBarPos, aScrollBarSize );
+ mrScrollBar.SetLineSize( 1 );
+ mrScrollBar.SetPageSize( static_cast< long >( mbVertical ? mnColCount : mnRowCount ) );
+ mrScrollBar.SetVisibleSize( static_cast< long >( mbVertical ? mnColCount : mnRowCount ) );
+ mrScrollBar.SetScrollHdl( LINK( this, ScPivotFieldWindow, ScrollHdl ) );
+ mrScrollBar.SetEndScrollHdl( LINK( this, ScPivotFieldWindow, ScrollHdl ) );
}
-void ScDPFieldWindow::DrawField(
- OutputDevice& rDev, const Rectangle& rRect, FieldString& rText, bool bFocus )
+ScPivotFieldWindow::~ScPivotFieldWindow()
{
- VirtualDevice aVirDev( rDev );
- // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
- aVirDev.EnableRTL( IsRTLEnabled() );
+ ::rtl::Reference< ScAccessibleDataPilotControl > xAcc = GetAccessibleControl();
+ if( xAcc.is() )
+ xAcc->dispose();
+}
- String aText = rText.first;
- Size aDevSize( rRect.GetSize() );
- long nWidth = aDevSize.Width();
- long nHeight = aDevSize.Height();
- long nLabelWidth = rDev.GetTextWidth( aText );
- long nLabelHeight = rDev.GetTextHeight();
-
- // #i31600# if text is too long, cut and add ellipsis
- rText.second = nLabelWidth + 6 <= nWidth;
- if( !rText.second )
- {
- xub_StrLen nMinLen = 0;
- xub_StrLen nMaxLen = aText.Len();
- bool bFits = false;
- do
- {
- xub_StrLen nCurrLen = (nMinLen + nMaxLen) / 2;
- aText = String( rText.first, 0, nCurrLen ).AppendAscii( "..." );
- nLabelWidth = rDev.GetTextWidth( aText );
- bFits = nLabelWidth + 6 <= nWidth;
- (bFits ? nMinLen : nMaxLen) = nCurrLen;
- }
- while( !bFits || (nMinLen + 1 < nMaxLen) );
+void ScPivotFieldWindow::ReadDataLabels( const ScDPLabelDataVector& rLabels )
+{
+ maFields.clear();
+ maFields.reserve( rLabels.size() );
+ for( ScDPLabelDataVector::const_iterator aIt = rLabels.begin(), aEnd = rLabels.end(); aIt != aEnd; ++aIt )
+ {
+ ScPivotWindowField aField( *aIt );
+ if( aField.maFieldName.getLength() > 0 )
+ maFields.push_back( aField );
}
- Point aLabelPos( (nWidth - nLabelWidth) / 2, ::std::max< long >( (nHeight - nLabelHeight) / 2, 3 ) );
-
- aVirDev.SetOutputSizePixel( aDevSize );
- aVirDev.SetFont( rDev.GetFont() );
- DecorationView aDecoView( &aVirDev );
- aDecoView.DrawButton( Rectangle( Point( 0, 0 ), aDevSize ), bFocus ? BUTTON_DRAW_DEFAULT : 0 );
- aVirDev.SetTextColor( aTextColor );
- aVirDev.DrawText( aLabelPos, aText );
- rDev.DrawBitmap( rRect.TopLeft(), aVirDev.GetBitmap( Point( 0, 0 ), aDevSize ) );
+ Invalidate();
}
-void ScDPFieldWindow::Redraw()
+void ScPivotFieldWindow::ReadPivotFields( const ScPivotFieldVector& rPivotFields )
{
- VirtualDevice aVirDev;
- // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
- aVirDev.EnableRTL( IsRTLEnabled() );
- aVirDev.SetMapMode( MAP_PIXEL );
-
- Point aPos0;
- Size aSize( GetSizePixel() );
- Font aFont( GetFont() ); // Font vom Window
- aFont.SetTransparent( sal_True );
- aVirDev.SetFont( aFont );
- aVirDev.SetOutputSizePixel( aSize );
-
- DrawBackground( aVirDev );
-
- if( !aFieldArr.empty() && (nFieldSelected >= aFieldArr.size()) )
- nFieldSelected = aFieldArr.size() - 1;
- Rectangle aFieldRect( aPos0, GetFieldSize() );
- for( size_t nIx = 0; nIx < aFieldArr.size(); ++nIx )
+ maFields.clear();
+ maFields.reserve( rPivotFields.size() );
+ for( ScPivotFieldVector::const_iterator aIt = rPivotFields.begin(), aEnd = rPivotFields.end(); aIt != aEnd; ++aIt )
{
- aFieldRect.SetPos( GetFieldPosition( nIx ) );
- bool bFocus = HasFocus() && (nIx == nFieldSelected);
- DrawField( aVirDev, aFieldRect, aFieldArr[ nIx ], bFocus );
+ ScPivotWindowField aField( *mpDialog, *aIt, meFieldType == PIVOTFIELDTYPE_DATA );
+ if( aField.maFieldName.getLength() > 0 )
+ maFields.push_back( aField );
}
- DrawBitmap( aPos0, aVirDev.GetBitmap( aPos0, aSize ) );
+ Invalidate();
+}
- if( HasFocus() && (nFieldSelected < aFieldArr.size()) )
+void ScPivotFieldWindow::WriteFieldNames( ScDPNameVec& rFieldNames ) const
+{
+ rFieldNames.clear();
+ rFieldNames.reserve( maFields.size() );
+ // do not use the names stored in maFields, but generate plain display names from label data
+ for( ScPivotWindowFieldVector::const_iterator aIt = maFields.begin(), aEnd = maFields.end(); aIt != aEnd; ++aIt )
{
- long nFieldWidth = aFieldRect.GetWidth();
- long nSelectionWidth = Min( GetTextWidth( aFieldArr[ nFieldSelected ].first ) + 4, nFieldWidth - 6 );
- Rectangle aSelection(
- GetFieldPosition( nFieldSelected ) + Point( (nFieldWidth - nSelectionWidth) / 2, 3 ),
- Size( nSelectionWidth, aFieldRect.GetHeight() - 6 ) );
- InvertTracking( aSelection, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
+ if( ScDPLabelData* pLabelData = mpDialog->GetLabelData( aIt->maFuncData.mnCol ) )
+ {
+ OUString aDisplayName = pLabelData->getDisplayName();
+ if( aDisplayName.getLength() > 0 )
+ rFieldNames.push_back( aDisplayName );
+ }
}
-
- UpdateStyle();
}
-void ScDPFieldWindow::UpdateStyle()
+void ScPivotFieldWindow::WritePivotFields( ScPivotFieldVector& rPivotFields ) const
{
- WinBits nMask = ~(WB_TABSTOP | WB_NOTABSTOP);
- SetStyle( (GetStyle() & nMask) | (IsEmpty() ? WB_NOTABSTOP : WB_TABSTOP) );
+ rPivotFields.resize( maFields.size() );
+ ScPivotFieldVector::iterator aOutIt = rPivotFields.begin();
+ for( ScPivotWindowFieldVector::const_iterator aIt = maFields.begin(), aEnd = maFields.end(); aIt != aEnd; ++aIt, ++aOutIt )
+ {
+ aOutIt->nCol = aIt->maFuncData.mnCol;
+ aOutIt->nFuncMask = aIt->maFuncData.mnFuncMask;
+ aOutIt->maFieldRef = aIt->maFuncData.maFieldRef;
+ }
}
-//-------------------------------------------------------------------
-
-bool ScDPFieldWindow::IsValidIndex( size_t nIndex ) const
+OUString ScPivotFieldWindow::GetDescription() const
{
- return nIndex < nFieldSize;
+ switch( meFieldType )
+ {
+ case PIVOTFIELDTYPE_COL: return String( ScResId( STR_ACC_DATAPILOT_COL_DESCR ) );
+ case PIVOTFIELDTYPE_ROW: return String( ScResId( STR_ACC_DATAPILOT_ROW_DESCR ) );
+ case PIVOTFIELDTYPE_DATA: return String( ScResId( STR_ACC_DATAPILOT_DATA_DESCR ) );
+ case PIVOTFIELDTYPE_SELECT: return String( ScResId( STR_ACC_DATAPILOT_SEL_DESCR ) );
+ default:;
+ }
+ return OUString();
}
-bool ScDPFieldWindow::IsExistingIndex( size_t nIndex ) const
+OUString ScPivotFieldWindow::GetFieldText( size_t nFieldIndex ) const
{
- return nIndex < aFieldArr.size();
+ return (nFieldIndex < maFields.size()) ? maFields[ nFieldIndex ].maFieldName : OUString();
}
-bool ScDPFieldWindow::IsShortenedText( size_t nIndex ) const
+ScPivotFuncDataEntry ScPivotFieldWindow::FindFuncDataByCol( SCCOL nCol ) const
{
- return (nIndex < aFieldArr.size()) && !aFieldArr[ nIndex ].second;
+ for( ScPivotWindowFieldVector::const_iterator aIt = maFields.begin(), aEnd = maFields.end(); aIt != aEnd; ++aIt )
+ if( aIt->maFuncData.mnCol == nCol )
+ return ScPivotFuncDataEntry( &aIt->maFuncData, aIt - maFields.begin() );
+ return ScPivotFuncDataEntry( 0, PIVOTFIELD_INVALID );
}
-size_t ScDPFieldWindow::CalcNewFieldIndex( SCsCOL nDX, SCsROW nDY ) const
+Point ScPivotFieldWindow::GetFieldPosition( size_t nFieldIndex ) const
{
- size_t nNewField = nFieldSelected;
- switch( eType )
- {
- case TYPE_PAGE:
- nNewField += static_cast<SCsCOLROW>(nDX) + nDY * MAX_PAGEFIELDS / 2;
- break;
- case TYPE_COL:
- nNewField += static_cast<SCsCOLROW>(nDX) + nDY * MAX_FIELDS / 2;
- break;
- case TYPE_ROW:
- case TYPE_DATA:
- nNewField += nDY;
- break;
- case TYPE_SELECT:
- nNewField += static_cast<SCsCOLROW>(nDX) * LINE_SIZE + nDY;
- break;
- }
-
- return IsExistingIndex( nNewField ) ? nNewField : nFieldSelected;
+ long nRelIndex = static_cast< long >( nFieldIndex ) - mnFirstVisIndex;
+ long nCol = static_cast< long >( mbVertical ? (nRelIndex / mnRowCount) : (nRelIndex % mnColCount) );
+ long nRow = static_cast< long >( mbVertical ? (nRelIndex % mnRowCount) : (nRelIndex / mnColCount) );
+ return Point( nCol * (maFieldSize.Width() + maSpaceSize.Width()), nRow * (maFieldSize.Height() + maSpaceSize.Height()) );
}
-void ScDPFieldWindow::SetSelection( size_t nIndex )
+size_t ScPivotFieldWindow::GetFieldIndex( const Point& rWindowPos ) const
{
- if( !aFieldArr.empty() )
+ if( (rWindowPos.X() >= 0) && (rWindowPos.Y() >= 0) )
{
- if( nFieldSelected >= aFieldArr.size() )
- nFieldSelected = aFieldArr.size() - 1;
- if( nFieldSelected != nIndex )
+ long nGridWidth = maFieldSize.Width() + maSpaceSize.Width();
+ long nGridHeight = maFieldSize.Height() + maSpaceSize.Height();
+ size_t nCol = static_cast< size_t >( rWindowPos.X() / nGridWidth );
+ size_t nRow = static_cast< size_t >( rWindowPos.Y() / nGridHeight );
+ if( (nCol < mnColCount) && (nRow < mnRowCount) )
{
- sal_Int32 nOldSelected(nFieldSelected);
- nFieldSelected = nIndex;
- Redraw();
-
- if (pAccessible && HasFocus())
+ long nColOffset = rWindowPos.X() % nGridWidth;
+ long nRowOffset = rWindowPos.Y() % nGridHeight;
+ // check that passed position is not in the space between the fields
+ if( (nColOffset < maFieldSize.Width()) && (nRowOffset < maFieldSize.Height()) )
{
- com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xTempAcc = xAccessible;
- if (xTempAcc.is())
- pAccessible->FieldFocusChange(nOldSelected, nFieldSelected);
- else
- pAccessible = NULL;
+ size_t nFieldIndex = mnFirstVisIndex + (mbVertical ? (nCol * mnRowCount + nRow) : (nRow * mnColCount + nCol));
+ return (nFieldIndex < maFields.size()) ? nFieldIndex : PIVOTFIELD_INVALID;
}
}
}
+ return PIVOTFIELD_INVALID;
}
-void ScDPFieldWindow::SetSelectionHome()
+size_t ScPivotFieldWindow::GetDropIndex( const Point& rWindowPos ) const
{
- if( !aFieldArr.empty() )
+ if( (rWindowPos.X() >= 0) && (rWindowPos.Y() >= 0) )
{
- if( eType == TYPE_SELECT )
- pDlg->NotifyMoveSlider( KEY_HOME );
- SetSelection( 0 );
+ long nGridWidth = maFieldSize.Width() + maSpaceSize.Width();
+ long nGridHeight = maFieldSize.Height() + maSpaceSize.Height();
+ size_t nCol = static_cast< size_t >( rWindowPos.X() / nGridWidth );
+ size_t nRow = static_cast< size_t >( rWindowPos.Y() / nGridHeight );
+ if( (nCol < mnColCount) && (nRow < mnRowCount) )
+ {
+ size_t nFieldIndex = mnFirstVisIndex + (mbVertical ? (nCol * mnRowCount + nRow) : (nRow * mnColCount + nCol));
+ long nColOffset = rWindowPos.X() % nGridWidth;
+ long nRowOffset = rWindowPos.Y() % nGridHeight;
+ // take next field, if position is in right/lower third
+ if( (mnColCount == 1) ? (nRowOffset * 3 > nGridHeight * 2) : (nColOffset * 3 > nGridWidth * 2) )
+ ++nFieldIndex;
+ return ::std::min( nFieldIndex, maFields.size() );
+ }
}
+ return maFields.size();
}
-void ScDPFieldWindow::SetSelectionEnd()
+void ScPivotFieldWindow::GrabFocusAndSelect( size_t nSelectIndex )
{
- if( !aFieldArr.empty() )
- {
- if( eType == TYPE_SELECT )
- pDlg->NotifyMoveSlider( KEY_END );
- SetSelection( aFieldArr.size() - 1 );
- }
+ if( !HasFocus() ) GrabFocus();
+ MoveSelection( nSelectIndex );
}
-void ScDPFieldWindow::MoveSelection( sal_uInt16 nKeyCode, SCsCOL nDX, SCsROW nDY )
+void ScPivotFieldWindow::SelectNextField()
{
- size_t nNewIndex = CalcNewFieldIndex( nDX, nDY );
- if( (eType == TYPE_SELECT) && (nNewIndex == nFieldSelected) )
+ MoveSelection( NEXT_FIELD );
+}
+
+void ScPivotFieldWindow::InsertField( size_t nInsertIndex, const ScPivotFuncData& rFuncData )
+{
+ if( (meFieldType != PIVOTFIELDTYPE_SELECT) && (nInsertIndex <= maFields.size()) )
{
- if( pDlg->NotifyMoveSlider( nKeyCode ) )
+ size_t nFieldIndex = FindFuncDataByCol( rFuncData.mnCol ).second;
+ if( nFieldIndex < maFields.size() )
+ {
+ // field exists already in this window, move it to the specified position
+ MoveField( nFieldIndex, nInsertIndex );
+ }
+ else
{
- switch( nKeyCode )
+ // insert the field into the vector and notify accessibility object
+ ScPivotWindowField aField( *mpDialog, rFuncData, meFieldType == PIVOTFIELDTYPE_DATA );
+ if( aField.maFieldName.getLength() > 0 )
{
- case KEY_UP: nNewIndex += (LINE_SIZE - 1); break;
- case KEY_DOWN: nNewIndex -= (LINE_SIZE - 1); break;
+ InsertFieldUnchecked( nInsertIndex, aField );
+ // adjust selection and scroll position
+ MoveSelection( nInsertIndex );
+ Invalidate();
}
}
}
- SetSelection( nNewIndex );
}
-void ScDPFieldWindow::ModifySelectionOffset( long nOffsetDiff )
+bool ScPivotFieldWindow::RemoveField( size_t nRemoveIndex )
{
- nFieldSelected -= nOffsetDiff;
- Redraw();
+ if( (meFieldType != PIVOTFIELDTYPE_SELECT) && (nRemoveIndex < maFields.size()) )
+ {
+ // remove the field from the vector and notify accessibility object
+ RemoveFieldUnchecked( nRemoveIndex );
+ // adjust selection and scroll position, if last field is removed
+ if( !maFields.empty() )
+ MoveSelection( (mnSelectIndex < maFields.size()) ? mnSelectIndex : (maFields.size() - 1) );
+ Invalidate();
+ return true;
+ }
+ return false;
}
-void ScDPFieldWindow::SelectNext()
+bool ScPivotFieldWindow::MoveField( size_t nFieldIndex, size_t nInsertIndex )
{
- if( eType == TYPE_SELECT )
- MoveSelection( KEY_DOWN, 0, 1 );
+ /* If field is moved behind current position, insertion index needs to be
+ adjusted, because the field is first removed from the vector. This is
+ done before nFieldIndex and nInsertIndex are checked for equality, to
+ catch the cases "move before ourselves" and "move bedind ourselves"
+ which are both no-ops. */
+ if( nFieldIndex < nInsertIndex )
+ --nInsertIndex;
+
+ if( (meFieldType != PIVOTFIELDTYPE_SELECT) && (nFieldIndex != nInsertIndex) && (nFieldIndex < maFields.size()) && (nInsertIndex < maFields.size()) )
+ {
+ // move the field in the vector and notify accessibility object
+ ScPivotWindowField aField = maFields[ nFieldIndex ];
+ RemoveFieldUnchecked( nFieldIndex );
+ InsertFieldUnchecked( nInsertIndex, aField );
+ // adjust selection and scroll position
+ MoveSelection( nInsertIndex );
+ Invalidate();
+ return true;
+ }
+ return false;
}
-void ScDPFieldWindow::GrabFocusWithSel( size_t nIndex )
+const ScPivotFuncData* ScPivotFieldWindow::GetSelectedFuncData() const
{
- SetSelection( nIndex );
- if( !HasFocus() )
- GrabFocus();
+ return (mnSelectIndex < maFields.size()) ? &maFields[ mnSelectIndex ].maFuncData : 0;
}
-void ScDPFieldWindow::MoveField( size_t nDestIndex )
+void ScPivotFieldWindow::ModifySelectedField( const ScPivotFuncData& rFuncData )
{
- if( nDestIndex != nFieldSelected )
+ if( mnSelectIndex < maFields.size() )
{
- // "recycle" existing functionality
- pDlg->NotifyMouseButtonDown( eType, nFieldSelected );
- pDlg->NotifyMouseButtonUp( OutputToScreenPixel( GetFieldPosition( nDestIndex ) ) );
+ maFields[ mnSelectIndex ].maFuncData = rFuncData;
+ maFields[ mnSelectIndex ].InitFieldName( *mpDialog, meFieldType == PIVOTFIELDTYPE_DATA );
+ Invalidate();
}
}
-void ScDPFieldWindow::MoveFieldRel( SCsCOL nDX, SCsROW nDY )
+bool ScPivotFieldWindow::RemoveSelectedField()
{
- MoveField( CalcNewFieldIndex( nDX, nDY ) );
+ return RemoveField( mnSelectIndex );
}
-//-------------------------------------------------------------------
-
-void __EXPORT ScDPFieldWindow::Paint( const Rectangle& /* rRect */ )
+bool ScPivotFieldWindow::MoveSelectedField( size_t nInsertIndex )
{
- // #124828# hiding the caption is now done from StateChanged
- Redraw();
+ return MoveField( mnSelectIndex, nInsertIndex );
}
-void ScDPFieldWindow::UseMnemonic()
+void ScPivotFieldWindow::NotifyStartTracking()
{
- // Now the FixedText has its mnemonic char. Grab the text and hide the
- // FixedText to be able to handle tabstop and mnemonics separately.
- if( pFtCaption )
- {
- SetText( pFtCaption->GetText() );
- pFtCaption->Hide();
- }
-
- // after reading the mnemonics, tab stop style bits can be updated
- UpdateStyle();
+ // rescue old scrolling index, to be able to restore it when tracking is cancelled
+ mnOldFirstVisIndex = mnFirstVisIndex;
}
-void __EXPORT ScDPFieldWindow::DataChanged( const DataChangedEvent& rDCEvt )
+void ScPivotFieldWindow::NotifyTracking( const Point& rWindowPos )
{
- if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ size_t nFieldIndex = GetDropIndex( rWindowPos );
+
+ // insertion index changed: draw new cursor and exit
+ if( nFieldIndex != mnInsCursorIndex )
{
- GetStyleSettings();
- Redraw();
+ mnInsCursorIndex = nFieldIndex;
+ mnAutoScrollDelay = INITIAL_TRACKING_DELAY;
+ Invalidate();
+ return;
}
- Control::DataChanged( rDCEvt );
-}
-void __EXPORT ScDPFieldWindow::MouseButtonDown( const MouseEvent& rMEvt )
-{
- if( rMEvt.IsLeft() )
+ // insertion index unchanged: countdown for auto scrolling
+ if( mnAutoScrollDelay > 0 )
{
- size_t nIndex = 0;
- if( GetFieldIndex( rMEvt.GetPosPixel(), nIndex ) && IsExistingIndex( nIndex ) )
- {
- GrabFocusWithSel( nIndex );
+ --mnAutoScrollDelay;
+ return;
+ }
- if( rMEvt.GetClicks() == 1 )
- {
- PointerStyle ePtr = pDlg->NotifyMouseButtonDown( eType, nIndex );
- CaptureMouse();
- SetPointer( Pointer( ePtr ) );
- }
- else
- pDlg->NotifyDoubleClick( eType, nIndex );
- }
+ // check if tracking happens on first or last field
+ long nScrollDelta = 0;
+ if( (mnInsCursorIndex > 0) && (mnInsCursorIndex == mnFirstVisIndex) )
+ nScrollDelta = -static_cast< long >( mnLineSize );
+ else if( (mnInsCursorIndex < maFields.size()) && (mnInsCursorIndex == mnFirstVisIndex + mnPageSize) )
+ nScrollDelta = static_cast< long >( mnLineSize );
+ if( nScrollDelta != 0 )
+ {
+ // update mnInsCursorIndex, so it will be drawn at the same position after scrolling
+ mnInsCursorIndex += nScrollDelta;
+ mnFirstVisIndex += nScrollDelta;
+ // delay auto scroll by line size, to slow down scrolling in column/page windows
+ mnAutoScrollDelay = mnLineSize - 1;
+ Invalidate();
}
}
-void __EXPORT ScDPFieldWindow::MouseButtonUp( const MouseEvent& rMEvt )
+void ScPivotFieldWindow::NotifyEndTracking( ScPivotFieldEndTracking eEndType )
{
- if( rMEvt.IsLeft() )
+ if( eEndType != ENDTRACKING_DROP )
+ mnFirstVisIndex = mnOldFirstVisIndex;
+ if( eEndType != ENDTRACKING_SUSPEND )
{
- if( rMEvt.GetClicks() == 1 )
- {
- pDlg->NotifyMouseButtonUp( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
- SetPointer( Pointer( POINTER_ARROW ) );
- }
-
- if( IsMouseCaptured() )
- ReleaseMouse();
+ mnOldFirstVisIndex = PIVOTFIELD_INVALID;
+ mbIsTrackingSource = false;
}
+ mnInsCursorIndex = PIVOTFIELD_INVALID;
+ Invalidate();
}
-void __EXPORT ScDPFieldWindow::MouseMove( const MouseEvent& rMEvt )
+// protected ------------------------------------------------------------------
+
+void ScPivotFieldWindow::Paint( const Rectangle& /*rRect*/ )
{
- if( IsMouseCaptured() )
+ // prepare a virtual device for buffered painting
+ VirtualDevice aVirDev;
+ // #i97623# VirtualDevice is always LTR on construction while other windows derive direction from parent
+ aVirDev.EnableRTL( IsRTLEnabled() );
+ aVirDev.SetMapMode( MAP_PIXEL );
+ aVirDev.SetOutputSizePixel( GetSizePixel() );
+ Font aFont = GetFont();
+ aFont.SetTransparent( true );
+ aVirDev.SetFont( aFont );
+
+ // draw the background and all fields
+ DrawBackground( aVirDev );
+ for( size_t nFieldIndex = mnFirstVisIndex, nEndIndex = mnFirstVisIndex + mnPageSize; nFieldIndex < nEndIndex; ++nFieldIndex )
+ DrawField( aVirDev, nFieldIndex );
+ DrawInsertionCursor( aVirDev );
+ DrawBitmap( Point( 0, 0 ), aVirDev.GetBitmap( Point( 0, 0 ), GetSizePixel() ) );
+
+ // draw field text focus
+ if( HasFocus() && (mnSelectIndex < maFields.size()) && (mnFirstVisIndex <= mnSelectIndex) && (mnSelectIndex < mnFirstVisIndex + mnPageSize) )
{
- PointerStyle ePtr = pDlg->NotifyMouseMove( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
- SetPointer( Pointer( ePtr ) );
+ long nFieldWidth = maFieldSize.Width();
+ long nSelectionWidth = Min( GetTextWidth( maFields[ mnSelectIndex ].maFieldName ) + 4, nFieldWidth - 6 );
+ Rectangle aSelection(
+ GetFieldPosition( mnSelectIndex ) + Point( (nFieldWidth - nSelectionWidth) / 2, 3 ),
+ Size( nSelectionWidth, maFieldSize.Height() - 6 ) );
+ InvertTracking( aSelection, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
}
- size_t nIndex = 0;
- if( GetFieldIndex( rMEvt.GetPosPixel(), nIndex ) && IsShortenedText( nIndex ) )
+
+ // update scrollbar
+ size_t nFieldCount = maFields.size();
+ /* Already show the scrollbar if window is full but no fields are hidden
+ (yet). This gives the user the hint that it is now possible to add more
+ fields to the window. */
+ mrScrollBar.Show( nFieldCount >= mnPageSize );
+ mrScrollBar.Enable( nFieldCount > mnPageSize );
+ if( mrScrollBar.IsVisible() )
{
- Point aPos = OutputToScreenPixel( rMEvt.GetPosPixel() );
- Rectangle aRect( aPos, GetSizePixel() );
- String aHelpText = GetFieldText(nIndex);
- Help::ShowQuickHelp( this, aRect, aHelpText );
+ mrScrollBar.SetRange( Range( 0, static_cast< long >( (nFieldCount - 1) / mnLineSize + 1 ) ) );
+ mrScrollBar.SetThumbPos( static_cast< long >( mnFirstVisIndex / mnLineSize ) );
}
+
+ /* Exclude empty fields from tab chain, but do not disable them. They need
+ to be enabled because they still act as target for field movement via
+ keyboard shortcuts. */
+ WinBits nMask = ~(WB_TABSTOP | WB_NOTABSTOP);
+ SetStyle( (GetStyle() & nMask) | (IsEmpty() ? WB_NOTABSTOP : WB_TABSTOP) );
}
-void __EXPORT ScDPFieldWindow::KeyInput( const KeyEvent& rKEvt )
+void ScPivotFieldWindow::StateChanged( StateChangedType nStateChange )
{
- const KeyCode& rKeyCode = rKEvt.GetKeyCode();
- sal_uInt16 nCode = rKeyCode.GetCode();
- sal_Bool bKeyEvaluated = sal_False;
+ Control::StateChanged( nStateChange );
- if( rKeyCode.IsMod1() && (eType != TYPE_SELECT) )
- {
- bKeyEvaluated = sal_True;
- switch( nCode )
- {
- case KEY_UP: MoveFieldRel( 0, -1 ); break;
- case KEY_DOWN: MoveFieldRel( 0, 1 ); break;
- case KEY_LEFT: MoveFieldRel( -1, 0 ); break;
- case KEY_RIGHT: MoveFieldRel( 1, 0 ); break;
- case KEY_HOME: MoveField( 0 ); break;
- case KEY_END: MoveField( aFieldArr.size() - 1 ); break;
- default: bKeyEvaluated = sal_False;
- }
- }
- else
+ if( nStateChange == STATE_CHANGE_INITSHOW )
{
- bKeyEvaluated = sal_True;
- switch( nCode )
+ /* After the fixed text associated to this control has received its
+ unique mnemonic from VCL dialog initialization code, put this text
+ into the field windows.
+ #124828# Hiding the FixedTexts and clearing the tab stop style bits
+ has to be done after assigning the mnemonics, but Paint() is too
+ late, because the test tool may send key events to the dialog when
+ it isn't visible. Mnemonics are assigned in Dialog::StateChanged()
+ for STATE_CHANGE_INITSHOW, so this can be done immediately
+ afterwards. */
+ if( mpFtCaption )
{
- case KEY_UP: MoveSelection( nCode, 0, -1 ); break;
- case KEY_DOWN: MoveSelection( nCode, 0, 1 ); break;
- case KEY_LEFT: MoveSelection( nCode, -1, 0 ); break;
- case KEY_RIGHT: MoveSelection( nCode, 1, 0 ); break;
- case KEY_HOME: SetSelectionHome(); break;
- case KEY_END: SetSelectionEnd(); break;
- case KEY_DELETE:
- pDlg->NotifyRemoveField( eType, nFieldSelected ); break;
- default: bKeyEvaluated = sal_False;
+ SetText( mpFtCaption->GetText() );
+ mpFtCaption->Hide();
}
}
-
- if( !bKeyEvaluated )
- Control::KeyInput( rKEvt );
}
-void __EXPORT ScDPFieldWindow::GetFocus()
+void ScPivotFieldWindow::DataChanged( const DataChangedEvent& rDCEvt )
{
- Control::GetFocus();
- Redraw();
- if( GetGetFocusFlags() & GETFOCUS_MNEMONIC ) // move field on shortcut
- pDlg->NotifyMoveField( eType );
- else // else change focus
- pDlg->NotifyFieldFocus( eType, sal_True );
-
- if (pAccessible)
- {
- com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xTempAcc = xAccessible;
- if (xTempAcc.is())
- pAccessible->GotFocus();
- else
- pAccessible = NULL;
- }
+ Control::DataChanged( rDCEvt );
+ if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ Invalidate();
}
-void __EXPORT ScDPFieldWindow::LoseFocus()
+void ScPivotFieldWindow::KeyInput( const KeyEvent& rKEvt )
{
- Control::LoseFocus();
- Redraw();
- pDlg->NotifyFieldFocus( eType, sal_False );
+ bool bKeyEvaluated = false;
- if (pAccessible)
+ if( !maFields.empty() )
{
- com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xTempAcc = xAccessible;
- if (xTempAcc.is())
- pAccessible->LostFocus();
+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ sal_uInt16 nCode = rKeyCode.GetCode();
+
+ // do not move fields in selection window
+ if( rKeyCode.IsMod1() && (meFieldType != PIVOTFIELDTYPE_SELECT) )
+ {
+ bKeyEvaluated = true;
+ switch( nCode )
+ {
+ case KEY_UP: MoveSelectedField( mbVertical ? PREV_FIELD : PREV_LINE ); break;
+ case KEY_DOWN: MoveSelectedField( mbVertical ? NEXT_FIELD : NEXT_LINE ); break;
+ case KEY_LEFT: MoveSelectedField( mbVertical ? PREV_LINE : PREV_FIELD ); break;
+ case KEY_RIGHT: MoveSelectedField( mbVertical ? NEXT_LINE : NEXT_FIELD ); break;
+ case KEY_HOME: MoveSelectedField( FIRST_FIELD ); break;
+ case KEY_END: MoveSelectedField( LAST_FIELD ); break;
+ default: bKeyEvaluated = false;
+ }
+ }
else
- pAccessible = NULL;
+ {
+ bKeyEvaluated = true;
+ switch( nCode )
+ {
+ case KEY_UP: MoveSelection( mbVertical ? PREV_FIELD : PREV_LINE ); break;
+ case KEY_DOWN: MoveSelection( mbVertical ? NEXT_FIELD : NEXT_LINE ); break;
+ case KEY_LEFT: MoveSelection( mbVertical ? PREV_LINE : PREV_FIELD ); break;
+ case KEY_RIGHT: MoveSelection( mbVertical ? NEXT_LINE : NEXT_FIELD ); break;
+ case KEY_PAGEUP: MoveSelection( PREV_PAGE ); break;
+ case KEY_PAGEDOWN: MoveSelection( NEXT_PAGE ); break;
+ case KEY_HOME: MoveSelection( FIRST_FIELD ); break;
+ case KEY_END: MoveSelection( LAST_FIELD ); break;
+ // delete field per DEL key - dialog needs to change focus if window becomes empty
+ case KEY_DELETE: RemoveSelectedField(); mpDialog->NotifyFieldRemoved( *this ); break;
+ default: bKeyEvaluated = false;
+ }
+ }
}
-}
-//-------------------------------------------------------------------
+ if( !bKeyEvaluated )
+ Control::KeyInput( rKEvt );
+}
-void ScDPFieldWindow::AddField( const String& rText, size_t nNewIndex )
+void ScPivotFieldWindow::MouseButtonDown( const MouseEvent& rMEvt )
{
- DBG_ASSERT( nNewIndex == aFieldArr.size(), "ScDPFieldWindow::AddField - invalid index" );
- if( IsValidIndex( nNewIndex ) )
+ if( rMEvt.IsLeft() )
{
- aFieldArr.push_back( FieldString( rText, true ) );
- if (pAccessible)
+ size_t nNewSelectIndex = GetFieldIndex( rMEvt.GetPosPixel() );
+ if( nNewSelectIndex < maFields.size() )
{
- com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xTempAcc = xAccessible;
- if (xTempAcc.is())
- pAccessible->AddField(nNewIndex);
+ // grabbing after GetFieldIndex() will prevent to focus empty window
+ GrabFocusAndSelect( nNewSelectIndex );
+ if( rMEvt.GetClicks() == 1 )
+ {
+ // one click: start tracking
+ mbIsTrackingSource = true;
+ mnOldFirstVisIndex = mnFirstVisIndex;
+ mpDialog->NotifyStartTracking( *this );
+ }
else
- pAccessible = NULL;
+ {
+ // two clicks: open field options dialog
+ mpDialog->NotifyDoubleClick( *this );
+ }
}
}
}
-void ScDPFieldWindow::DelField( size_t nDelIndex )
+void ScPivotFieldWindow::RequestHelp( const HelpEvent& rHEvt )
{
- if( IsExistingIndex( nDelIndex ) )
+ if( (rHEvt.GetMode() & HELPMODE_QUICK) != 0 )
{
- if (pAccessible) // before decrement fieldcount
+ // show a tooltip with full field name, if field text is clipped
+ size_t nFieldIndex = GetFieldIndex( rHEvt.GetMousePosPixel() - GetPosPixel() );
+ if( (nFieldIndex < maFields.size()) && maFields[ nFieldIndex ].mbClipped )
{
- com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xTempAcc = xAccessible;
- if (xTempAcc.is())
- pAccessible->RemoveField(nDelIndex);
- else
- pAccessible = NULL;
+ Rectangle aRect( rHEvt.GetMousePosPixel(), GetSizePixel() );
+ Help::ShowQuickHelp( this, aRect, maFields[ nFieldIndex ].maFieldName );
+ return;
}
- aFieldArr.erase( aFieldArr.begin() + nDelIndex );
- Redraw();
}
+ Control::RequestHelp( rHEvt );
}
-void ScDPFieldWindow::ClearFields()
+void ScPivotFieldWindow::GetFocus()
{
- if( eType == TYPE_SELECT || eType == TYPE_PAGE || eType == TYPE_COL || eType == TYPE_ROW || eType == TYPE_DATA)
- {
- com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xTempAcc = xAccessible;
- if (!xTempAcc.is() && pAccessible)
- pAccessible = NULL;
- if (pAccessible)
- for( size_t nIdx = aFieldArr.size(); nIdx > 0; --nIdx )
- pAccessible->RemoveField( nIdx - 1 );
+ Control::GetFocus();
+ Invalidate();
+ ::rtl::Reference< ScAccessibleDataPilotControl > xAcc = GetAccessibleControl();
+ if( xAcc.is() )
+ xAcc->GotFocus();
+}
- aFieldArr.clear();
- }
+void ScPivotFieldWindow::LoseFocus()
+{
+ Control::LoseFocus();
+ Invalidate();
+ ::rtl::Reference< ScAccessibleDataPilotControl > xAcc = GetAccessibleControl();
+ if( xAcc.is() )
+ xAcc->LostFocus();
+}
+
+uno::Reference< accessibility::XAccessible > ScPivotFieldWindow::CreateAccessible()
+{
+ mpAccessible = new ScAccessibleDataPilotControl( GetAccessibleParentWindow()->GetAccessible(), this );
+ uno::Reference< accessibility::XAccessible > xReturn( mpAccessible );
+ mpAccessible->Init();
+ mxAccessible = xReturn;
+ return xReturn;
+}
+
+// private --------------------------------------------------------------------
+
+size_t ScPivotFieldWindow::RecalcVisibleIndex( size_t nSelectIndex ) const
+{
+ // calculate a scrolling offset that shows the selected field
+ size_t nNewFirstVisIndex = mnFirstVisIndex;
+ if( nSelectIndex < nNewFirstVisIndex )
+ nNewFirstVisIndex = static_cast< size_t >( (nSelectIndex / mnLineSize) * mnLineSize );
+ else if( nSelectIndex >= nNewFirstVisIndex + mnPageSize )
+ nNewFirstVisIndex = static_cast< size_t >( (nSelectIndex / mnLineSize + 1) * mnLineSize ) - mnPageSize;
+ // check if there are complete empty lines in the bottom/right
+ size_t nMaxFirstVisIndex = (maFields.size() <= mnPageSize) ? 0 : (((maFields.size() - 1) / mnLineSize + 1) * mnLineSize - mnPageSize);
+ return ::std::min( nNewFirstVisIndex, nMaxFirstVisIndex );
}
-void ScDPFieldWindow::SetFieldText( const String& rText, size_t nIndex )
+void ScPivotFieldWindow::SetSelectionUnchecked( size_t nSelectIndex, size_t nFirstVisIndex )
{
- if( IsExistingIndex( nIndex ) )
+ if( !maFields.empty() && (nSelectIndex < maFields.size()) )
{
- aFieldArr[ nIndex ] = FieldString( rText, true );
- Redraw();
+ bool bScrollPosChanged = mnFirstVisIndex != nFirstVisIndex;
+ bool bSelectionChanged = mnSelectIndex != nSelectIndex;
- if (pAccessible)
+ sal_Int32 nOldSelected = static_cast< sal_Int32 >( mnSelectIndex );
+ mnFirstVisIndex = nFirstVisIndex;
+ mnSelectIndex = nSelectIndex;
+
+ if( bScrollPosChanged || bSelectionChanged )
+ Invalidate();
+
+ // TODO: accessibility action for changed scrolling position?
+
+ // notify accessibility object about changed selection
+ if( bSelectionChanged && HasFocus() )
{
- com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xTempAcc = xAccessible;
- if (xTempAcc.is())
- pAccessible->FieldNameChange(nIndex);
- else
- pAccessible = NULL;
+ ::rtl::Reference< ScAccessibleDataPilotControl > xAcc = GetAccessibleControl();
+ if( xAcc.is() )
+ xAcc->FieldFocusChange( nOldSelected, static_cast< sal_Int32 >( mnSelectIndex ) );
}
}
}
-const String& ScDPFieldWindow::GetFieldText( size_t nIndex ) const
+void ScPivotFieldWindow::MoveSelection( size_t nSelectIndex )
{
- if( IsExistingIndex( nIndex ) )
- return aFieldArr[ nIndex ].first;
- return EMPTY_STRING;
+ if( nSelectIndex < maFields.size() )
+ SetSelectionUnchecked( nSelectIndex, RecalcVisibleIndex( nSelectIndex ) );
}
-//-------------------------------------------------------------------
-
-bool ScDPFieldWindow::AddField( const String& rText, const Point& rPos, size_t& rnIndex )
+void ScPivotFieldWindow::MoveSelection( MoveType eMoveType )
{
- if ( aFieldArr.size() == nFieldSize )
- return sal_False;
+ if( maFields.empty() )
+ return;
- size_t nNewIndex = 0;
- if( GetFieldIndex( rPos, nNewIndex ) )
+ size_t nLastIndex = maFields.size() - 1;
+ size_t nNewSelectIndex = mnSelectIndex;
+ switch( eMoveType )
{
- if( nNewIndex > aFieldArr.size() )
- nNewIndex = aFieldArr.size();
-
- aFieldArr.insert( aFieldArr.begin() + nNewIndex, FieldString( rText, true ) );
- nFieldSelected = nNewIndex;
- Redraw();
- rnIndex = nNewIndex;
+ case PREV_FIELD:
+ nNewSelectIndex = (nNewSelectIndex > 0) ? (nNewSelectIndex - 1) : 0;
+ break;
+ case NEXT_FIELD:
+ nNewSelectIndex = (nNewSelectIndex < nLastIndex) ? (nNewSelectIndex + 1) : nLastIndex;
+ break;
+ case PREV_LINE:
+ nNewSelectIndex = (nNewSelectIndex > mnLineSize) ? (nNewSelectIndex - mnLineSize) : 0;
+ break;
+ case NEXT_LINE:
+ nNewSelectIndex = (nNewSelectIndex + mnLineSize < nLastIndex) ? (nNewSelectIndex + mnLineSize) : nLastIndex;
+ break;
+ case PREV_PAGE:
+ nNewSelectIndex = (nNewSelectIndex > mnPageSize) ? (nNewSelectIndex - mnPageSize) : 0;
+ break;
+ case NEXT_PAGE:
+ nNewSelectIndex = (nNewSelectIndex + mnPageSize < nLastIndex) ? (nNewSelectIndex + mnPageSize) : nLastIndex;
+ break;
+ case FIRST_FIELD:
+ nNewSelectIndex = 0;
+ break;
+ case LAST_FIELD:
+ nNewSelectIndex = nLastIndex;
+ break;
+ }
- if (pAccessible)
- {
- com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xTempAcc = xAccessible;
- if (xTempAcc.is())
- pAccessible->AddField(nNewIndex);
- else
- pAccessible = NULL;
- }
+ // SetSelectionUnchecked() redraws the control and updates the scrollbar
+ SetSelectionUnchecked( nNewSelectIndex, RecalcVisibleIndex( nNewSelectIndex ) );
+}
- return true;
+void ScPivotFieldWindow::MoveSelectedField( MoveType eMoveType )
+{
+ if( mnSelectIndex < maFields.size() )
+ {
+ // find position to insert the field by changing the selection first
+ size_t nOldSelectIndex = mnSelectIndex;
+ MoveSelection( eMoveType );
+ MoveField( nOldSelectIndex, (nOldSelectIndex < mnSelectIndex) ? (mnSelectIndex + 1) : mnSelectIndex );
}
+}
- return false;
+void ScPivotFieldWindow::InsertFieldUnchecked( size_t nInsertIndex, const ScPivotWindowField& rField )
+{
+ maFields.insert( maFields.begin() + nInsertIndex, rField );
+ ::rtl::Reference< ScAccessibleDataPilotControl > xAcc = GetAccessibleControl();
+ if( xAcc.is() )
+ xAcc->AddField( static_cast< sal_Int32 >( nInsertIndex ) );
+}
+
+void ScPivotFieldWindow::RemoveFieldUnchecked( size_t nRemoveIndex )
+{
+ ::rtl::Reference< ScAccessibleDataPilotControl > xAcc = GetAccessibleControl();
+ if( xAcc.is() )
+ xAcc->RemoveField( static_cast< sal_Int32 >( nRemoveIndex ) );
+ maFields.erase( maFields.begin() + nRemoveIndex );
}
-void ScDPFieldWindow::GetExistingIndex( const Point& rPos, size_t& rnIndex )
+void ScPivotFieldWindow::DrawBackground( OutputDevice& rDev )
{
- if( !aFieldArr.empty() && (eType != TYPE_SELECT) && GetFieldIndex( rPos, rnIndex ) )
+ Size aDevSize = rDev.GetOutputSizePixel();
+ const StyleSettings& rStyleSett = GetSettings().GetStyleSettings();
+
+ if( meFieldType == PIVOTFIELDTYPE_SELECT )
{
- if( rnIndex >= aFieldArr.size() )
- rnIndex = aFieldArr.size() - 1;
+ rDev.SetLineColor();
+ rDev.SetFillColor( rStyleSett.GetFaceColor() );
+ rDev.DrawRect( Rectangle( Point( 0, 0 ), aDevSize ) );
}
else
- rnIndex = 0;
+ {
+ rDev.SetLineColor( rStyleSett.GetWindowTextColor() );
+ rDev.SetFillColor( rStyleSett.GetWindowColor() );
+ rDev.DrawRect( Rectangle( Point( 0, 0 ), aDevSize ) );
+
+ /* Draw the caption text. This needs some special handling, because we
+ support hard line breaks here. This part will draw each line of the
+ text for itself. */
+ rDev.SetTextColor( rStyleSett.GetWindowTextColor() );
+ xub_StrLen nTokenCnt = GetText().GetTokenCount( '\n' );
+ long nY = (aDevSize.Height() - nTokenCnt * rDev.GetTextHeight()) / 2;
+ for( xub_StrLen nToken = 0, nStringIx = 0; nToken < nTokenCnt; ++nToken )
+ {
+ String aLine = GetText().GetToken( 0, '\n', nStringIx );
+ Point aLinePos( (aDevSize.Width() - rDev.GetCtrlTextWidth( aLine )) / 2, nY );
+ rDev.DrawCtrlText( aLinePos, aLine );
+ nY += rDev.GetTextHeight();
+ }
+ }
}
-String ScDPFieldWindow::GetDescription() const
+void ScPivotFieldWindow::DrawField( OutputDevice& rDev, size_t nFieldIndex )
{
- String sDescription;
- switch( eType )
+ if( (nFieldIndex < maFields.size()) && (mnFirstVisIndex <= nFieldIndex) && (nFieldIndex < mnFirstVisIndex + mnPageSize) )
{
- case TYPE_COL:
- sDescription = ScResId(STR_ACC_DATAPILOT_COL_DESCR);
- break;
- case TYPE_ROW:
- sDescription = ScResId(STR_ACC_DATAPILOT_ROW_DESCR);
- break;
- case TYPE_DATA:
- sDescription = ScResId(STR_ACC_DATAPILOT_DATA_DESCR);
- break;
- case TYPE_SELECT:
- sDescription = ScResId(STR_ACC_DATAPILOT_SEL_DESCR);
- break;
- default:
+ // draw the button
+ Point aFieldPos = GetFieldPosition( nFieldIndex );
+ bool bFocus = HasFocus() && (nFieldIndex == mnSelectIndex);
+ DecorationView aDecoView( &rDev );
+ aDecoView.DrawButton( Rectangle( aFieldPos, maFieldSize ), bFocus ? BUTTON_DRAW_DEFAULT : 0 );
+
+ // #i31600# if text is too long, cut and add ellipsis
+ const OUString& rFullText = maFields[ nFieldIndex ].maFieldName;
+ OUString aClippedText = rFullText;
+ long nLabelWidth = rDev.GetTextWidth( rFullText );
+ if( (maFields[ nFieldIndex ].mbClipped = nLabelWidth + 6 > maFieldSize.Width()) == true )
{
- // added to avoid warnings
+ sal_Int32 nMinLen = 0;
+ sal_Int32 nMaxLen = rFullText.getLength();
+ bool bFits = false;
+ do
+ {
+ sal_Int32 nCurrLen = (nMinLen + nMaxLen) / 2;
+ aClippedText = rFullText.copy( 0, nCurrLen ) + OUString( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
+ nLabelWidth = rDev.GetTextWidth( aClippedText );
+ bFits = nLabelWidth + 6 <= maFieldSize.Width();
+ (bFits ? nMinLen : nMaxLen) = nCurrLen;
+ }
+ while( !bFits || (nMinLen + 1 < nMaxLen) );
}
+
+ // draw the button text
+ Point aLabelOffset( (maFieldSize.Width() - nLabelWidth) / 2, ::std::max< long >( (maFieldSize.Height() - rDev.GetTextHeight()) / 2, 3 ) );
+ rDev.SetTextColor( GetSettings().GetStyleSettings().GetButtonTextColor() );
+ rDev.DrawText( aFieldPos + aLabelOffset, aClippedText );
}
- return sDescription;
}
-::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ScDPFieldWindow::CreateAccessible()
+void ScPivotFieldWindow::DrawInsertionCursor( OutputDevice& rDev )
{
- pAccessible =
- new ScAccessibleDataPilotControl(GetAccessibleParentWindow()->GetAccessible(), this);
+ if( (mnInsCursorIndex <= maFields.size()) && (mnFirstVisIndex <= mnInsCursorIndex) && (mnInsCursorIndex <= mnFirstVisIndex + mnPageSize) &&
+ (!mbIsTrackingSource || (mnInsCursorIndex < mnSelectIndex) || (mnInsCursorIndex > mnSelectIndex + 1)) )
+ {
+ Color aTextColor = GetSettings().GetStyleSettings().GetButtonTextColor();
+ rDev.SetLineColor( aTextColor );
+ rDev.SetFillColor( aTextColor );
- com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible > xReturn = pAccessible;
+ bool bVerticalCursor = mnColCount > 1;
+ long nCursorLength = bVerticalCursor ? maFieldSize.Height() : maFieldSize.Width();
- pAccessible->Init();
- xAccessible = xReturn;
+ bool bEndOfLastField = mnInsCursorIndex == mnFirstVisIndex + mnPageSize;
+ Point aMainLinePos = GetFieldPosition( bEndOfLastField ? (mnInsCursorIndex - 1) : mnInsCursorIndex );
+ if( bEndOfLastField )
+ (bVerticalCursor ? aMainLinePos.X() : aMainLinePos.Y()) += ((bVerticalCursor ? maFieldSize.Width() : maFieldSize.Height()) - CURSOR_WIDTH);
+ else if( (bVerticalCursor ? aMainLinePos.X() : aMainLinePos.Y()) > 0 )
+ (bVerticalCursor ? aMainLinePos.X() : aMainLinePos.Y()) -= ((CURSOR_WIDTH + 1) / 2);
+ Size aMainLineSize( bVerticalCursor ? CURSOR_WIDTH : nCursorLength, bVerticalCursor ? nCursorLength : CURSOR_WIDTH );
+ rDev.DrawRect( Rectangle( aMainLinePos, aMainLineSize ) );
- return xReturn;
+ Point aSubLinePos = aMainLinePos;
+ (bVerticalCursor ? aSubLinePos.X() : aSubLinePos.Y()) -= CURSOR_WIDTH;
+ Size aSubLineSize( bVerticalCursor ? (3 * CURSOR_WIDTH) : CURSOR_WIDTH, bVerticalCursor ? CURSOR_WIDTH : (3 * CURSOR_WIDTH) );
+ rDev.DrawRect( Rectangle( aSubLinePos, aSubLineSize ) );
+
+ (bVerticalCursor ? aSubLinePos.Y() : aSubLinePos.X()) += (nCursorLength - CURSOR_WIDTH);
+ rDev.DrawRect( Rectangle( aSubLinePos, aSubLineSize ) );
+ }
}
-//===================================================================
+::rtl::Reference< ScAccessibleDataPilotControl > ScPivotFieldWindow::GetAccessibleControl()
+{
+ ::rtl::Reference< ScAccessibleDataPilotControl > xAccImpl;
+ if( mpAccessible )
+ {
+ // try to resolve the weak reference mxAccessible
+ uno::Reference< accessibility::XAccessible > xAcc = mxAccessible;
+ if( xAcc.is() )
+ xAccImpl.set( mpAccessible ); // the rtl reference keeps the object alive
+ else
+ mpAccessible = 0; // object is dead, forget the pointer
+ }
+ return xAccImpl;
+ }
+
+// handlers -------------------------------------------------------------------
+
+IMPL_LINK( ScPivotFieldWindow, ScrollHdl, ScrollBar*, pScrollBar )
+{
+ // scrollbar may return negative values, if it is too small
+ long nThumbPos = pScrollBar->GetThumbPos();
+ if( nThumbPos >= 0 )
+ {
+ size_t nNewFirstVisIndex = static_cast< size_t >( nThumbPos * mnLineSize );
+ // keep the selection index on same relative position inside row/column
+ size_t nSelectLineOffset = mnSelectIndex % mnLineSize;
+ size_t nNewSelectIndex = mnSelectIndex;
+ if( nNewSelectIndex < nNewFirstVisIndex )
+ nNewSelectIndex = nNewFirstVisIndex + nSelectLineOffset;
+ else if( nNewSelectIndex >= nNewFirstVisIndex + mnPageSize )
+ nNewSelectIndex = nNewFirstVisIndex + mnPageSize - mnLineSize + nSelectLineOffset;
+ nNewSelectIndex = ::std::min( nNewSelectIndex, maFields.size() - 1 );
+ SetSelectionUnchecked( nNewSelectIndex, nNewFirstVisIndex );
+ }
+ GrabFocus();
+ return 0;
+}
+// ============================================================================