| /************************************************************** |
| * |
| * 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_sc.hxx" |
| |
| #include "pvlaydlg.hxx" |
| |
| #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> |
| #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp> |
| |
| #include <sfx2/dispatch.hxx> |
| #include <vcl/mnemonic.hxx> |
| #include <vcl/msgbox.hxx> |
| |
| #include "dbdocfun.hxx" |
| #include "uiitems.hxx" |
| #include "rangeutl.hxx" |
| #include "document.hxx" |
| #include "viewdata.hxx" |
| #include "tabvwsh.hxx" |
| #include "reffact.hxx" |
| #include "scresid.hxx" |
| #include "globstr.hrc" |
| #include "pivot.hrc" |
| #include "dpobject.hxx" |
| #include "dpsave.hxx" |
| #include "dpshttab.hxx" |
| #include "scmod.hxx" |
| |
| #include "sc.hrc" //CHINA001 |
| #include "scabstdlg.hxx" //CHINA001 |
| |
| // ============================================================================ |
| |
| using namespace ::com::sun::star; |
| using ::rtl::OUString; |
| |
| // ============================================================================ |
| |
| namespace { |
| |
| const sal_uInt16 STD_FORMAT = sal_uInt16( SCA_VALID | SCA_TAB_3D | SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB_ABSOLUTE ); |
| |
| OUString lclGetNameWithoutMnemonic( const FixedText& rFixedText ) |
| { |
| return MnemonicGenerator::EraseAllMnemonicChars( rFixedText.GetText() ); |
| } |
| |
| } // namespace |
| |
| // ============================================================================ |
| |
| ScPivotLayoutDlg::ScPivotLayoutDlg( SfxBindings* pB, SfxChildWindow* pCW, Window* pParent, const ScDPObject& rDPObject ) : |
| |
| ScAnyRefDlg( pB, pCW, pParent, RID_SCDLG_PIVOT_LAYOUT ), |
| |
| maFlLayout( this, ScResId( FL_LAYOUT ) ), |
| maScrPage( this, ScResId( SCROLL_PAGE ) ), |
| maFtPage( this, ScResId( FT_PAGE ) ), |
| maWndPage( this, ScResId( WND_PAGE ), maScrPage, &maFtPage, lclGetNameWithoutMnemonic( maFtPage ), PIVOTFIELDTYPE_PAGE, HID_SC_DPLAY_PAGE, POINTER_PIVOT_FIELD, 5, 2, 1, 0 ), |
| maScrCol( this, ScResId( SCROLL_COL ) ), |
| maFtCol( this, ScResId( FT_COL ) ), |
| maWndCol( this, ScResId( WND_COL ), maScrCol, &maFtCol, lclGetNameWithoutMnemonic( maFtCol ), PIVOTFIELDTYPE_COL, HID_SC_DPLAY_COLUMN, POINTER_PIVOT_COL, 4, 2, 1, 0 ), |
| maScrRow( this, ScResId( SCROLL_ROW ) ), |
| maFtRow( this, ScResId( FT_ROW ) ), |
| maWndRow( this, ScResId( WND_ROW ), maScrRow, &maFtRow, lclGetNameWithoutMnemonic( maFtRow ), PIVOTFIELDTYPE_ROW, HID_SC_DPLAY_ROW, POINTER_PIVOT_ROW, 1, 8, 1, 0 ), |
| maScrData( this, ScResId( SCROLL_DATA ) ), |
| maFtData( this, ScResId( FT_DATA ) ), |
| maWndData( this, ScResId( WND_DATA ), maScrData, &maFtData, lclGetNameWithoutMnemonic( maFtData ), PIVOTFIELDTYPE_DATA, HID_SC_DPLAY_DATA, POINTER_PIVOT_FIELD, 1, 8, 4, 0 ), |
| maFlSelect( this, ScResId( FL_SELECT ) ), |
| maScrSelect( this, ScResId( WND_HSCROLL ) ), |
| maWndSelect( this, ScResId( WND_SELECT ), maScrSelect, 0, String( ScResId( STR_SELECT ) ), PIVOTFIELDTYPE_SELECT, HID_SC_DPLAY_SELECT, POINTER_PIVOT_FIELD, 2, 10, 1, 2 ), |
| maFtInfo( this, ScResId( FT_INFO ) ), |
| |
| maFlAreas( this, ScResId( FL_OUTPUT ) ), |
| maFtInArea( this, ScResId( FT_INAREA) ), |
| maEdInPos( this, this, ScResId( ED_INAREA) ), |
| maRbInPos( this, ScResId( RB_INAREA ), &maEdInPos, this ), |
| maLbOutPos( this, ScResId( LB_OUTAREA ) ), |
| maFtOutArea( this, ScResId( FT_OUTAREA ) ), |
| maEdOutPos( this, this, ScResId( ED_OUTAREA ) ), |
| maRbOutPos( this, ScResId( RB_OUTAREA ), &maEdOutPos, this ), |
| maBtnIgnEmptyRows( this, ScResId( BTN_IGNEMPTYROWS ) ), |
| maBtnDetectCat( this, ScResId( BTN_DETECTCAT ) ), |
| maBtnTotalCol( this, ScResId( BTN_TOTALCOL ) ), |
| maBtnTotalRow( this, ScResId( BTN_TOTALROW ) ), |
| maBtnFilter( this, ScResId( BTN_FILTER ) ), |
| maBtnDrillDown( this, ScResId( BTN_DRILLDOWN ) ), |
| |
| maBtnOk( this, ScResId( BTN_OK ) ), |
| maBtnCancel( this, ScResId( BTN_CANCEL ) ), |
| maBtnHelp( this, ScResId( BTN_HELP ) ), |
| maBtnRemove( this, ScResId( BTN_REMOVE ) ), |
| maBtnOptions( this, ScResId( BTN_OPTIONS ) ), |
| maBtnMore( this, ScResId( BTN_MORE ) ), |
| |
| mxDlgDPObject( new ScDPObject( rDPObject ) ), |
| mpViewData( ((ScTabViewShell*)SfxViewShell::Current())->GetViewData() ), |
| mpDoc( ((ScTabViewShell*)SfxViewShell::Current())->GetViewData()->GetDocument() ), |
| mpFocusWindow( 0 ), |
| mpTrackingWindow( 0 ), |
| mpDropWindow( 0 ), |
| mpActiveEdit( 0 ), |
| mbRefInputMode( false ) |
| { |
| DBG_ASSERT( mpViewData && mpDoc, "ScPivotLayoutDlg::ScPivotLayoutDlg - missing document or view data" ); |
| |
| mxDlgDPObject->SetAlive( true ); // needed to get structure information |
| mxDlgDPObject->FillOldParam( maPivotData ); |
| mxDlgDPObject->FillLabelData( maPivotData ); |
| |
| maBtnRemove.SetClickHdl( LINK( this, ScPivotLayoutDlg, ClickHdl ) ); |
| maBtnOptions.SetClickHdl( LINK( this, ScPivotLayoutDlg, ClickHdl ) ); |
| |
| // PIVOT_MAXFUNC defined in sc/inc/dpglobal.hxx |
| maFuncNames.reserve( PIVOT_MAXFUNC ); |
| for( sal_uInt16 i = 1; i <= PIVOT_MAXFUNC; ++i ) |
| maFuncNames.push_back( String( ScResId( i ) ) ); |
| |
| maBtnMore.AddWindow( &maFlAreas ); |
| maBtnMore.AddWindow( &maFtInArea ); |
| maBtnMore.AddWindow( &maEdInPos ); |
| maBtnMore.AddWindow( &maRbInPos ); |
| maBtnMore.AddWindow( &maFtOutArea ); |
| maBtnMore.AddWindow( &maLbOutPos ); |
| maBtnMore.AddWindow( &maEdOutPos ); |
| maBtnMore.AddWindow( &maRbOutPos ); |
| maBtnMore.AddWindow( &maBtnIgnEmptyRows ); |
| maBtnMore.AddWindow( &maBtnDetectCat ); |
| maBtnMore.AddWindow( &maBtnTotalCol ); |
| maBtnMore.AddWindow( &maBtnTotalRow ); |
| maBtnMore.AddWindow( &maBtnFilter ); |
| maBtnMore.AddWindow( &maBtnDrillDown ); |
| maBtnMore.SetClickHdl( LINK( this, ScPivotLayoutDlg, MoreClickHdl ) ); |
| |
| if( mxDlgDPObject->GetSheetDesc() ) |
| { |
| maEdInPos.Enable(); |
| maRbInPos.Enable(); |
| ScRange aRange = mxDlgDPObject->GetSheetDesc()->aSourceRange; |
| String aString; |
| aRange.Format( aString, SCR_ABS_3D, mpDoc, mpDoc->GetAddressConvention() ); |
| maEdInPos.SetText( aString ); |
| } |
| else |
| { |
| // data is not reachable, so could be a remote database |
| maEdInPos.Disable(); |
| maRbInPos.Disable(); |
| } |
| |
| // #i29203# align right border of page window with data window |
| long nPagePosX = maWndData.GetPosPixel().X() + maWndData.GetSizePixel().Width() - maWndPage.GetSizePixel().Width(); |
| maWndPage.SetPosPixel( Point( nPagePosX, maWndPage.GetPosPixel().Y() ) ); |
| maScrPage.SetPosPixel( Point( maScrData.GetPosPixel().X(), maScrPage.GetPosPixel().Y() ) ); |
| |
| InitFieldWindows(); |
| |
| maLbOutPos.SetSelectHdl( LINK( this, ScPivotLayoutDlg, SelAreaHdl ) ); |
| maEdOutPos.SetModifyHdl( LINK( this, ScPivotLayoutDlg, EdOutModifyHdl ) ); |
| maEdInPos.SetModifyHdl( LINK( this, ScPivotLayoutDlg, EdInModifyHdl ) ); |
| maBtnOk.SetClickHdl( LINK( this, ScPivotLayoutDlg, OkHdl ) ); |
| maBtnCancel.SetClickHdl( LINK( this, ScPivotLayoutDlg, CancelHdl ) ); |
| |
| if( mpViewData && mpDoc ) |
| { |
| /* |
| * Aus den RangeNames des Dokumentes werden nun die |
| * in einem Zeiger-Array gemerkt, bei denen es sich |
| * um sinnvolle Bereiche handelt |
| */ |
| |
| maLbOutPos.Clear(); |
| maLbOutPos.InsertEntry( String( ScResId( SCSTR_UNDEFINED ) ), 0 ); |
| maLbOutPos.InsertEntry( String( ScResId( SCSTR_NEWTABLE ) ), 1 ); |
| |
| ScAreaNameIterator aIter( mpDoc ); |
| String aName; |
| ScRange aRange; |
| String aRefStr; |
| while ( aIter.Next( aName, aRange ) ) |
| { |
| if ( !aIter.WasDBName() ) // hier keine DB-Bereiche ! |
| { |
| sal_uInt16 nInsert = maLbOutPos.InsertEntry( aName ); |
| |
| aRange.aStart.Format( aRefStr, SCA_ABS_3D, mpDoc, mpDoc->GetAddressConvention() ); |
| maLbOutPos.SetEntryData( nInsert, new String( aRefStr ) ); |
| } |
| } |
| } |
| |
| if ( maPivotData.nTab != MAXTAB+1 ) |
| { |
| String aStr; |
| ScAddress( maPivotData.nCol, |
| maPivotData.nRow, |
| maPivotData.nTab ).Format( aStr, STD_FORMAT, mpDoc, mpDoc->GetAddressConvention() ); |
| maEdOutPos.SetText( aStr ); |
| EdOutModifyHdl( 0 ); |
| } |
| else |
| { |
| maLbOutPos.SelectEntryPos( maLbOutPos.GetEntryCount()-1 ); |
| SelAreaHdl(NULL); |
| } |
| |
| maBtnIgnEmptyRows.Check( maPivotData.bIgnoreEmptyRows ); |
| maBtnDetectCat.Check( maPivotData.bDetectCategories ); |
| maBtnTotalCol.Check( maPivotData.bMakeTotalCol ); |
| maBtnTotalRow.Check( maPivotData.bMakeTotalRow ); |
| |
| const ScDPSaveData* pSaveData = mxDlgDPObject->GetSaveData(); |
| maBtnFilter.Check( !pSaveData || pSaveData->GetFilterButton() ); |
| maBtnDrillDown.Check( !pSaveData || pSaveData->GetDrillDown() ); |
| |
| // child event listener handles field movement when keyboard shortcut is pressed |
| AddChildEventListener( LINK( this, ScPivotLayoutDlg, ChildEventListener ) ); |
| GrabFieldFocus( maWndSelect ); |
| |
| FreeResource(); |
| } |
| |
| ScPivotLayoutDlg::~ScPivotLayoutDlg() |
| { |
| RemoveChildEventListener( LINK( this, ScPivotLayoutDlg, ChildEventListener ) ); |
| |
| for( sal_uInt16 i = 2, nEntries = maLbOutPos.GetEntryCount(); i < nEntries; ++i ) |
| delete (String*)maLbOutPos.GetEntryData( i ); |
| } |
| |
| ScDPLabelData* ScPivotLayoutDlg::GetLabelData( SCCOL nCol, size_t* pnIndex ) |
| { |
| ScDPLabelData* pLabelData = 0; |
| for( ScDPLabelDataVector::iterator aIt = maLabelData.begin(), aEnd = maLabelData.end(); !pLabelData && (aIt != aEnd); ++aIt ) |
| { |
| if( aIt->mnCol == nCol ) |
| { |
| pLabelData = &*aIt; |
| if( pnIndex ) |
| *pnIndex = aIt - maLabelData.begin(); |
| } |
| } |
| return pLabelData; |
| } |
| |
| String ScPivotLayoutDlg::GetFuncString( sal_uInt16& rnFuncMask, bool bIsValue ) |
| { |
| String aStr; |
| |
| if( (rnFuncMask == PIVOT_FUNC_NONE) || (rnFuncMask == PIVOT_FUNC_AUTO) ) |
| { |
| if( bIsValue ) |
| { |
| aStr = GetFuncName( PIVOTSTR_SUM ); |
| rnFuncMask = PIVOT_FUNC_SUM; |
| } |
| else |
| { |
| aStr = GetFuncName( PIVOTSTR_COUNT ); |
| rnFuncMask = PIVOT_FUNC_COUNT; |
| } |
| } |
| else if( rnFuncMask == PIVOT_FUNC_SUM ) aStr = GetFuncName( PIVOTSTR_SUM ); |
| else if( rnFuncMask == PIVOT_FUNC_COUNT ) aStr = GetFuncName( PIVOTSTR_COUNT ); |
| else if( rnFuncMask == PIVOT_FUNC_AVERAGE ) aStr = GetFuncName( PIVOTSTR_AVG ); |
| else if( rnFuncMask == PIVOT_FUNC_MAX ) aStr = GetFuncName( PIVOTSTR_MAX ); |
| else if( rnFuncMask == PIVOT_FUNC_MIN ) aStr = GetFuncName( PIVOTSTR_MIN ); |
| else if( rnFuncMask == PIVOT_FUNC_PRODUCT ) aStr = GetFuncName( PIVOTSTR_PROD ); |
| else if( rnFuncMask == PIVOT_FUNC_COUNT_NUM ) aStr = GetFuncName( PIVOTSTR_COUNT2 ); |
| else if( rnFuncMask == PIVOT_FUNC_STD_DEV ) aStr = GetFuncName( PIVOTSTR_DEV ); |
| else if( rnFuncMask == PIVOT_FUNC_STD_DEVP ) aStr = GetFuncName( PIVOTSTR_DEV2 ); |
| else if( rnFuncMask == PIVOT_FUNC_STD_VAR ) aStr = GetFuncName( PIVOTSTR_VAR ); |
| else if( rnFuncMask == PIVOT_FUNC_STD_VARP ) aStr = GetFuncName( PIVOTSTR_VAR2 ); |
| else |
| { |
| aStr = ScGlobal::GetRscString( STR_TABLE_ERGEBNIS ); |
| aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " - " ) ); |
| } |
| |
| return aStr; |
| } |
| |
| void ScPivotLayoutDlg::NotifyStartTracking( ScPivotFieldWindow& rSourceWindow ) |
| { |
| mpTrackingWindow = &rSourceWindow; |
| mpDropWindow = 0; |
| rSourceWindow.NotifyStartTracking(); |
| StartTracking( STARTTRACK_BUTTONREPEAT ); |
| SetPointer( Pointer( rSourceWindow.GetDropPointerStyle() ) ); |
| } |
| |
| void ScPivotLayoutDlg::NotifyDoubleClick( ScPivotFieldWindow& rSourceWindow ) |
| { |
| // nothing to do on double-click in selection window |
| if( rSourceWindow.GetType() == PIVOTFIELDTYPE_SELECT ) |
| return; |
| |
| const ScPivotFuncData* pFuncData = rSourceWindow.GetSelectedFuncData(); |
| DBG_ASSERT( pFuncData, "ScPivotLayoutDlg::NotifyDoubleClick - invalid selection" ); |
| if( !pFuncData ) |
| return; |
| |
| ScDPLabelData* pLabelData = GetLabelData( pFuncData->mnCol ); |
| DBG_ASSERT( pLabelData, "ScPivotLayoutDlg::NotifyDoubleClick - missing label data" ); |
| if( !pLabelData ) |
| return; |
| |
| ScAbstractDialogFactory* pFactory = ScAbstractDialogFactory::Create(); |
| DBG_ASSERT( pFactory, "ScPivotLayoutDlg::NotifyDoubleClick - ScAbstractDialogFactory creation failed" ); |
| if( !pFactory ) |
| return; |
| |
| if( rSourceWindow.GetType() == PIVOTFIELDTYPE_DATA ) |
| { |
| ::std::auto_ptr< AbstractScDPFunctionDlg > xDlg( pFactory->CreateScDPFunctionDlg( |
| this, RID_SCDLG_DPDATAFIELD, maLabelData, *pLabelData, *pFuncData ) ); |
| if( xDlg->Execute() == RET_OK ) |
| { |
| ScPivotFuncData aFuncData( *pFuncData ); |
| aFuncData.mnFuncMask = pLabelData->mnFuncMask = xDlg->GetFuncMask(); |
| aFuncData.maFieldRef = xDlg->GetFieldRef(); |
| rSourceWindow.ModifySelectedField( aFuncData ); |
| } |
| } |
| else |
| { |
| // list of plain names of all data fields |
| ScDPNameVec aDataFieldNames; |
| maWndData.WriteFieldNames( aDataFieldNames ); |
| // allow to modify layout options for row fields, if multiple data fields exist, or if it is not the last row field |
| bool bLayout = (rSourceWindow.GetType() == PIVOTFIELDTYPE_ROW) && ((aDataFieldNames.size() > 1) || (rSourceWindow.GetSelectedIndex() + 1 < rSourceWindow.GetFieldCount())); |
| |
| ::std::auto_ptr< AbstractScDPSubtotalDlg > xDlg( pFactory->CreateScDPSubtotalDlg( |
| this, RID_SCDLG_PIVOTSUBT, *mxDlgDPObject, *pLabelData, *pFuncData, aDataFieldNames, bLayout ) ); |
| if( xDlg->Execute() == RET_OK ) |
| { |
| xDlg->FillLabelData( *pLabelData ); |
| ScPivotFuncData aFuncData( *pFuncData ); |
| aFuncData.mnFuncMask = pLabelData->mnFuncMask; |
| rSourceWindow.ModifySelectedField( aFuncData ); |
| } |
| } |
| } |
| |
| void ScPivotLayoutDlg::NotifyFieldRemoved( ScPivotFieldWindow& rSourceWindow ) |
| { |
| // update focus: move to selection window, if source window is empty now |
| GrabFieldFocus( rSourceWindow ); |
| } |
| |
| // protected ------------------------------------------------------------------ |
| |
| void ScPivotLayoutDlg::Tracking( const TrackingEvent& rTEvt ) |
| { |
| DBG_ASSERT( mpTrackingWindow, "ScPivotLayoutDlg::Tracking - missing tracking source window" ); |
| if( !mpTrackingWindow ) |
| return; |
| |
| // find target window |
| const Point& rDialogPos = rTEvt.GetMouseEvent().GetPosPixel(); |
| ScPivotFieldWindow* pTargetWindow = dynamic_cast< ScPivotFieldWindow* >( FindWindow( rDialogPos ) ); |
| |
| // check if the target orientation is allowed for this field |
| if( pTargetWindow && (mpTrackingWindow != pTargetWindow) && !IsInsertAllowed( *mpTrackingWindow, *pTargetWindow ) ) |
| pTargetWindow = 0; |
| |
| // tracking from selection window: do not show "delete" mouse pointer |
| PointerStyle eTargetPointer = pTargetWindow ? pTargetWindow->GetDropPointerStyle() : |
| ((mpTrackingWindow->GetType() == PIVOTFIELDTYPE_SELECT) ? POINTER_NOTALLOWED : POINTER_PIVOT_DELETE); |
| |
| // after calculating pointer style, check if target is selection window |
| if( pTargetWindow && (pTargetWindow->GetType() == PIVOTFIELDTYPE_SELECT) ) |
| pTargetWindow = 0; |
| |
| // notify windows about tracking |
| if( mpDropWindow != pTargetWindow ) |
| { |
| // tracking window changed |
| if( mpDropWindow ) |
| mpDropWindow->NotifyEndTracking( ENDTRACKING_SUSPEND ); |
| if( pTargetWindow ) |
| pTargetWindow->NotifyStartTracking(); |
| mpDropWindow = pTargetWindow; |
| } |
| if( mpDropWindow ) |
| mpDropWindow->NotifyTracking( rDialogPos - pTargetWindow->GetPosPixel() ); |
| |
| // end tracking: move or remove field |
| if( rTEvt.IsTrackingEnded() ) |
| { |
| bool bCancelled = rTEvt.IsTrackingCanceled(); |
| if( mpDropWindow ) |
| { |
| mpDropWindow->NotifyEndTracking( bCancelled ? ENDTRACKING_CANCEL : ENDTRACKING_DROP ); |
| if( !bCancelled ) |
| { |
| size_t nInsertIndex = mpDropWindow->GetDropIndex( rDialogPos - mpDropWindow->GetPosPixel() ); |
| bool bMoved = MoveField( *mpTrackingWindow, *mpDropWindow, nInsertIndex, true ); |
| // focus drop window, if move was successful, otherwise back to source window |
| GrabFieldFocus( bMoved ? *mpDropWindow : *mpTrackingWindow ); |
| } |
| } |
| else |
| { |
| // drop target invalid (outside field windows): remove tracked field |
| if( !bCancelled ) |
| mpTrackingWindow->RemoveSelectedField(); |
| // focus source window (or another window, if it is empty now) |
| GrabFieldFocus( *mpTrackingWindow ); |
| } |
| eTargetPointer = POINTER_ARROW; |
| if( mpTrackingWindow != mpDropWindow ) |
| mpTrackingWindow->NotifyEndTracking( ENDTRACKING_CANCEL ); |
| mpTrackingWindow = mpDropWindow = 0; |
| } |
| SetPointer( eTargetPointer ); |
| } |
| |
| void ScPivotLayoutDlg::SetReference( const ScRange& rRef, ScDocument* pDocP ) |
| { |
| if( !mbRefInputMode || !mpActiveEdit ) |
| return; |
| |
| if( rRef.aStart != rRef.aEnd ) |
| RefInputStart( mpActiveEdit ); |
| |
| if( mpActiveEdit == &maEdInPos ) |
| { |
| String aRefStr; |
| rRef.Format( aRefStr, SCR_ABS_3D, pDocP, pDocP->GetAddressConvention() ); |
| mpActiveEdit->SetRefString( aRefStr ); |
| } |
| else if( mpActiveEdit == &maEdOutPos ) |
| { |
| String aRefStr; |
| rRef.aStart.Format( aRefStr, STD_FORMAT, pDocP, pDocP->GetAddressConvention() ); |
| mpActiveEdit->SetRefString( aRefStr ); |
| } |
| } |
| |
| sal_Bool ScPivotLayoutDlg::IsRefInputMode() const |
| { |
| return mbRefInputMode; |
| } |
| |
| void ScPivotLayoutDlg::SetActive() |
| { |
| if( mbRefInputMode ) |
| { |
| if( mpActiveEdit ) |
| mpActiveEdit->GrabFocus(); |
| |
| if( mpActiveEdit == &maEdInPos ) |
| EdInModifyHdl( 0 ); |
| else if( mpActiveEdit == &maEdOutPos ) |
| EdOutModifyHdl( 0 ); |
| } |
| else |
| { |
| GrabFocus(); |
| } |
| |
| RefInputDone(); |
| } |
| |
| sal_Bool ScPivotLayoutDlg::Close() |
| { |
| return DoClose( ScPivotLayoutWrapper::GetChildWindowId() ); |
| } |
| |
| // private -------------------------------------------------------------------- |
| |
| ScPivotFieldWindow& ScPivotLayoutDlg::GetFieldWindow( ScPivotFieldType eFieldType ) |
| { |
| switch( eFieldType ) |
| { |
| case PIVOTFIELDTYPE_PAGE: return maWndPage; |
| case PIVOTFIELDTYPE_ROW: return maWndRow; |
| case PIVOTFIELDTYPE_COL: return maWndCol; |
| case PIVOTFIELDTYPE_DATA: return maWndData; |
| default:; |
| } |
| return maWndSelect; |
| } |
| |
| bool ScPivotLayoutDlg::IsInsertAllowed( const ScPivotFieldWindow& rSourceWindow, const ScPivotFieldWindow& rTargetWindow ) |
| { |
| if( rTargetWindow.GetType() != PIVOTFIELDTYPE_SELECT ) |
| { |
| const ScPivotFuncData* pSourceData = rSourceWindow.GetSelectedFuncData(); |
| ScDPLabelData* pLabelData = pSourceData ? GetLabelData( pSourceData->mnCol ) : 0; |
| DBG_ASSERT( pLabelData, "ScPivotLayoutDlg::IsInsertAllowed - label data not found" ); |
| if( pLabelData ) |
| { |
| sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN; |
| switch( rTargetWindow.GetType() ) |
| { |
| case PIVOTFIELDTYPE_PAGE: eOrient = sheet::DataPilotFieldOrientation_PAGE; break; |
| case PIVOTFIELDTYPE_COL: eOrient = sheet::DataPilotFieldOrientation_COLUMN; break; |
| case PIVOTFIELDTYPE_ROW: eOrient = sheet::DataPilotFieldOrientation_ROW; break; |
| case PIVOTFIELDTYPE_DATA: eOrient = sheet::DataPilotFieldOrientation_DATA; break; |
| default: return false; |
| } |
| return ScDPObject::IsOrientationAllowed( static_cast< sal_uInt16 >( eOrient ), pLabelData->mnFlags ); |
| } |
| } |
| return false; |
| } |
| |
| void ScPivotLayoutDlg::InitFieldWindows() |
| { |
| maLabelData = maPivotData.maLabelArray; |
| maWndSelect.ReadDataLabels( maLabelData ); |
| maWndPage.ReadPivotFields( maPivotData.maPageArr ); |
| maWndCol.ReadPivotFields( maPivotData.maColArr ); |
| maWndRow.ReadPivotFields( maPivotData.maRowArr ); |
| maWndData.ReadPivotFields( maPivotData.maDataArr ); |
| } |
| |
| void ScPivotLayoutDlg::GrabFieldFocus( ScPivotFieldWindow& rFieldWindow ) |
| { |
| if( rFieldWindow.IsEmpty() ) |
| { |
| if( maWndSelect.IsEmpty() ) |
| maBtnOk.GrabFocus(); |
| else |
| maWndSelect.GrabFocus(); |
| } |
| else |
| rFieldWindow.GrabFocus(); |
| } |
| |
| namespace { |
| |
| void lclFindFieldWindow( ScPivotFieldWindow*& rpFieldWindow, const ScPivotFuncData*& rpFuncData, size_t& rnFieldIndex, ScPivotFieldWindow& rFieldWindow ) |
| { |
| ScPivotFuncDataEntry aEntry = rFieldWindow.FindFuncDataByCol( rpFuncData->mnCol ); |
| if( aEntry.first ) |
| { |
| rpFieldWindow = &rFieldWindow; |
| rpFuncData = aEntry.first; |
| rnFieldIndex = aEntry.second; |
| } |
| } |
| |
| } // namespace |
| |
| bool ScPivotLayoutDlg::MoveField( ScPivotFieldWindow& rSourceWindow, ScPivotFieldWindow& rTargetWindow, size_t nInsertIndex, bool bMoveExisting ) |
| { |
| // move inside the same window |
| if( &rSourceWindow == &rTargetWindow ) |
| return bMoveExisting && rTargetWindow.MoveSelectedField( nInsertIndex ); |
| |
| // do not insert if not supported by target window |
| if( !IsInsertAllowed( rSourceWindow, rTargetWindow ) ) |
| { |
| rSourceWindow.RemoveSelectedField(); |
| return false; |
| } |
| |
| // move from one window to another window |
| if( const ScPivotFuncData* pSourceData = rSourceWindow.GetSelectedFuncData() ) |
| { |
| // move to page/col/row window: try to find existing field in another window |
| ScPivotFieldWindow* pSourceWindow = &rSourceWindow; |
| size_t nSourceIndex = rSourceWindow.GetSelectedIndex(); |
| if( rTargetWindow.GetType() != PIVOTFIELDTYPE_DATA ) |
| { |
| lclFindFieldWindow( pSourceWindow, pSourceData, nSourceIndex, maWndPage ); |
| lclFindFieldWindow( pSourceWindow, pSourceData, nSourceIndex, maWndCol ); |
| lclFindFieldWindow( pSourceWindow, pSourceData, nSourceIndex, maWndRow ); |
| } |
| |
| // found in target window: move to new position |
| if( pSourceWindow == &rTargetWindow ) |
| return bMoveExisting && pSourceWindow->MoveField( nSourceIndex, nInsertIndex ); |
| |
| // insert field into target window |
| rTargetWindow.InsertField( nInsertIndex, *pSourceData ); |
| // remove field from source window |
| pSourceWindow->RemoveField( nSourceIndex ); |
| // remove field from data window, if it is the original source |
| if( (rSourceWindow.GetType() == PIVOTFIELDTYPE_DATA) && (pSourceWindow->GetType() != PIVOTFIELDTYPE_DATA) ) |
| rSourceWindow.RemoveSelectedField(); |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // handlers ------------------------------------------------------------------- |
| |
| IMPL_LINK( ScPivotLayoutDlg, ClickHdl, PushButton *, pBtn ) |
| { |
| if( mpFocusWindow ) |
| { |
| /* Raising sub dialogs (from the NotifyDoubleClick function) triggers |
| VCL child window focus events from this sub dialog which may |
| invalidate the member mpFocusWindow pointing to the target field |
| window. This would cause a crash with the following call to the |
| GrabFieldFocus function, if mpFocusWindow is used directly. */ |
| ScPivotFieldWindow& rTargetWindow = *mpFocusWindow; |
| |
| if( pBtn == &maBtnRemove ) |
| { |
| rTargetWindow.RemoveSelectedField(); |
| // focus back to field window |
| GrabFieldFocus( rTargetWindow ); |
| } |
| else if( pBtn == &maBtnOptions ) |
| { |
| NotifyDoubleClick( rTargetWindow ); |
| // focus back to field window |
| GrabFieldFocus( rTargetWindow ); |
| } |
| } |
| return 0; |
| } |
| |
| IMPL_LINK( ScPivotLayoutDlg, OkHdl, OKButton *, EMPTYARG ) |
| { |
| String aOutPosStr = maEdOutPos.GetText(); |
| ScAddress aAdrDest; |
| bool bToNewTable = maLbOutPos.GetSelectEntryPos() == 1; |
| sal_uInt16 nResult = !bToNewTable ? aAdrDest.Parse( aOutPosStr, mpDoc, mpDoc->GetAddressConvention() ) : 0; |
| |
| if( bToNewTable || ((aOutPosStr.Len() > 0) && ((nResult & SCA_VALID) == SCA_VALID)) ) |
| { |
| ScPivotFieldVector aPageFields, aColFields, aRowFields, aDataFields; |
| maWndPage.WritePivotFields( aPageFields ); |
| maWndCol.WritePivotFields( aColFields ); |
| maWndRow.WritePivotFields( aRowFields ); |
| maWndData.WritePivotFields( aDataFields ); |
| |
| // TODO: handle data field in dialog field windows? |
| aRowFields.resize( aRowFields.size() + 1 ); |
| aRowFields.back().nCol = PIVOT_DATA_FIELD; |
| |
| ScDPSaveData* pOldSaveData = mxDlgDPObject->GetSaveData(); |
| |
| ScRange aOutRange( aAdrDest ); // bToNewTable is passed separately |
| |
| ScDPSaveData aSaveData; |
| aSaveData.SetIgnoreEmptyRows( maBtnIgnEmptyRows.IsChecked() ); |
| aSaveData.SetRepeatIfEmpty( maBtnDetectCat.IsChecked() ); |
| aSaveData.SetColumnGrand( maBtnTotalCol.IsChecked() ); |
| aSaveData.SetRowGrand( maBtnTotalRow.IsChecked() ); |
| aSaveData.SetFilterButton( maBtnFilter.IsChecked() ); |
| aSaveData.SetDrillDown( maBtnDrillDown.IsChecked() ); |
| |
| uno::Reference< sheet::XDimensionsSupplier > xSource = mxDlgDPObject->GetSource(); |
| |
| ScDPObject::ConvertOrientation( aSaveData, aPageFields, sheet::DataPilotFieldOrientation_PAGE, 0, 0, 0, xSource, false ); |
| ScDPObject::ConvertOrientation( aSaveData, aColFields, sheet::DataPilotFieldOrientation_COLUMN, 0, 0, 0, xSource, false ); |
| ScDPObject::ConvertOrientation( aSaveData, aRowFields, sheet::DataPilotFieldOrientation_ROW, 0, 0, 0, xSource, false ); |
| ScDPObject::ConvertOrientation( aSaveData, aDataFields, sheet::DataPilotFieldOrientation_DATA, 0, 0, 0, xSource, false, &aColFields, &aRowFields, &aPageFields ); |
| |
| for( ScDPLabelDataVector::const_iterator aIt = maLabelData.begin(), aEnd = maLabelData.end(); aIt != aEnd; ++aIt ) |
| { |
| if( ScDPSaveDimension* pDim = aSaveData.GetExistingDimensionByName( aIt->maName ) ) |
| { |
| pDim->SetUsedHierarchy( aIt->mnUsedHier ); |
| pDim->SetShowEmpty( aIt->mbShowAll ); |
| pDim->SetSortInfo( &aIt->maSortInfo ); |
| pDim->SetLayoutInfo( &aIt->maLayoutInfo ); |
| pDim->SetAutoShowInfo( &aIt->maShowInfo ); |
| ScDPSaveDimension* pOldDim = NULL; |
| if (pOldSaveData) |
| { |
| // Transfer the existing layout names to new dimension instance. |
| pOldDim = pOldSaveData->GetExistingDimensionByName(aIt->maName); |
| if (pOldDim) |
| { |
| const OUString* pLayoutName = pOldDim->GetLayoutName(); |
| if (pLayoutName) |
| pDim->SetLayoutName(*pLayoutName); |
| |
| const OUString* pSubtotalName = pOldDim->GetSubtotalName(); |
| if (pSubtotalName) |
| pDim->SetSubtotalName(*pSubtotalName); |
| } |
| } |
| |
| bool bManualSort = ( aIt->maSortInfo.Mode == sheet::DataPilotFieldSortMode::MANUAL ); |
| |
| // visibility of members |
| for (::std::vector<ScDPLabelData::Member>::const_iterator itr = aIt->maMembers.begin(), itrEnd = aIt->maMembers.end(); |
| itr != itrEnd; ++itr) |
| { |
| ScDPSaveMember* pMember = pDim->GetMemberByName(itr->maName); |
| |
| // #i40054# create/access members only if flags are not default |
| // (or in manual sorting mode - to keep the order) |
| if (bManualSort || !itr->mbVisible || !itr->mbShowDetails) |
| { |
| pMember->SetIsVisible(itr->mbVisible); |
| pMember->SetShowDetails(itr->mbShowDetails); |
| } |
| if (pOldDim) |
| { |
| // Transfer the existing layout name. |
| ScDPSaveMember* pOldMember = pOldDim->GetMemberByName(itr->maName); |
| if (pOldMember) |
| { |
| const OUString* pLayoutName = pOldMember->GetLayoutName(); |
| if (pLayoutName) |
| pMember->SetLayoutName(*pLayoutName); |
| } |
| } |
| } |
| } |
| } |
| ScDPSaveDimension* pDim = aSaveData.GetDataLayoutDimension(); |
| if (pDim && pOldSaveData) |
| { |
| ScDPSaveDimension* pOldDim = pOldSaveData->GetDataLayoutDimension(); |
| if (pOldDim) |
| { |
| const OUString* pLayoutName = pOldDim->GetLayoutName(); |
| if (pLayoutName) |
| pDim->SetLayoutName(*pLayoutName); |
| } |
| } |
| |
| // also transfer grand total name |
| if (pOldSaveData) |
| { |
| const OUString* pGrandTotalName = pOldSaveData->GetGrandTotalName(); |
| if (pGrandTotalName) |
| aSaveData.SetGrandTotalName(*pGrandTotalName); |
| } |
| |
| sal_uInt16 nWhichPivot = SC_MOD()->GetPool().GetWhich( SID_PIVOT_TABLE ); |
| ScPivotItem aOutItem( nWhichPivot, &aSaveData, &aOutRange, bToNewTable ); |
| |
| mbRefInputMode = false; // to allow deselecting when switching sheets |
| |
| SetDispatcherLock( false ); |
| SwitchToDocument(); |
| |
| // #95513# don't hide the dialog before executing the slot, instead it is used as |
| // parent for message boxes in ScTabViewShell::GetDialogParent |
| |
| const SfxPoolItem* pRet = GetBindings().GetDispatcher()->Execute( |
| SID_PIVOT_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD, &aOutItem, 0L, 0L ); |
| |
| bool bSuccess = true; |
| if (pRet) |
| { |
| const SfxBoolItem* pItem = dynamic_cast<const SfxBoolItem*>(pRet); |
| if (pItem) |
| bSuccess = pItem->GetValue(); |
| } |
| if (bSuccess) |
| // Table successfully inserted. |
| Close(); |
| else |
| { |
| // Table insertion failed. Keep the dialog open. |
| mbRefInputMode = true; |
| SetDispatcherLock(true); |
| } |
| } |
| else |
| { |
| if( !maBtnMore.GetState() ) |
| maBtnMore.SetState( true ); |
| |
| ErrorBox( this, WinBits( WB_OK | WB_DEF_OK ), ScGlobal::GetRscString( STR_INVALID_TABREF ) ).Execute(); |
| maEdOutPos.GrabFocus(); |
| } |
| return 0; |
| } |
| |
| IMPL_LINK( ScPivotLayoutDlg, CancelHdl, CancelButton *, EMPTYARG ) |
| { |
| Close(); |
| return 0; |
| } |
| |
| IMPL_LINK( ScPivotLayoutDlg, MoreClickHdl, MoreButton *, EMPTYARG ) |
| { |
| if ( maBtnMore.GetState() ) |
| { |
| mbRefInputMode = true; |
| if ( maEdInPos.IsEnabled() ) |
| { |
| maEdInPos.Enable(); |
| maEdInPos.GrabFocus(); |
| maEdInPos.Enable(); |
| } |
| else |
| { |
| maEdOutPos.Enable(); |
| maEdOutPos.GrabFocus(); |
| maEdOutPos.Enable(); |
| } |
| } |
| else |
| { |
| mbRefInputMode = false; |
| } |
| return 0; |
| } |
| |
| IMPL_LINK( ScPivotLayoutDlg, EdOutModifyHdl, Edit *, EMPTYARG ) |
| { |
| String theCurPosStr = maEdOutPos.GetText(); |
| sal_uInt16 nResult = ScAddress().Parse( theCurPosStr, mpDoc, mpDoc->GetAddressConvention() ); |
| |
| if ( SCA_VALID == (nResult & SCA_VALID) ) |
| { |
| String* pStr = 0; |
| bool bFound = false; |
| sal_uInt16 i = 0; |
| sal_uInt16 nCount = maLbOutPos.GetEntryCount(); |
| |
| for ( i=2; i<nCount && !bFound; i++ ) |
| { |
| pStr = (String*)maLbOutPos.GetEntryData( i ); |
| bFound = (theCurPosStr == *pStr); |
| } |
| |
| if ( bFound ) |
| maLbOutPos.SelectEntryPos( --i ); |
| else |
| maLbOutPos.SelectEntryPos( 0 ); |
| } |
| return 0; |
| } |
| |
| |
| IMPL_LINK( ScPivotLayoutDlg, EdInModifyHdl, Edit *, EMPTYARG ) |
| { |
| String theCurPosStr = maEdInPos.GetText(); |
| sal_uInt16 nResult = ScRange().Parse( theCurPosStr, mpDoc, mpDoc->GetAddressConvention() ); |
| |
| // invalid source range |
| if( SCA_VALID != (nResult & SCA_VALID) ) |
| return 0; |
| |
| ScRefAddress start, end; |
| ConvertDoubleRef( mpDoc, theCurPosStr, 1, start, end, mpDoc->GetAddressConvention() ); |
| ScRange aNewRange( start.GetAddress(), end.GetAddress() ); |
| ScSheetSourceDesc inSheet = *mxDlgDPObject->GetSheetDesc(); |
| |
| // new range is identical to the current range |
| if( inSheet.aSourceRange == aNewRange ) |
| return 0; |
| |
| ScTabViewShell* pTabViewShell = mpViewData->GetViewShell(); |
| inSheet.aSourceRange = aNewRange; |
| mxDlgDPObject->SetSheetDesc( inSheet ); |
| mxDlgDPObject->FillOldParam( maPivotData ); |
| mxDlgDPObject->FillLabelData( maPivotData ); |
| |
| // SetDialogDPObject does not take ownership but makes a copy internally |
| pTabViewShell->SetDialogDPObject( mxDlgDPObject.get() ); |
| |
| // re-initialize the field windows from the new data |
| InitFieldWindows(); |
| |
| return 0; |
| } |
| |
| IMPL_LINK( ScPivotLayoutDlg, SelAreaHdl, ListBox *, EMPTYARG ) |
| { |
| String aString; |
| sal_uInt16 nSelPos = maLbOutPos.GetSelectEntryPos(); |
| if( nSelPos > 1 ) |
| { |
| aString = *(String*)maLbOutPos.GetEntryData( nSelPos ); |
| } |
| else |
| { |
| // do not allow to specify output position, if target is "new sheet" |
| bool bNewSheet = nSelPos == 1; |
| maEdOutPos.Enable( !bNewSheet ); |
| maRbOutPos.Enable( !bNewSheet ); |
| } |
| |
| maEdOutPos.SetText( aString ); |
| return 0; |
| } |
| |
| IMPL_LINK( ScPivotLayoutDlg, ChildEventListener, VclWindowEvent*, pEvent ) |
| { |
| Window* pWindow = pEvent->GetWindow(); |
| // check that this dialog is the parent of the window, to ignore focus events from sub dialogs |
| if( (pEvent->GetId() == VCLEVENT_WINDOW_GETFOCUS) && pWindow && (pWindow->GetParent() == this) ) |
| { |
| // check if old window and/or new window are field windows |
| ScPivotFieldWindow* pSourceWindow = mpFocusWindow; |
| ScPivotFieldWindow* pTargetWindow = dynamic_cast< ScPivotFieldWindow* >( pWindow ); |
| |
| /* Enable or disable the Remove/Options buttons. Do nothing if the |
| buttons themselves get the focus. |
| #128113# The TestTool may set the focus into an empty window. Then |
| the Remove/Options buttons must be disabled. */ |
| if( (pWindow != &maBtnRemove) && (pWindow != &maBtnOptions) ) |
| { |
| bool bEnableButtons = pTargetWindow && (pTargetWindow->GetType() != PIVOTFIELDTYPE_SELECT) && !pTargetWindow->IsEmpty(); |
| maBtnRemove.Enable( bEnableButtons ); |
| maBtnOptions.Enable( bEnableButtons ); |
| /* Remember the new focus window (will not be changed, if |
| Remove/Option buttons are getting focus, because they need to |
| know the field window they are working on). */ |
| mpFocusWindow = pTargetWindow; |
| } |
| |
| /* Move the last selected field to target window, if focus changes via |
| keyboard shortcut. */ |
| if( pSourceWindow && pTargetWindow && (pSourceWindow != pTargetWindow) && ((pTargetWindow->GetGetFocusFlags() & GETFOCUS_MNEMONIC) != 0) ) |
| { |
| // append field in target window |
| MoveField( *pSourceWindow, *pTargetWindow, pTargetWindow->GetFieldCount(), false ); |
| // move cursor in selection window to next field |
| if( pSourceWindow->GetType() == PIVOTFIELDTYPE_SELECT ) |
| pSourceWindow->SelectNextField(); |
| // return focus to source window (if it is not empty) |
| GrabFieldFocus( pSourceWindow->IsEmpty() ? *pTargetWindow : *pSourceWindow ); |
| } |
| |
| mpActiveEdit = dynamic_cast< ::formula::RefEdit* >( pEvent->GetWindow() ); |
| } |
| return 0; |
| } |
| |
| // ============================================================================ |