Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / source / ui / dbgui / pvfundlg.cxx
blob45a5038292235b767df833f27493b59561f3165f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #undef SC_DLLIMPLEMENTATION
22 #include "pvfundlg.hxx"
24 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
25 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
26 #include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp>
27 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
28 #include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp>
30 #include <tools/resary.hxx>
31 #include <vcl/builderfactory.hxx>
32 #include <vcl/msgbox.hxx>
34 #include "scresid.hxx"
35 #include "dpobject.hxx"
36 #include "dpsave.hxx"
37 #include "sc.hrc"
38 #include "globstr.hrc"
39 #include "dputil.hxx"
41 #include <vector>
43 using namespace ::com::sun::star::sheet;
45 using ::com::sun::star::uno::Sequence;
46 using ::std::vector;
48 namespace {
50 /** Appends all strings from the Sequence to the list box.
52 Empty strings are replaced by a localized "(empty)" entry and inserted at
53 the specified position.
55 @return true = The passed string list contains an empty string entry.
57 template< typename ListBoxType >
58 bool lclFillListBox( ListBoxType& rLBox, const Sequence< OUString >& rStrings, sal_Int32 nEmptyPos = LISTBOX_APPEND )
60 bool bEmpty = false;
61 const OUString* pStr = rStrings.getConstArray();
62 if( pStr )
64 for( const OUString* pEnd = pStr + rStrings.getLength(); pStr != pEnd; ++pStr )
66 if( !pStr->isEmpty() )
67 rLBox.InsertEntry( *pStr );
68 else
70 rLBox.InsertEntry( ScGlobal::GetRscString( STR_EMPTYDATA ), nEmptyPos );
71 bEmpty = true;
75 return bEmpty;
78 template< typename ListBoxType >
79 bool lclFillListBox( ListBoxType& rLBox, const vector<ScDPLabelData::Member>& rMembers, sal_Int32 nEmptyPos = LISTBOX_APPEND )
81 bool bEmpty = false;
82 vector<ScDPLabelData::Member>::const_iterator itr = rMembers.begin(), itrEnd = rMembers.end();
83 for (; itr != itrEnd; ++itr)
85 OUString aName = itr->getDisplayName();
86 if (!aName.isEmpty())
87 rLBox.InsertEntry(aName);
88 else
90 rLBox.InsertEntry(ScGlobal::GetRscString(STR_EMPTYDATA), nEmptyPos);
91 bEmpty = true;
94 return bEmpty;
97 /** This table represents the order of the strings in the resource string array. */
98 static const PivotFunc spnFunctions[] =
100 PivotFunc::Sum,
101 PivotFunc::Count,
102 PivotFunc::Average,
103 PivotFunc::Max,
104 PivotFunc::Min,
105 PivotFunc::Product,
106 PivotFunc::CountNum,
107 PivotFunc::StdDev,
108 PivotFunc::StdDevP,
109 PivotFunc::StdVar,
110 PivotFunc::StdVarP
113 const sal_uInt16 SC_BASEITEM_PREV_POS = 0;
114 const sal_uInt16 SC_BASEITEM_NEXT_POS = 1;
115 const sal_uInt16 SC_BASEITEM_USER_POS = 2;
117 const sal_uInt16 SC_SORTNAME_POS = 0;
118 const sal_uInt16 SC_SORTDATA_POS = 1;
120 const long SC_SHOW_DEFAULT = 10;
122 static const ScDPListBoxWrapper::MapEntryType spRefTypeMap[] =
124 { 0, DataPilotFieldReferenceType::NONE },
125 { 1, DataPilotFieldReferenceType::ITEM_DIFFERENCE },
126 { 2, DataPilotFieldReferenceType::ITEM_PERCENTAGE },
127 { 3, DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE },
128 { 4, DataPilotFieldReferenceType::RUNNING_TOTAL },
129 { 5, DataPilotFieldReferenceType::ROW_PERCENTAGE },
130 { 6, DataPilotFieldReferenceType::COLUMN_PERCENTAGE },
131 { 7, DataPilotFieldReferenceType::TOTAL_PERCENTAGE },
132 { 8, DataPilotFieldReferenceType::INDEX },
133 { WRAPPER_LISTBOX_ENTRY_NOTFOUND, DataPilotFieldReferenceType::NONE }
136 static const ScDPListBoxWrapper::MapEntryType spLayoutMap[] =
138 { 0, DataPilotFieldLayoutMode::TABULAR_LAYOUT },
139 { 1, DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP },
140 { 2, DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM },
141 { WRAPPER_LISTBOX_ENTRY_NOTFOUND, DataPilotFieldLayoutMode::TABULAR_LAYOUT }
144 static const ScDPListBoxWrapper::MapEntryType spShowFromMap[] =
146 { 0, DataPilotFieldShowItemsMode::FROM_TOP },
147 { 1, DataPilotFieldShowItemsMode::FROM_BOTTOM },
148 { WRAPPER_LISTBOX_ENTRY_NOTFOUND, DataPilotFieldShowItemsMode::FROM_TOP }
151 } // namespace
153 ScDPFunctionListBox::ScDPFunctionListBox(vcl::Window* pParent, WinBits nStyle)
154 : ListBox(pParent, nStyle)
156 FillFunctionNames();
159 VCL_BUILDER_DECL_FACTORY(ScDPFunctionListBox)
161 WinBits nWinStyle = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_SIMPLEMODE;
162 OString sBorder = VclBuilder::extractCustomProperty(rMap);
163 if (!sBorder.isEmpty())
164 nWinStyle |= WB_BORDER;
165 rRet = VclPtr<ScDPFunctionListBox>::Create(pParent, nWinStyle);
168 void ScDPFunctionListBox::SetSelection( PivotFunc nFuncMask )
170 if( (nFuncMask == PivotFunc::NONE) || (nFuncMask == PivotFunc::Auto) )
171 SetNoSelection();
172 else
173 for( sal_Int32 nEntry = 0, nCount = GetEntryCount(); nEntry < nCount; ++nEntry )
174 SelectEntryPos( nEntry, bool(nFuncMask & spnFunctions[ nEntry ]) );
177 PivotFunc ScDPFunctionListBox::GetSelection() const
179 PivotFunc nFuncMask = PivotFunc::NONE;
180 for( sal_Int32 nSel = 0, nCount = GetSelectEntryCount(); nSel < nCount; ++nSel )
181 nFuncMask |= spnFunctions[ GetSelectEntryPos( nSel ) ];
182 return nFuncMask;
185 void ScDPFunctionListBox::FillFunctionNames()
187 OSL_ENSURE( !GetEntryCount(), "ScDPMultiFuncListBox::FillFunctionNames - do not add texts to resource" );
188 Clear();
189 ResStringArray aArr( ScResId( SCSTR_DPFUNCLISTBOX ) );
190 for( sal_uInt16 nIndex = 0, nCount = sal::static_int_cast<sal_uInt16>(aArr.Count()); nIndex < nCount; ++nIndex )
191 InsertEntry( aArr.GetString( nIndex ) );
194 ScDPFunctionDlg::ScDPFunctionDlg(
195 vcl::Window* pParent, const ScDPLabelDataVector& rLabelVec,
196 const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData)
197 : ModalDialog(pParent, "DataFieldDialog",
198 "modules/scalc/ui/datafielddialog.ui")
199 , mrLabelVec(rLabelVec)
200 , mbEmptyItem(false)
202 get(mpFtName, "name");
203 get(mpLbType, "type");
204 mxLbTypeWrp.reset(new ScDPListBoxWrapper(*mpLbType, spRefTypeMap));
205 get(mpLbFunc, "functions");
206 mpLbFunc->set_height_request(mpLbFunc->GetTextHeight() * 8);
207 get(mpFtBaseField, "basefieldft");
208 get(mpLbBaseField, "basefield");
209 get(mpFtBaseItem, "baseitemft");
210 get(mpLbBaseItem, "baseitem");
211 get(mpBtnOk, "ok");
213 Init( rLabelData, rFuncData );
216 ScDPFunctionDlg::~ScDPFunctionDlg()
218 disposeOnce();
221 void ScDPFunctionDlg::dispose()
223 mpLbFunc.clear();
224 mpFtName.clear();
225 mpLbType.clear();
226 mpFtBaseField.clear();
227 mpLbBaseField.clear();
228 mpFtBaseItem.clear();
229 mpLbBaseItem.clear();
230 mpBtnOk.clear();
231 ModalDialog::dispose();
235 PivotFunc ScDPFunctionDlg::GetFuncMask() const
237 return mpLbFunc->GetSelection();
240 DataPilotFieldReference ScDPFunctionDlg::GetFieldRef() const
242 DataPilotFieldReference aRef;
244 aRef.ReferenceType = mxLbTypeWrp->GetControlValue();
245 aRef.ReferenceField = GetBaseFieldName(mpLbBaseField->GetSelectEntry());
247 sal_Int32 nBaseItemPos = mpLbBaseItem->GetSelectEntryPos();
248 switch( nBaseItemPos )
250 case SC_BASEITEM_PREV_POS:
251 aRef.ReferenceItemType = DataPilotFieldReferenceItemType::PREVIOUS;
252 break;
253 case SC_BASEITEM_NEXT_POS:
254 aRef.ReferenceItemType = DataPilotFieldReferenceItemType::NEXT;
255 break;
256 default:
258 aRef.ReferenceItemType = DataPilotFieldReferenceItemType::NAMED;
259 if( !mbEmptyItem || (nBaseItemPos > SC_BASEITEM_USER_POS) )
260 aRef.ReferenceItemName = GetBaseItemName(mpLbBaseItem->GetSelectEntry());
264 return aRef;
267 void ScDPFunctionDlg::Init( const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData )
269 // list box
270 PivotFunc nFuncMask = (rFuncData.mnFuncMask == PivotFunc::NONE) ? PivotFunc::Sum : rFuncData.mnFuncMask;
271 mpLbFunc->SetSelection( nFuncMask );
273 // field name
274 mpFtName->SetText(rLabelData.getDisplayName());
276 // handlers
277 mpLbFunc->SetDoubleClickHdl( LINK( this, ScDPFunctionDlg, DblClickHdl ) );
278 mpLbType->SetSelectHdl( LINK( this, ScDPFunctionDlg, SelectHdl ) );
279 mpLbBaseField->SetSelectHdl( LINK( this, ScDPFunctionDlg, SelectHdl ) );
281 // base field list box
282 OUString aSelectedEntry;
283 for( ScDPLabelDataVector::const_iterator aIt = mrLabelVec.begin(), aEnd = mrLabelVec.end(); aIt != aEnd; ++aIt )
285 mpLbBaseField->InsertEntry((*aIt)->getDisplayName());
286 maBaseFieldNameMap.insert(
287 NameMapType::value_type((*aIt)->getDisplayName(), (*aIt)->maName));
288 if ((*aIt)->maName == rFuncData.maFieldRef.ReferenceField)
289 aSelectedEntry = (*aIt)->getDisplayName();
292 // base item list box
293 mpLbBaseItem->SetSeparatorPos( SC_BASEITEM_USER_POS - 1 );
295 // select field reference type
296 mxLbTypeWrp->SetControlValue( rFuncData.maFieldRef.ReferenceType );
297 SelectHdl( *mpLbType.get() ); // enables base field/item list boxes
299 // select base field
300 mpLbBaseField->SelectEntry(aSelectedEntry);
301 if( mpLbBaseField->GetSelectEntryPos() >= mpLbBaseField->GetEntryCount() )
302 mpLbBaseField->SelectEntryPos( 0 );
303 SelectHdl( *mpLbBaseField.get() ); // fills base item list, selects base item
305 // select base item
306 switch( rFuncData.maFieldRef.ReferenceItemType )
308 case DataPilotFieldReferenceItemType::PREVIOUS:
309 mpLbBaseItem->SelectEntryPos( SC_BASEITEM_PREV_POS );
310 break;
311 case DataPilotFieldReferenceItemType::NEXT:
312 mpLbBaseItem->SelectEntryPos( SC_BASEITEM_NEXT_POS );
313 break;
314 default:
316 if( mbEmptyItem && rFuncData.maFieldRef.ReferenceItemName.isEmpty() )
318 // select special "(empty)" entry added before other items
319 mpLbBaseItem->SelectEntryPos( SC_BASEITEM_USER_POS );
321 else
323 sal_Int32 nStartPos = mbEmptyItem ? (SC_BASEITEM_USER_POS + 1) : SC_BASEITEM_USER_POS;
324 sal_Int32 nPos = FindBaseItemPos( rFuncData.maFieldRef.ReferenceItemName, nStartPos );
325 if( nPos >= mpLbBaseItem->GetEntryCount() )
326 nPos = (mpLbBaseItem->GetEntryCount() > SC_BASEITEM_USER_POS) ? SC_BASEITEM_USER_POS : SC_BASEITEM_PREV_POS;
327 mpLbBaseItem->SelectEntryPos( nPos );
333 const OUString& ScDPFunctionDlg::GetBaseFieldName(const OUString& rLayoutName) const
335 NameMapType::const_iterator itr = maBaseFieldNameMap.find(rLayoutName);
336 return itr == maBaseFieldNameMap.end() ? rLayoutName : itr->second;
339 const OUString& ScDPFunctionDlg::GetBaseItemName(const OUString& rLayoutName) const
341 NameMapType::const_iterator itr = maBaseItemNameMap.find(rLayoutName);
342 return itr == maBaseItemNameMap.end() ? rLayoutName : itr->second;
345 sal_Int32 ScDPFunctionDlg::FindBaseItemPos( const OUString& rEntry, sal_Int32 nStartPos ) const
347 sal_Int32 nPos = nStartPos;
348 bool bFound = false;
349 while (nPos < mpLbBaseItem->GetEntryCount())
351 // translate the displayed field name back to its original field name.
352 const OUString& rInName = mpLbBaseItem->GetEntry(nPos);
353 const OUString& rName = GetBaseItemName(rInName);
354 if (rName.equals(rEntry))
356 bFound = true;
357 break;
359 ++nPos;
361 return bFound ? nPos : LISTBOX_ENTRY_NOTFOUND;
364 IMPL_LINK_TYPED( ScDPFunctionDlg, SelectHdl, ListBox&, rLBox, void )
366 if( &rLBox == mpLbType )
368 bool bEnableField, bEnableItem;
369 switch( mxLbTypeWrp->GetControlValue() )
371 case DataPilotFieldReferenceType::ITEM_DIFFERENCE:
372 case DataPilotFieldReferenceType::ITEM_PERCENTAGE:
373 case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
374 bEnableField = bEnableItem = true;
375 break;
377 case DataPilotFieldReferenceType::RUNNING_TOTAL:
378 bEnableField = true;
379 bEnableItem = false;
380 break;
382 default:
383 bEnableField = bEnableItem = false;
386 bEnableField &= mpLbBaseField->GetEntryCount() > 0;
387 mpFtBaseField->Enable( bEnableField );
388 mpLbBaseField->Enable( bEnableField );
390 bEnableItem &= bEnableField;
391 mpFtBaseItem->Enable( bEnableItem );
392 mpLbBaseItem->Enable( bEnableItem );
394 else if( &rLBox == mpLbBaseField )
396 // keep "previous" and "next" entries
397 while( mpLbBaseItem->GetEntryCount() > SC_BASEITEM_USER_POS )
398 mpLbBaseItem->RemoveEntry( SC_BASEITEM_USER_POS );
400 // update item list for current base field
401 mbEmptyItem = false;
402 size_t nBasePos = mpLbBaseField->GetSelectEntryPos();
403 if( nBasePos < mrLabelVec.size() )
405 const vector<ScDPLabelData::Member>& rMembers = mrLabelVec[nBasePos]->maMembers;
406 mbEmptyItem = lclFillListBox(*mpLbBaseItem, rMembers, SC_BASEITEM_USER_POS);
407 // build cache for base names.
408 NameMapType aMap;
409 vector<ScDPLabelData::Member>::const_iterator itr = rMembers.begin(), itrEnd = rMembers.end();
410 for (; itr != itrEnd; ++itr)
411 aMap.insert(NameMapType::value_type(itr->getDisplayName(), itr->maName));
412 maBaseItemNameMap.swap(aMap);
415 // select base item
416 sal_uInt16 nItemPos = (mpLbBaseItem->GetEntryCount() > SC_BASEITEM_USER_POS) ? SC_BASEITEM_USER_POS : SC_BASEITEM_PREV_POS;
417 mpLbBaseItem->SelectEntryPos( nItemPos );
421 IMPL_LINK_NOARG_TYPED(ScDPFunctionDlg, DblClickHdl, ListBox&, void)
423 mpBtnOk->Click();
426 ScDPSubtotalDlg::ScDPSubtotalDlg( vcl::Window* pParent, ScDPObject& rDPObj,
427 const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData,
428 const ScDPNameVec& rDataFields, bool bEnableLayout )
429 : ModalDialog(pParent, "PivotFieldDialog",
430 "modules/scalc/ui/pivotfielddialog.ui")
431 , mrDPObj(rDPObj)
432 , mrDataFields(rDataFields)
433 , maLabelData(rLabelData)
434 , mbEnableLayout(bEnableLayout)
436 get(mpBtnOk, "ok");
437 get(mpBtnOptions, "options");
438 get(mpCbShowAll, "showall");
439 get(mpFtName, "name");
440 get(mpLbFunc, "functions");
441 mpLbFunc->EnableMultiSelection(true);
442 mpLbFunc->set_height_request(mpLbFunc->GetTextHeight() * 8);
443 get(mpRbNone, "none");
444 get(mpRbAuto, "auto");
445 get(mpRbUser, "user");
447 Init( rLabelData, rFuncData );
450 ScDPSubtotalDlg::~ScDPSubtotalDlg()
452 disposeOnce();
455 void ScDPSubtotalDlg::dispose()
457 mpRbNone.clear();
458 mpRbAuto.clear();
459 mpRbUser.clear();
460 mpLbFunc.clear();
461 mpFtName.clear();
462 mpCbShowAll.clear();
463 mpBtnOk.clear();
464 mpBtnOptions.clear();
465 ModalDialog::dispose();
468 PivotFunc ScDPSubtotalDlg::GetFuncMask() const
470 PivotFunc nFuncMask = PivotFunc::NONE;
472 if( mpRbAuto->IsChecked() )
473 nFuncMask = PivotFunc::Auto;
474 else if( mpRbUser->IsChecked() )
475 nFuncMask = mpLbFunc->GetSelection();
477 return nFuncMask;
480 void ScDPSubtotalDlg::FillLabelData( ScDPLabelData& rLabelData ) const
482 rLabelData.mnFuncMask = GetFuncMask();
483 rLabelData.mnUsedHier = maLabelData.mnUsedHier;
484 rLabelData.mbShowAll = mpCbShowAll->IsChecked();
485 rLabelData.maMembers = maLabelData.maMembers;
486 rLabelData.maSortInfo = maLabelData.maSortInfo;
487 rLabelData.maLayoutInfo = maLabelData.maLayoutInfo;
488 rLabelData.maShowInfo = maLabelData.maShowInfo;
489 rLabelData.mbRepeatItemLabels = maLabelData.mbRepeatItemLabels;
492 void ScDPSubtotalDlg::Init( const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData )
494 // field name
495 mpFtName->SetText(rLabelData.getDisplayName());
497 // radio buttons
498 mpRbNone->SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
499 mpRbAuto->SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
500 mpRbUser->SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
502 RadioButton* pRBtn = nullptr;
503 switch( rFuncData.mnFuncMask )
505 case PivotFunc::NONE: pRBtn = mpRbNone; break;
506 case PivotFunc::Auto: pRBtn = mpRbAuto; break;
507 default: pRBtn = mpRbUser;
509 pRBtn->Check();
510 RadioClickHdl( pRBtn );
512 // list box
513 mpLbFunc->SetSelection( rFuncData.mnFuncMask );
514 mpLbFunc->SetDoubleClickHdl( LINK( this, ScDPSubtotalDlg, DblClickHdl ) );
516 // show all
517 mpCbShowAll->Check( rLabelData.mbShowAll );
519 // options
520 mpBtnOptions->SetClickHdl( LINK( this, ScDPSubtotalDlg, ClickHdl ) );
523 IMPL_LINK_TYPED( ScDPSubtotalDlg, RadioClickHdl, Button*, pBtn, void )
525 mpLbFunc->Enable( pBtn == mpRbUser );
528 IMPL_LINK_NOARG_TYPED(ScDPSubtotalDlg, DblClickHdl, ListBox&, void)
530 mpBtnOk->Click();
533 IMPL_LINK_TYPED( ScDPSubtotalDlg, ClickHdl, Button*, pBtn, void )
535 if (pBtn == mpBtnOptions)
537 VclPtrInstance< ScDPSubtotalOptDlg > pDlg( this, mrDPObj, maLabelData, mrDataFields, mbEnableLayout );
538 if( pDlg->Execute() == RET_OK )
539 pDlg->FillLabelData( maLabelData );
543 ScDPSubtotalOptDlg::ScDPSubtotalOptDlg( vcl::Window* pParent, ScDPObject& rDPObj,
544 const ScDPLabelData& rLabelData, const ScDPNameVec& rDataFields,
545 bool bEnableLayout )
546 : ModalDialog(pParent, "DataFieldOptionsDialog",
547 "modules/scalc/ui/datafieldoptionsdialog.ui")
548 , mrDPObj(rDPObj)
549 , maLabelData(rLabelData)
551 get(m_pLbSortBy, "sortby");
552 m_pLbSortBy->set_width_request(m_pLbSortBy->approximate_char_width() * 20);
553 get(m_pRbSortAsc, "ascending");
554 get(m_pRbSortDesc, "descending");
555 get(m_pRbSortMan, "manual");
556 get(m_pLayoutFrame, "layoutframe");
557 get(m_pLbLayout, "layout");
558 get(m_pCbLayoutEmpty, "emptyline");
559 get(m_pCbRepeatItemLabels, "repeatitemlabels");
560 get(m_pCbShow, "show");
561 get(m_pNfShow, "items");
562 get(m_pFtShow, "showft");
563 get(m_pFtShowFrom, "showfromft");
564 get(m_pLbShowFrom, "from");
565 get(m_pFtShowUsing, "usingft");
566 get(m_pLbShowUsing, "using");
567 get(m_pHideFrame, "hideframe");
568 get(m_pLbHide, "hideitems");
569 m_pLbHide->set_height_request(GetTextHeight() * 5);
570 get(m_pFtHierarchy, "hierarchyft");
571 get(m_pLbHierarchy, "hierarchy");
573 m_xLbLayoutWrp.reset(new ScDPListBoxWrapper(*m_pLbLayout, spLayoutMap));
574 m_xLbShowFromWrp.reset(new ScDPListBoxWrapper(*m_pLbShowFrom, spShowFromMap));
576 Init( rDataFields, bEnableLayout );
579 ScDPSubtotalOptDlg::~ScDPSubtotalOptDlg()
581 disposeOnce();
584 void ScDPSubtotalOptDlg::dispose()
586 m_pLbSortBy.clear();
587 m_pRbSortAsc.clear();
588 m_pRbSortDesc.clear();
589 m_pRbSortMan.clear();
590 m_pLayoutFrame.clear();
591 m_pLbLayout.clear();
592 m_pCbLayoutEmpty.clear();
593 m_pCbRepeatItemLabels.clear();
594 m_pCbShow.clear();
595 m_pNfShow.clear();
596 m_pFtShow.clear();
597 m_pFtShowFrom.clear();
598 m_pLbShowFrom.clear();
599 m_pFtShowUsing.clear();
600 m_pLbShowUsing.clear();
601 m_pHideFrame.clear();
602 m_pLbHide.clear();
603 m_pFtHierarchy.clear();
604 m_pLbHierarchy.clear();
605 ModalDialog::dispose();
608 void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData& rLabelData ) const
610 // *** SORTING ***
612 if( m_pRbSortMan->IsChecked() )
613 rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::MANUAL;
614 else if( m_pLbSortBy->GetSelectEntryPos() == SC_SORTNAME_POS )
615 rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::NAME;
616 else
617 rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::DATA;
619 ScDPName aFieldName = GetFieldName(m_pLbSortBy->GetSelectEntry());
620 if (!aFieldName.maName.isEmpty())
622 rLabelData.maSortInfo.Field =
623 ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount);
624 rLabelData.maSortInfo.IsAscending = m_pRbSortAsc->IsChecked();
627 // *** LAYOUT MODE ***
629 rLabelData.maLayoutInfo.LayoutMode = m_xLbLayoutWrp->GetControlValue();
630 rLabelData.maLayoutInfo.AddEmptyLines = m_pCbLayoutEmpty->IsChecked();
631 rLabelData.mbRepeatItemLabels = m_pCbRepeatItemLabels->IsChecked();
633 // *** AUTO SHOW ***
635 aFieldName = GetFieldName(m_pLbShowUsing->GetSelectEntry());
636 if (!aFieldName.maName.isEmpty())
638 rLabelData.maShowInfo.IsEnabled = m_pCbShow->IsChecked();
639 rLabelData.maShowInfo.ShowItemsMode = m_xLbShowFromWrp->GetControlValue();
640 rLabelData.maShowInfo.ItemCount = sal::static_int_cast<sal_Int32>( m_pNfShow->GetValue() );
641 rLabelData.maShowInfo.DataField =
642 ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount);
645 // *** HIDDEN ITEMS ***
647 rLabelData.maMembers = maLabelData.maMembers;
648 sal_uLong nVisCount = m_pLbHide->GetEntryCount();
649 for( sal_uLong nPos = 0; nPos < nVisCount; ++nPos )
650 rLabelData.maMembers[nPos].mbVisible = !m_pLbHide->IsChecked(nPos);
652 // *** HIERARCHY ***
654 rLabelData.mnUsedHier = m_pLbHierarchy->GetSelectEntryCount() ? m_pLbHierarchy->GetSelectEntryPos() : 0;
657 void ScDPSubtotalOptDlg::Init( const ScDPNameVec& rDataFields, bool bEnableLayout )
659 // *** SORTING ***
661 sal_Int32 nSortMode = maLabelData.maSortInfo.Mode;
663 // sort fields list box
664 m_pLbSortBy->InsertEntry(maLabelData.getDisplayName());
666 for( ScDPNameVec::const_iterator aIt = rDataFields.begin(), aEnd = rDataFields.end(); aIt != aEnd; ++aIt )
668 // Cache names for later lookup.
669 maDataFieldNameMap.insert(NameMapType::value_type(aIt->maLayoutName, *aIt));
671 m_pLbSortBy->InsertEntry( aIt->maLayoutName );
672 m_pLbShowUsing->InsertEntry( aIt->maLayoutName ); // for AutoShow
675 if( m_pLbSortBy->GetEntryCount() > SC_SORTDATA_POS )
676 m_pLbSortBy->SetSeparatorPos( SC_SORTDATA_POS - 1 );
678 sal_Int32 nSortPos = SC_SORTNAME_POS;
679 if( nSortMode == DataPilotFieldSortMode::DATA )
681 nSortPos = FindListBoxEntry( *m_pLbSortBy, maLabelData.maSortInfo.Field, SC_SORTDATA_POS );
682 if( nSortPos >= m_pLbSortBy->GetEntryCount() )
684 nSortPos = SC_SORTNAME_POS;
685 nSortMode = DataPilotFieldSortMode::MANUAL;
688 m_pLbSortBy->SelectEntryPos( nSortPos );
690 // sorting mode
691 m_pRbSortAsc->SetClickHdl( LINK( this, ScDPSubtotalOptDlg, RadioClickHdl ) );
692 m_pRbSortDesc->SetClickHdl( LINK( this, ScDPSubtotalOptDlg, RadioClickHdl ) );
693 m_pRbSortMan->SetClickHdl( LINK( this, ScDPSubtotalOptDlg, RadioClickHdl ) );
695 RadioButton* pRBtn = nullptr;
696 switch( nSortMode )
698 case DataPilotFieldSortMode::NONE:
699 case DataPilotFieldSortMode::MANUAL:
700 pRBtn = m_pRbSortMan;
701 break;
702 default:
703 pRBtn = maLabelData.maSortInfo.IsAscending ? m_pRbSortAsc : m_pRbSortDesc;
705 pRBtn->Check();
706 RadioClickHdl( pRBtn );
708 // *** LAYOUT MODE ***
710 m_pLayoutFrame->Enable(bEnableLayout);
712 m_xLbLayoutWrp->SetControlValue( maLabelData.maLayoutInfo.LayoutMode );
713 m_pCbLayoutEmpty->Check( maLabelData.maLayoutInfo.AddEmptyLines );
714 m_pCbRepeatItemLabels->Check( maLabelData.mbRepeatItemLabels );
716 // *** AUTO SHOW ***
718 m_pCbShow->Check( maLabelData.maShowInfo.IsEnabled );
719 m_pCbShow->SetClickHdl( LINK( this, ScDPSubtotalOptDlg, CheckHdl ) );
721 m_xLbShowFromWrp->SetControlValue( maLabelData.maShowInfo.ShowItemsMode );
722 long nCount = static_cast< long >( maLabelData.maShowInfo.ItemCount );
723 if( nCount < 1 )
724 nCount = SC_SHOW_DEFAULT;
725 m_pNfShow->SetValue( nCount );
727 // m_pLbShowUsing already filled above
728 m_pLbShowUsing->SelectEntry( maLabelData.maShowInfo.DataField );
729 if( m_pLbShowUsing->GetSelectEntryPos() >= m_pLbShowUsing->GetEntryCount() )
730 m_pLbShowUsing->SelectEntryPos( 0 );
732 CheckHdl(m_pCbShow); // enable/disable dependent controls
734 // *** HIDDEN ITEMS ***
736 InitHideListBox();
738 // *** HIERARCHY ***
740 if( maLabelData.maHiers.getLength() > 1 )
742 lclFillListBox( *m_pLbHierarchy, maLabelData.maHiers );
743 sal_Int32 nHier = maLabelData.mnUsedHier;
744 if( (nHier < 0) || (nHier >= maLabelData.maHiers.getLength()) ) nHier = 0;
745 m_pLbHierarchy->SelectEntryPos( static_cast< sal_Int32 >( nHier ) );
746 m_pLbHierarchy->SetSelectHdl( LINK( this, ScDPSubtotalOptDlg, SelectHdl ) );
748 else
750 m_pFtHierarchy->Disable();
751 m_pLbHierarchy->Disable();
755 void ScDPSubtotalOptDlg::InitHideListBox()
757 m_pLbHide->Clear();
758 lclFillListBox( *m_pLbHide, maLabelData.maMembers );
759 size_t n = maLabelData.maMembers.size();
760 for (sal_uLong i = 0; i < n; ++i)
761 m_pLbHide->CheckEntryPos(i, !maLabelData.maMembers[i].mbVisible);
762 bool bEnable = m_pLbHide->GetEntryCount() > 0;
763 m_pHideFrame->Enable(bEnable);
766 ScDPName ScDPSubtotalOptDlg::GetFieldName(const OUString& rLayoutName) const
768 NameMapType::const_iterator itr = maDataFieldNameMap.find(rLayoutName);
769 return itr == maDataFieldNameMap.end() ? ScDPName() : itr->second;
772 sal_Int32 ScDPSubtotalOptDlg::FindListBoxEntry(
773 const ListBox& rLBox, const OUString& rEntry, sal_Int32 nStartPos ) const
775 sal_Int32 nPos = nStartPos;
776 bool bFound = false;
777 while (nPos < rLBox.GetEntryCount())
779 // translate the displayed field name back to its original field name.
780 ScDPName aName = GetFieldName(rLBox.GetEntry(nPos));
781 OUString aUnoName = ScDPUtil::createDuplicateDimensionName(aName.maName, aName.mnDupCount);
782 if (aUnoName.equals(rEntry))
784 bFound = true;
785 break;
787 ++nPos;
789 return bFound ? nPos : LISTBOX_ENTRY_NOTFOUND;
792 IMPL_LINK_TYPED( ScDPSubtotalOptDlg, RadioClickHdl, Button*, pBtn, void )
794 m_pLbSortBy->Enable( pBtn != m_pRbSortMan );
797 IMPL_LINK_TYPED( ScDPSubtotalOptDlg, CheckHdl, Button*, pCBox, void )
799 if (pCBox == m_pCbShow)
801 bool bEnable = m_pCbShow->IsChecked();
802 m_pNfShow->Enable( bEnable );
803 m_pFtShow->Enable( bEnable );
804 m_pFtShowFrom->Enable( bEnable );
805 m_pLbShowFrom->Enable( bEnable );
807 bool bEnableUsing = bEnable && (m_pLbShowUsing->GetEntryCount() > 0);
808 m_pFtShowUsing->Enable(bEnableUsing);
809 m_pLbShowUsing->Enable(bEnableUsing);
813 IMPL_LINK_TYPED( ScDPSubtotalOptDlg, SelectHdl, ListBox&, rLBox, void )
815 if (&rLBox == m_pLbHierarchy)
817 mrDPObj.GetMembers(maLabelData.mnCol, m_pLbHierarchy->GetSelectEntryPos(), maLabelData.maMembers);
818 InitHideListBox();
822 ScDPShowDetailDlg::ScDPShowDetailDlg( vcl::Window* pParent, ScDPObject& rDPObj, sal_uInt16 nOrient ) :
823 ModalDialog ( pParent, "ShowDetail", "modules/scalc/ui/showdetaildialog.ui" ),
824 mrDPObj(rDPObj)
826 get(mpLbDims, "dimsTreeview");
827 get(mpBtnOk, "ok");
829 ScDPSaveData* pSaveData = rDPObj.GetSaveData();
830 long nDimCount = rDPObj.GetDimCount();
831 for (long nDim=0; nDim<nDimCount; nDim++)
833 bool bIsDataLayout;
834 sal_Int32 nDimFlags = 0;
835 OUString aName = rDPObj.GetDimName( nDim, bIsDataLayout, &nDimFlags );
836 if ( !bIsDataLayout && !rDPObj.IsDuplicated( nDim ) && ScDPObject::IsOrientationAllowed( nOrient, nDimFlags ) )
838 const ScDPSaveDimension* pDimension = pSaveData ? pSaveData->GetExistingDimensionByName(aName) : nullptr;
839 if ( !pDimension || (pDimension->GetOrientation() != nOrient) )
841 if (pDimension)
843 const OUString* pLayoutName = pDimension->GetLayoutName();
844 if (pLayoutName)
845 aName = *pLayoutName;
847 mpLbDims->InsertEntry( aName );
848 maNameIndexMap.insert(DimNameIndexMap::value_type(aName, nDim));
852 if( mpLbDims->GetEntryCount() )
853 mpLbDims->SelectEntryPos( 0 );
855 mpLbDims->SetDoubleClickHdl( LINK( this, ScDPShowDetailDlg, DblClickHdl ) );
858 ScDPShowDetailDlg::~ScDPShowDetailDlg()
860 disposeOnce();
863 void ScDPShowDetailDlg::dispose()
865 mpLbDims.clear();
866 mpBtnOk.clear();
867 ModalDialog::dispose();
870 short ScDPShowDetailDlg::Execute()
872 return mpLbDims->GetEntryCount() ? ModalDialog::Execute() : static_cast<short>(RET_CANCEL);
875 OUString ScDPShowDetailDlg::GetDimensionName() const
877 // Look up the internal dimension name which may be different from the
878 // displayed field name.
879 OUString aSelectedName = mpLbDims->GetSelectEntry();
880 DimNameIndexMap::const_iterator itr = maNameIndexMap.find(aSelectedName);
881 if (itr == maNameIndexMap.end())
882 // This should never happen!
883 return aSelectedName;
885 long nDim = itr->second;
886 bool bIsDataLayout = false;
887 return mrDPObj.GetDimName(nDim, bIsDataLayout);
890 IMPL_LINK_TYPED( ScDPShowDetailDlg, DblClickHdl, ListBox&, rLBox, void )
892 if( &rLBox == mpLbDims )
893 mpBtnOk->Click();
896 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */