Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #undef SC_DLLIMPLEMENTATION
21 :
22 : #include "pvfundlg.hxx"
23 :
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>
29 :
30 : #include <tools/resary.hxx>
31 : #include <vcl/builder.hxx>
32 : #include <vcl/msgbox.hxx>
33 :
34 : #include "scresid.hxx"
35 : #include "dpobject.hxx"
36 : #include "dpsave.hxx"
37 : #include "pvfundlg.hrc"
38 : #include "globstr.hrc"
39 : #include "dputil.hxx"
40 :
41 : #include <vector>
42 :
43 : using namespace ::com::sun::star::sheet;
44 :
45 : using ::com::sun::star::uno::Sequence;
46 : using ::std::vector;
47 :
48 : namespace {
49 :
50 : /** Appends all strings from the Sequence to the list box.
51 :
52 : Empty strings are replaced by a localized "(empty)" entry and inserted at
53 : the specified position.
54 :
55 : @return true = The passed string list contains an empty string entry.
56 : */
57 : template< typename ListBoxType >
58 0 : bool lclFillListBox( ListBoxType& rLBox, const Sequence< OUString >& rStrings, sal_Int32 nEmptyPos = LISTBOX_APPEND )
59 : {
60 0 : bool bEmpty = false;
61 0 : const OUString* pStr = rStrings.getConstArray();
62 0 : if( pStr )
63 : {
64 0 : for( const OUString* pEnd = pStr + rStrings.getLength(); pStr != pEnd; ++pStr )
65 : {
66 0 : if( !pStr->isEmpty() )
67 0 : rLBox.InsertEntry( *pStr );
68 : else
69 : {
70 0 : rLBox.InsertEntry( ScGlobal::GetRscString( STR_EMPTYDATA ), nEmptyPos );
71 0 : bEmpty = true;
72 : }
73 : }
74 : }
75 0 : return bEmpty;
76 : }
77 :
78 : template< typename ListBoxType >
79 0 : bool lclFillListBox( ListBoxType& rLBox, const vector<ScDPLabelData::Member>& rMembers, sal_Int32 nEmptyPos = LISTBOX_APPEND )
80 : {
81 0 : bool bEmpty = false;
82 0 : vector<ScDPLabelData::Member>::const_iterator itr = rMembers.begin(), itrEnd = rMembers.end();
83 0 : for (; itr != itrEnd; ++itr)
84 : {
85 0 : OUString aName = itr->getDisplayName();
86 0 : if (!aName.isEmpty())
87 0 : rLBox.InsertEntry(aName);
88 : else
89 : {
90 0 : rLBox.InsertEntry(ScGlobal::GetRscString(STR_EMPTYDATA), nEmptyPos);
91 0 : bEmpty = true;
92 : }
93 : }
94 0 : return bEmpty;
95 : }
96 :
97 : /** This table represents the order of the strings in the resource string array. */
98 : static const sal_uInt16 spnFunctions[] =
99 : {
100 : PIVOT_FUNC_SUM,
101 : PIVOT_FUNC_COUNT,
102 : PIVOT_FUNC_AVERAGE,
103 : PIVOT_FUNC_MAX,
104 : PIVOT_FUNC_MIN,
105 : PIVOT_FUNC_PRODUCT,
106 : PIVOT_FUNC_COUNT_NUM,
107 : PIVOT_FUNC_STD_DEV,
108 : PIVOT_FUNC_STD_DEVP,
109 : PIVOT_FUNC_STD_VAR,
110 : PIVOT_FUNC_STD_VARP
111 : };
112 :
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;
116 :
117 : const sal_uInt16 SC_SORTNAME_POS = 0;
118 : const sal_uInt16 SC_SORTDATA_POS = 1;
119 :
120 : const long SC_SHOW_DEFAULT = 10;
121 :
122 : static const ScDPListBoxWrapper::MapEntryType spRefTypeMap[] =
123 : {
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 }
134 : };
135 :
136 : static const ScDPListBoxWrapper::MapEntryType spLayoutMap[] =
137 : {
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 }
142 : };
143 :
144 : static const ScDPListBoxWrapper::MapEntryType spShowFromMap[] =
145 : {
146 : { 0, DataPilotFieldShowItemsMode::FROM_TOP },
147 : { 1, DataPilotFieldShowItemsMode::FROM_BOTTOM },
148 : { WRAPPER_LISTBOX_ENTRY_NOTFOUND, DataPilotFieldShowItemsMode::FROM_TOP }
149 : };
150 :
151 : } // namespace
152 :
153 0 : ScDPFunctionListBox::ScDPFunctionListBox(Window* pParent, WinBits nStyle)
154 0 : : ListBox(pParent, nStyle)
155 : {
156 0 : FillFunctionNames();
157 0 : }
158 :
159 0 : extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeScDPFunctionListBox(Window *pParent, VclBuilder::stringmap &rMap)
160 : {
161 0 : WinBits nWinStyle = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_SIMPLEMODE;
162 0 : OString sBorder = VclBuilder::extractCustomProperty(rMap);
163 0 : if (!sBorder.isEmpty())
164 0 : nWinStyle |= WB_BORDER;
165 0 : return new ScDPFunctionListBox(pParent, nWinStyle);
166 : }
167 :
168 0 : void ScDPFunctionListBox::SetSelection( sal_uInt16 nFuncMask )
169 : {
170 0 : if( (nFuncMask == PIVOT_FUNC_NONE) || (nFuncMask == PIVOT_FUNC_AUTO) )
171 0 : SetNoSelection();
172 : else
173 0 : for( sal_Int32 nEntry = 0, nCount = GetEntryCount(); nEntry < nCount; ++nEntry )
174 0 : SelectEntryPos( nEntry, (nFuncMask & spnFunctions[ nEntry ]) != 0 );
175 0 : }
176 :
177 0 : sal_uInt16 ScDPFunctionListBox::GetSelection() const
178 : {
179 0 : sal_uInt16 nFuncMask = PIVOT_FUNC_NONE;
180 0 : for( sal_Int32 nSel = 0, nCount = GetSelectEntryCount(); nSel < nCount; ++nSel )
181 0 : nFuncMask |= spnFunctions[ GetSelectEntryPos( nSel ) ];
182 0 : return nFuncMask;
183 : }
184 :
185 0 : void ScDPFunctionListBox::FillFunctionNames()
186 : {
187 : OSL_ENSURE( !GetEntryCount(), "ScDPMultiFuncListBox::FillFunctionNames - do not add texts to resource" );
188 0 : Clear();
189 0 : ResStringArray aArr( ScResId( SCSTR_DPFUNCLISTBOX ) );
190 0 : for( sal_uInt16 nIndex = 0, nCount = sal::static_int_cast<sal_uInt16>(aArr.Count()); nIndex < nCount; ++nIndex )
191 0 : InsertEntry( aArr.GetString( nIndex ) );
192 0 : }
193 :
194 0 : ScDPFunctionDlg::ScDPFunctionDlg(
195 : 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 0 : , mbEmptyItem(false)
201 : {
202 0 : get(mpFtName, "name");
203 0 : get(mpLbType, "type");
204 0 : mxLbTypeWrp.reset(new ScDPListBoxWrapper(*mpLbType, spRefTypeMap));
205 0 : get(mpLbFunc, "functions");
206 0 : mpLbFunc->set_height_request(mpLbFunc->GetTextHeight() * 8);
207 0 : get(mpFtBaseField, "basefieldft");
208 0 : get(mpLbBaseField, "basefield");
209 0 : get(mpFtBaseItem, "baseitemft");
210 0 : get(mpLbBaseItem, "baseitem");
211 0 : get(mpBtnOk, "ok");
212 :
213 0 : Init( rLabelData, rFuncData );
214 0 : }
215 :
216 0 : sal_uInt16 ScDPFunctionDlg::GetFuncMask() const
217 : {
218 0 : return mpLbFunc->GetSelection();
219 : }
220 :
221 0 : DataPilotFieldReference ScDPFunctionDlg::GetFieldRef() const
222 : {
223 0 : DataPilotFieldReference aRef;
224 :
225 0 : aRef.ReferenceType = mxLbTypeWrp->GetControlValue();
226 0 : aRef.ReferenceField = GetBaseFieldName(mpLbBaseField->GetSelectEntry());
227 :
228 0 : sal_Int32 nBaseItemPos = mpLbBaseItem->GetSelectEntryPos();
229 0 : switch( nBaseItemPos )
230 : {
231 : case SC_BASEITEM_PREV_POS:
232 0 : aRef.ReferenceItemType = DataPilotFieldReferenceItemType::PREVIOUS;
233 0 : break;
234 : case SC_BASEITEM_NEXT_POS:
235 0 : aRef.ReferenceItemType = DataPilotFieldReferenceItemType::NEXT;
236 0 : break;
237 : default:
238 : {
239 0 : aRef.ReferenceItemType = DataPilotFieldReferenceItemType::NAMED;
240 0 : if( !mbEmptyItem || (nBaseItemPos > SC_BASEITEM_USER_POS) )
241 0 : aRef.ReferenceItemName = GetBaseItemName(mpLbBaseItem->GetSelectEntry());
242 : }
243 : }
244 :
245 0 : return aRef;
246 : }
247 :
248 0 : void ScDPFunctionDlg::Init( const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData )
249 : {
250 : // list box
251 0 : sal_uInt16 nFuncMask = (rFuncData.mnFuncMask == PIVOT_FUNC_NONE) ? PIVOT_FUNC_SUM : rFuncData.mnFuncMask;
252 0 : mpLbFunc->SetSelection( nFuncMask );
253 :
254 : // field name
255 0 : mpFtName->SetText(rLabelData.getDisplayName());
256 :
257 : // handlers
258 0 : mpLbFunc->SetDoubleClickHdl( LINK( this, ScDPFunctionDlg, DblClickHdl ) );
259 0 : mpLbType->SetSelectHdl( LINK( this, ScDPFunctionDlg, SelectHdl ) );
260 0 : mpLbBaseField->SetSelectHdl( LINK( this, ScDPFunctionDlg, SelectHdl ) );
261 :
262 : // base field list box
263 0 : OUString aSelectedEntry;
264 0 : for( ScDPLabelDataVector::const_iterator aIt = mrLabelVec.begin(), aEnd = mrLabelVec.end(); aIt != aEnd; ++aIt )
265 : {
266 0 : mpLbBaseField->InsertEntry(aIt->getDisplayName());
267 : maBaseFieldNameMap.insert(
268 0 : NameMapType::value_type(aIt->getDisplayName(), aIt->maName));
269 0 : if (aIt->maName == rFuncData.maFieldRef.ReferenceField)
270 0 : aSelectedEntry = aIt->getDisplayName();
271 : }
272 :
273 : // base item list box
274 0 : mpLbBaseItem->SetSeparatorPos( SC_BASEITEM_USER_POS - 1 );
275 :
276 : // select field reference type
277 0 : mxLbTypeWrp->SetControlValue( rFuncData.maFieldRef.ReferenceType );
278 0 : SelectHdl( mpLbType ); // enables base field/item list boxes
279 :
280 : // select base field
281 0 : mpLbBaseField->SelectEntry(aSelectedEntry);
282 0 : if( mpLbBaseField->GetSelectEntryPos() >= mpLbBaseField->GetEntryCount() )
283 0 : mpLbBaseField->SelectEntryPos( 0 );
284 0 : SelectHdl( mpLbBaseField ); // fills base item list, selects base item
285 :
286 : // select base item
287 0 : switch( rFuncData.maFieldRef.ReferenceItemType )
288 : {
289 : case DataPilotFieldReferenceItemType::PREVIOUS:
290 0 : mpLbBaseItem->SelectEntryPos( SC_BASEITEM_PREV_POS );
291 0 : break;
292 : case DataPilotFieldReferenceItemType::NEXT:
293 0 : mpLbBaseItem->SelectEntryPos( SC_BASEITEM_NEXT_POS );
294 0 : break;
295 : default:
296 : {
297 0 : if( mbEmptyItem && rFuncData.maFieldRef.ReferenceItemName.isEmpty() )
298 : {
299 : // select special "(empty)" entry added before other items
300 0 : mpLbBaseItem->SelectEntryPos( SC_BASEITEM_USER_POS );
301 : }
302 : else
303 : {
304 0 : sal_Int32 nStartPos = mbEmptyItem ? (SC_BASEITEM_USER_POS + 1) : SC_BASEITEM_USER_POS;
305 0 : sal_Int32 nPos = FindBaseItemPos( rFuncData.maFieldRef.ReferenceItemName, nStartPos );
306 0 : if( nPos >= mpLbBaseItem->GetEntryCount() )
307 0 : nPos = (mpLbBaseItem->GetEntryCount() > SC_BASEITEM_USER_POS) ? SC_BASEITEM_USER_POS : SC_BASEITEM_PREV_POS;
308 0 : mpLbBaseItem->SelectEntryPos( nPos );
309 : }
310 : }
311 0 : }
312 0 : }
313 :
314 0 : const OUString& ScDPFunctionDlg::GetBaseFieldName(const OUString& rLayoutName) const
315 : {
316 0 : NameMapType::const_iterator itr = maBaseFieldNameMap.find(rLayoutName);
317 0 : return itr == maBaseFieldNameMap.end() ? rLayoutName : itr->second;
318 : }
319 :
320 0 : const OUString& ScDPFunctionDlg::GetBaseItemName(const OUString& rLayoutName) const
321 : {
322 0 : NameMapType::const_iterator itr = maBaseItemNameMap.find(rLayoutName);
323 0 : return itr == maBaseItemNameMap.end() ? rLayoutName : itr->second;
324 : }
325 :
326 0 : sal_Int32 ScDPFunctionDlg::FindBaseItemPos( const OUString& rEntry, sal_Int32 nStartPos ) const
327 : {
328 0 : sal_Int32 nPos = nStartPos;
329 0 : bool bFound = false;
330 0 : while (nPos < mpLbBaseItem->GetEntryCount())
331 : {
332 : // translate the displayed field name back to its original field name.
333 0 : const OUString& rName = GetBaseItemName(mpLbBaseItem->GetEntry(nPos));
334 0 : if (rName.equals(rEntry))
335 : {
336 0 : bFound = true;
337 0 : break;
338 : }
339 0 : ++nPos;
340 : }
341 0 : return bFound ? nPos : LISTBOX_ENTRY_NOTFOUND;
342 : }
343 :
344 0 : IMPL_LINK( ScDPFunctionDlg, SelectHdl, ListBox*, pLBox )
345 : {
346 0 : if( pLBox == mpLbType )
347 : {
348 : bool bEnableField, bEnableItem;
349 0 : switch( mxLbTypeWrp->GetControlValue() )
350 : {
351 : case DataPilotFieldReferenceType::ITEM_DIFFERENCE:
352 : case DataPilotFieldReferenceType::ITEM_PERCENTAGE:
353 : case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
354 0 : bEnableField = bEnableItem = true;
355 0 : break;
356 :
357 : case DataPilotFieldReferenceType::RUNNING_TOTAL:
358 0 : bEnableField = true;
359 0 : bEnableItem = false;
360 0 : break;
361 :
362 : default:
363 0 : bEnableField = bEnableItem = false;
364 : }
365 :
366 0 : bEnableField &= mpLbBaseField->GetEntryCount() > 0;
367 0 : mpFtBaseField->Enable( bEnableField );
368 0 : mpLbBaseField->Enable( bEnableField );
369 :
370 0 : bEnableItem &= bEnableField;
371 0 : mpFtBaseItem->Enable( bEnableItem );
372 0 : mpLbBaseItem->Enable( bEnableItem );
373 : }
374 0 : else if( pLBox == mpLbBaseField )
375 : {
376 : // keep "previous" and "next" entries
377 0 : while( mpLbBaseItem->GetEntryCount() > SC_BASEITEM_USER_POS )
378 0 : mpLbBaseItem->RemoveEntry( SC_BASEITEM_USER_POS );
379 :
380 : // update item list for current base field
381 0 : mbEmptyItem = false;
382 0 : size_t nBasePos = mpLbBaseField->GetSelectEntryPos();
383 0 : if( nBasePos < mrLabelVec.size() )
384 : {
385 0 : const vector<ScDPLabelData::Member>& rMembers = mrLabelVec[nBasePos].maMembers;
386 0 : mbEmptyItem = lclFillListBox(*mpLbBaseItem, rMembers, SC_BASEITEM_USER_POS);
387 : // build cache for base names.
388 0 : NameMapType aMap;
389 0 : vector<ScDPLabelData::Member>::const_iterator itr = rMembers.begin(), itrEnd = rMembers.end();
390 0 : for (; itr != itrEnd; ++itr)
391 0 : aMap.insert(NameMapType::value_type(itr->getDisplayName(), itr->maName));
392 0 : maBaseItemNameMap.swap(aMap);
393 : }
394 :
395 : // select base item
396 0 : sal_uInt16 nItemPos = (mpLbBaseItem->GetEntryCount() > SC_BASEITEM_USER_POS) ? SC_BASEITEM_USER_POS : SC_BASEITEM_PREV_POS;
397 0 : mpLbBaseItem->SelectEntryPos( nItemPos );
398 : }
399 0 : return 0;
400 : }
401 :
402 0 : IMPL_LINK_NOARG(ScDPFunctionDlg, DblClickHdl)
403 : {
404 0 : mpBtnOk->Click();
405 0 : return 0;
406 : }
407 :
408 0 : ScDPSubtotalDlg::ScDPSubtotalDlg( Window* pParent, ScDPObject& rDPObj,
409 : const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData,
410 : const ScDPNameVec& rDataFields, bool bEnableLayout )
411 : : ModalDialog(pParent, "PivotFieldDialog",
412 : "modules/scalc/ui/pivotfielddialog.ui")
413 : , mrDPObj(rDPObj)
414 : , mrDataFields(rDataFields)
415 : , maLabelData(rLabelData)
416 0 : , mbEnableLayout(bEnableLayout)
417 : {
418 0 : get(mpBtnOk, "ok");
419 0 : get(mpBtnOptions, "options");
420 0 : get(mpCbShowAll, "showall");
421 0 : get(mpFtName, "name");
422 0 : get(mpLbFunc, "functions");
423 0 : mpLbFunc->EnableMultiSelection(true);
424 0 : mpLbFunc->set_height_request(mpLbFunc->GetTextHeight() * 8);
425 0 : get(mpRbNone, "none");
426 0 : get(mpRbAuto, "auto");
427 0 : get(mpRbUser, "user");
428 :
429 0 : Init( rLabelData, rFuncData );
430 0 : }
431 :
432 0 : sal_uInt16 ScDPSubtotalDlg::GetFuncMask() const
433 : {
434 0 : sal_uInt16 nFuncMask = PIVOT_FUNC_NONE;
435 :
436 0 : if( mpRbAuto->IsChecked() )
437 0 : nFuncMask = PIVOT_FUNC_AUTO;
438 0 : else if( mpRbUser->IsChecked() )
439 0 : nFuncMask = mpLbFunc->GetSelection();
440 :
441 0 : return nFuncMask;
442 : }
443 :
444 0 : void ScDPSubtotalDlg::FillLabelData( ScDPLabelData& rLabelData ) const
445 : {
446 0 : rLabelData.mnFuncMask = GetFuncMask();
447 0 : rLabelData.mnUsedHier = maLabelData.mnUsedHier;
448 0 : rLabelData.mbShowAll = mpCbShowAll->IsChecked();
449 0 : rLabelData.maMembers = maLabelData.maMembers;
450 0 : rLabelData.maSortInfo = maLabelData.maSortInfo;
451 0 : rLabelData.maLayoutInfo = maLabelData.maLayoutInfo;
452 0 : rLabelData.maShowInfo = maLabelData.maShowInfo;
453 0 : }
454 :
455 0 : void ScDPSubtotalDlg::Init( const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData )
456 : {
457 : // field name
458 0 : mpFtName->SetText(rLabelData.getDisplayName());
459 :
460 : // radio buttons
461 0 : mpRbNone->SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
462 0 : mpRbAuto->SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
463 0 : mpRbUser->SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
464 :
465 0 : RadioButton* pRBtn = 0;
466 0 : switch( rFuncData.mnFuncMask )
467 : {
468 0 : case PIVOT_FUNC_NONE: pRBtn = mpRbNone; break;
469 0 : case PIVOT_FUNC_AUTO: pRBtn = mpRbAuto; break;
470 0 : default: pRBtn = mpRbUser;
471 : }
472 0 : pRBtn->Check();
473 0 : RadioClickHdl( pRBtn );
474 :
475 : // list box
476 0 : mpLbFunc->SetSelection( rFuncData.mnFuncMask );
477 0 : mpLbFunc->SetDoubleClickHdl( LINK( this, ScDPSubtotalDlg, DblClickHdl ) );
478 :
479 : // show all
480 0 : mpCbShowAll->Check( rLabelData.mbShowAll );
481 :
482 : // options
483 0 : mpBtnOptions->SetClickHdl( LINK( this, ScDPSubtotalDlg, ClickHdl ) );
484 0 : }
485 :
486 0 : IMPL_LINK( ScDPSubtotalDlg, RadioClickHdl, RadioButton*, pBtn )
487 : {
488 0 : mpLbFunc->Enable( pBtn == mpRbUser );
489 0 : return 0;
490 : }
491 :
492 0 : IMPL_LINK_NOARG(ScDPSubtotalDlg, DblClickHdl)
493 : {
494 0 : mpBtnOk->Click();
495 0 : return 0;
496 : }
497 :
498 0 : IMPL_LINK( ScDPSubtotalDlg, ClickHdl, PushButton*, pBtn )
499 : {
500 0 : if (pBtn == mpBtnOptions)
501 : {
502 0 : ScDPSubtotalOptDlg* pDlg = new ScDPSubtotalOptDlg( this, mrDPObj, maLabelData, mrDataFields, mbEnableLayout );
503 0 : if( pDlg->Execute() == RET_OK )
504 0 : pDlg->FillLabelData( maLabelData );
505 0 : delete pDlg;
506 : }
507 0 : return 0;
508 : }
509 :
510 0 : ScDPSubtotalOptDlg::ScDPSubtotalOptDlg( Window* pParent, ScDPObject& rDPObj,
511 : const ScDPLabelData& rLabelData, const ScDPNameVec& rDataFields,
512 : bool bEnableLayout )
513 : : ModalDialog(pParent, "DataFieldOptionsDialog",
514 : "modules/scalc/ui/datafieldoptionsdialog.ui")
515 : , mrDPObj(rDPObj)
516 0 : , maLabelData(rLabelData)
517 : {
518 0 : get(m_pLbSortBy, "sortby");
519 0 : m_pLbSortBy->set_width_request(m_pLbSortBy->approximate_char_width() * 20);
520 0 : get(m_pRbSortAsc, "ascending");
521 0 : get(m_pRbSortDesc, "descending");
522 0 : get(m_pRbSortMan, "manual");
523 0 : get(m_pLayoutFrame, "layoutframe");
524 0 : get(m_pLbLayout, "layout");
525 0 : get(m_pCbLayoutEmpty, "emptyline");
526 0 : get(m_pCbShow, "show");
527 0 : get(m_pNfShow, "items");
528 0 : get(m_pFtShow, "showft");
529 0 : get(m_pFtShowFrom, "showfromft");
530 0 : get(m_pLbShowFrom, "from");
531 0 : get(m_pFtShowUsing, "usingft");
532 0 : get(m_pLbShowUsing, "using");
533 0 : get(m_pHideFrame, "hideframe");
534 0 : get(m_pLbHide, "hideitems");
535 0 : m_pLbHide->set_height_request(GetTextHeight() * 5);
536 0 : get(m_pFtHierarchy, "hierarchyft");
537 0 : get(m_pLbHierarchy, "hierarchy");
538 :
539 0 : m_xLbLayoutWrp.reset(new ScDPListBoxWrapper(*m_pLbLayout, spLayoutMap));
540 0 : m_xLbShowFromWrp.reset(new ScDPListBoxWrapper(*m_pLbShowFrom, spShowFromMap));
541 :
542 0 : Init( rDataFields, bEnableLayout );
543 0 : }
544 :
545 0 : void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData& rLabelData ) const
546 : {
547 : // *** SORTING ***
548 :
549 0 : if( m_pRbSortMan->IsChecked() )
550 0 : rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::MANUAL;
551 0 : else if( m_pLbSortBy->GetSelectEntryPos() == SC_SORTNAME_POS )
552 0 : rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::NAME;
553 : else
554 0 : rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::DATA;
555 :
556 0 : ScDPName aFieldName = GetFieldName(m_pLbSortBy->GetSelectEntry());
557 0 : if (!aFieldName.maName.isEmpty())
558 : {
559 0 : rLabelData.maSortInfo.Field =
560 0 : ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount);
561 0 : rLabelData.maSortInfo.IsAscending = m_pRbSortAsc->IsChecked();
562 : }
563 :
564 : // *** LAYOUT MODE ***
565 :
566 0 : rLabelData.maLayoutInfo.LayoutMode = m_xLbLayoutWrp->GetControlValue();
567 0 : rLabelData.maLayoutInfo.AddEmptyLines = m_pCbLayoutEmpty->IsChecked();
568 :
569 : // *** AUTO SHOW ***
570 :
571 0 : aFieldName = GetFieldName(m_pLbShowUsing->GetSelectEntry());
572 0 : if (!aFieldName.maName.isEmpty())
573 : {
574 0 : rLabelData.maShowInfo.IsEnabled = m_pCbShow->IsChecked();
575 0 : rLabelData.maShowInfo.ShowItemsMode = m_xLbShowFromWrp->GetControlValue();
576 0 : rLabelData.maShowInfo.ItemCount = sal::static_int_cast<sal_Int32>( m_pNfShow->GetValue() );
577 0 : rLabelData.maShowInfo.DataField =
578 0 : ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount);
579 : }
580 :
581 : // *** HIDDEN ITEMS ***
582 :
583 0 : rLabelData.maMembers = maLabelData.maMembers;
584 0 : sal_uLong nVisCount = m_pLbHide->GetEntryCount();
585 0 : for( sal_uInt16 nPos = 0; nPos < nVisCount; ++nPos )
586 0 : rLabelData.maMembers[nPos].mbVisible = !m_pLbHide->IsChecked(nPos);
587 :
588 : // *** HIERARCHY ***
589 :
590 0 : rLabelData.mnUsedHier = m_pLbHierarchy->GetSelectEntryCount() ? m_pLbHierarchy->GetSelectEntryPos() : 0;
591 0 : }
592 :
593 0 : void ScDPSubtotalOptDlg::Init( const ScDPNameVec& rDataFields, bool bEnableLayout )
594 : {
595 : // *** SORTING ***
596 :
597 0 : sal_Int32 nSortMode = maLabelData.maSortInfo.Mode;
598 :
599 : // sort fields list box
600 0 : m_pLbSortBy->InsertEntry(maLabelData.getDisplayName());
601 :
602 0 : for( ScDPNameVec::const_iterator aIt = rDataFields.begin(), aEnd = rDataFields.end(); aIt != aEnd; ++aIt )
603 : {
604 : // Cache names for later lookup.
605 0 : maDataFieldNameMap.insert(NameMapType::value_type(aIt->maLayoutName, *aIt));
606 :
607 0 : m_pLbSortBy->InsertEntry( aIt->maLayoutName );
608 0 : m_pLbShowUsing->InsertEntry( aIt->maLayoutName ); // for AutoShow
609 : }
610 :
611 0 : if( m_pLbSortBy->GetEntryCount() > SC_SORTDATA_POS )
612 0 : m_pLbSortBy->SetSeparatorPos( SC_SORTDATA_POS - 1 );
613 :
614 0 : sal_Int32 nSortPos = SC_SORTNAME_POS;
615 0 : if( nSortMode == DataPilotFieldSortMode::DATA )
616 : {
617 0 : nSortPos = FindListBoxEntry( *m_pLbSortBy, maLabelData.maSortInfo.Field, SC_SORTDATA_POS );
618 0 : if( nSortPos >= m_pLbSortBy->GetEntryCount() )
619 : {
620 0 : nSortPos = SC_SORTNAME_POS;
621 0 : nSortMode = DataPilotFieldSortMode::MANUAL;
622 : }
623 : }
624 0 : m_pLbSortBy->SelectEntryPos( nSortPos );
625 :
626 : // sorting mode
627 0 : m_pRbSortAsc->SetClickHdl( LINK( this, ScDPSubtotalOptDlg, RadioClickHdl ) );
628 0 : m_pRbSortDesc->SetClickHdl( LINK( this, ScDPSubtotalOptDlg, RadioClickHdl ) );
629 0 : m_pRbSortMan->SetClickHdl( LINK( this, ScDPSubtotalOptDlg, RadioClickHdl ) );
630 :
631 0 : RadioButton* pRBtn = 0;
632 0 : switch( nSortMode )
633 : {
634 : case DataPilotFieldSortMode::NONE:
635 : case DataPilotFieldSortMode::MANUAL:
636 0 : pRBtn = m_pRbSortMan;
637 0 : break;
638 : default:
639 0 : pRBtn = maLabelData.maSortInfo.IsAscending ? m_pRbSortAsc : m_pRbSortDesc;
640 : }
641 0 : pRBtn->Check();
642 0 : RadioClickHdl( pRBtn );
643 :
644 : // *** LAYOUT MODE ***
645 :
646 0 : m_pLayoutFrame->Enable(bEnableLayout);
647 :
648 0 : m_xLbLayoutWrp->SetControlValue( maLabelData.maLayoutInfo.LayoutMode );
649 0 : m_pCbLayoutEmpty->Check( maLabelData.maLayoutInfo.AddEmptyLines );
650 :
651 : // *** AUTO SHOW ***
652 :
653 0 : m_pCbShow->Check( maLabelData.maShowInfo.IsEnabled );
654 0 : m_pCbShow->SetClickHdl( LINK( this, ScDPSubtotalOptDlg, CheckHdl ) );
655 :
656 0 : m_xLbShowFromWrp->SetControlValue( maLabelData.maShowInfo.ShowItemsMode );
657 0 : long nCount = static_cast< long >( maLabelData.maShowInfo.ItemCount );
658 0 : if( nCount < 1 )
659 0 : nCount = SC_SHOW_DEFAULT;
660 0 : m_pNfShow->SetValue( nCount );
661 :
662 : // m_pLbShowUsing already filled above
663 0 : m_pLbShowUsing->SelectEntry( maLabelData.maShowInfo.DataField );
664 0 : if( m_pLbShowUsing->GetSelectEntryPos() >= m_pLbShowUsing->GetEntryCount() )
665 0 : m_pLbShowUsing->SelectEntryPos( 0 );
666 :
667 0 : CheckHdl(m_pCbShow); // enable/disable dependent controls
668 :
669 : // *** HIDDEN ITEMS ***
670 :
671 0 : InitHideListBox();
672 :
673 : // *** HIERARCHY ***
674 :
675 0 : if( maLabelData.maHiers.getLength() > 1 )
676 : {
677 0 : lclFillListBox( *m_pLbHierarchy, maLabelData.maHiers );
678 0 : sal_Int32 nHier = maLabelData.mnUsedHier;
679 0 : if( (nHier < 0) || (nHier >= maLabelData.maHiers.getLength()) ) nHier = 0;
680 0 : m_pLbHierarchy->SelectEntryPos( static_cast< sal_Int32 >( nHier ) );
681 0 : m_pLbHierarchy->SetSelectHdl( LINK( this, ScDPSubtotalOptDlg, SelectHdl ) );
682 : }
683 : else
684 : {
685 0 : m_pFtHierarchy->Disable();
686 0 : m_pLbHierarchy->Disable();
687 : }
688 0 : }
689 :
690 0 : void ScDPSubtotalOptDlg::InitHideListBox()
691 : {
692 0 : m_pLbHide->Clear();
693 0 : lclFillListBox( *m_pLbHide, maLabelData.maMembers );
694 0 : size_t n = maLabelData.maMembers.size();
695 0 : for (sal_uLong i = 0; i < n; ++i)
696 0 : m_pLbHide->CheckEntryPos(i, !maLabelData.maMembers[i].mbVisible);
697 0 : bool bEnable = m_pLbHide->GetEntryCount() > 0;
698 0 : m_pHideFrame->Enable(bEnable);
699 0 : }
700 :
701 0 : ScDPName ScDPSubtotalOptDlg::GetFieldName(const OUString& rLayoutName) const
702 : {
703 0 : NameMapType::const_iterator itr = maDataFieldNameMap.find(rLayoutName);
704 0 : return itr == maDataFieldNameMap.end() ? ScDPName() : itr->second;
705 : }
706 :
707 0 : sal_Int32 ScDPSubtotalOptDlg::FindListBoxEntry(
708 : const ListBox& rLBox, const OUString& rEntry, sal_Int32 nStartPos ) const
709 : {
710 0 : sal_Int32 nPos = nStartPos;
711 0 : bool bFound = false;
712 0 : while (nPos < rLBox.GetEntryCount())
713 : {
714 : // translate the displayed field name back to its original field name.
715 0 : ScDPName aName = GetFieldName(rLBox.GetEntry(nPos));
716 0 : OUString aUnoName = ScDPUtil::createDuplicateDimensionName(aName.maName, aName.mnDupCount);
717 0 : if (aUnoName.equals(rEntry))
718 : {
719 0 : bFound = true;
720 0 : break;
721 : }
722 0 : ++nPos;
723 0 : }
724 0 : return bFound ? nPos : LISTBOX_ENTRY_NOTFOUND;
725 : }
726 :
727 0 : IMPL_LINK( ScDPSubtotalOptDlg, RadioClickHdl, RadioButton*, pBtn )
728 : {
729 0 : m_pLbSortBy->Enable( pBtn != m_pRbSortMan );
730 0 : return 0;
731 : }
732 :
733 0 : IMPL_LINK( ScDPSubtotalOptDlg, CheckHdl, CheckBox*, pCBox )
734 : {
735 0 : if (pCBox == m_pCbShow)
736 : {
737 0 : bool bEnable = m_pCbShow->IsChecked();
738 0 : m_pNfShow->Enable( bEnable );
739 0 : m_pFtShow->Enable( bEnable );
740 0 : m_pFtShowFrom->Enable( bEnable );
741 0 : m_pLbShowFrom->Enable( bEnable );
742 :
743 0 : bool bEnableUsing = bEnable && (m_pLbShowUsing->GetEntryCount() > 0);
744 0 : m_pFtShowUsing->Enable(bEnableUsing);
745 0 : m_pLbShowUsing->Enable(bEnableUsing);
746 : }
747 0 : return 0;
748 : }
749 :
750 0 : IMPL_LINK( ScDPSubtotalOptDlg, SelectHdl, ListBox*, pLBox )
751 : {
752 0 : if (pLBox == m_pLbHierarchy)
753 : {
754 0 : mrDPObj.GetMembers(maLabelData.mnCol, m_pLbHierarchy->GetSelectEntryPos(), maLabelData.maMembers);
755 0 : InitHideListBox();
756 : }
757 0 : return 0;
758 : }
759 :
760 0 : ScDPShowDetailDlg::ScDPShowDetailDlg( Window* pParent, ScDPObject& rDPObj, sal_uInt16 nOrient ) :
761 : ModalDialog ( pParent, ScResId( RID_SCDLG_DPSHOWDETAIL ) ),
762 : maFtDims ( this, ScResId( FT_DIMS ) ),
763 : maLbDims ( this, ScResId( LB_DIMS ) ),
764 : maBtnOk ( this, ScResId( BTN_OK ) ),
765 : maBtnCancel ( this, ScResId( BTN_CANCEL ) ),
766 : maBtnHelp ( this, ScResId( BTN_HELP ) ),
767 :
768 0 : mrDPObj(rDPObj)
769 : {
770 0 : FreeResource();
771 :
772 0 : ScDPSaveData* pSaveData = rDPObj.GetSaveData();
773 0 : long nDimCount = rDPObj.GetDimCount();
774 0 : for (long nDim=0; nDim<nDimCount; nDim++)
775 : {
776 : bool bIsDataLayout;
777 0 : sal_Int32 nDimFlags = 0;
778 0 : OUString aName = rDPObj.GetDimName( nDim, bIsDataLayout, &nDimFlags );
779 0 : if ( !bIsDataLayout && !rDPObj.IsDuplicated( nDim ) && ScDPObject::IsOrientationAllowed( nOrient, nDimFlags ) )
780 : {
781 0 : const ScDPSaveDimension* pDimension = pSaveData ? pSaveData->GetExistingDimensionByName(aName) : 0;
782 0 : if ( !pDimension || (pDimension->GetOrientation() != nOrient) )
783 : {
784 0 : if (pDimension)
785 : {
786 0 : const OUString* pLayoutName = pDimension->GetLayoutName();
787 0 : if (pLayoutName)
788 0 : aName = *pLayoutName;
789 : }
790 0 : maLbDims.InsertEntry( aName );
791 0 : maNameIndexMap.insert(DimNameIndexMap::value_type(aName, nDim));
792 : }
793 : }
794 0 : }
795 0 : if( maLbDims.GetEntryCount() )
796 0 : maLbDims.SelectEntryPos( 0 );
797 :
798 0 : maLbDims.SetDoubleClickHdl( LINK( this, ScDPShowDetailDlg, DblClickHdl ) );
799 0 : }
800 :
801 0 : short ScDPShowDetailDlg::Execute()
802 : {
803 0 : return maLbDims.GetEntryCount() ? ModalDialog::Execute() : static_cast<short>(RET_CANCEL);
804 : }
805 :
806 0 : OUString ScDPShowDetailDlg::GetDimensionName() const
807 : {
808 : // Look up the internal dimension name which may be different from the
809 : // displayed field name.
810 0 : OUString aSelectedName = maLbDims.GetSelectEntry();
811 0 : DimNameIndexMap::const_iterator itr = maNameIndexMap.find(aSelectedName);
812 0 : if (itr == maNameIndexMap.end())
813 : // This should never happen!
814 0 : return aSelectedName;
815 :
816 0 : long nDim = itr->second;
817 0 : bool bIsDataLayout = false;
818 0 : return mrDPObj.GetDimName(nDim, bIsDataLayout);
819 : }
820 :
821 0 : IMPL_LINK( ScDPShowDetailDlg, DblClickHdl, ListBox*, pLBox )
822 : {
823 0 : if( pLBox == &maLbDims )
824 0 : maBtnOk.Click();
825 0 : return 0;
826 0 : }
827 :
828 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|