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 "sc.hrc"
38 : #include "globstr.hrc"
39 : #include "dputil.hxx"
40 :
41 : #include <vector>
42 : #include <boost/scoped_ptr.hpp>
43 :
44 : using namespace ::com::sun::star::sheet;
45 :
46 : using ::com::sun::star::uno::Sequence;
47 : using ::std::vector;
48 :
49 : namespace {
50 :
51 : /** Appends all strings from the Sequence to the list box.
52 :
53 : Empty strings are replaced by a localized "(empty)" entry and inserted at
54 : the specified position.
55 :
56 : @return true = The passed string list contains an empty string entry.
57 : */
58 : template< typename ListBoxType >
59 0 : bool lclFillListBox( ListBoxType& rLBox, const Sequence< OUString >& rStrings, sal_Int32 nEmptyPos = LISTBOX_APPEND )
60 : {
61 0 : bool bEmpty = false;
62 0 : const OUString* pStr = rStrings.getConstArray();
63 0 : if( pStr )
64 : {
65 0 : for( const OUString* pEnd = pStr + rStrings.getLength(); pStr != pEnd; ++pStr )
66 : {
67 0 : if( !pStr->isEmpty() )
68 0 : rLBox.InsertEntry( *pStr );
69 : else
70 : {
71 0 : rLBox.InsertEntry( ScGlobal::GetRscString( STR_EMPTYDATA ), nEmptyPos );
72 0 : bEmpty = true;
73 : }
74 : }
75 : }
76 0 : return bEmpty;
77 : }
78 :
79 : template< typename ListBoxType >
80 0 : bool lclFillListBox( ListBoxType& rLBox, const vector<ScDPLabelData::Member>& rMembers, sal_Int32 nEmptyPos = LISTBOX_APPEND )
81 : {
82 0 : bool bEmpty = false;
83 0 : vector<ScDPLabelData::Member>::const_iterator itr = rMembers.begin(), itrEnd = rMembers.end();
84 0 : for (; itr != itrEnd; ++itr)
85 : {
86 0 : OUString aName = itr->getDisplayName();
87 0 : if (!aName.isEmpty())
88 0 : rLBox.InsertEntry(aName);
89 : else
90 : {
91 0 : rLBox.InsertEntry(ScGlobal::GetRscString(STR_EMPTYDATA), nEmptyPos);
92 0 : bEmpty = true;
93 : }
94 : }
95 0 : return bEmpty;
96 : }
97 :
98 : /** This table represents the order of the strings in the resource string array. */
99 : static const sal_uInt16 spnFunctions[] =
100 : {
101 : PIVOT_FUNC_SUM,
102 : PIVOT_FUNC_COUNT,
103 : PIVOT_FUNC_AVERAGE,
104 : PIVOT_FUNC_MAX,
105 : PIVOT_FUNC_MIN,
106 : PIVOT_FUNC_PRODUCT,
107 : PIVOT_FUNC_COUNT_NUM,
108 : PIVOT_FUNC_STD_DEV,
109 : PIVOT_FUNC_STD_DEVP,
110 : PIVOT_FUNC_STD_VAR,
111 : PIVOT_FUNC_STD_VARP
112 : };
113 :
114 : const sal_uInt16 SC_BASEITEM_PREV_POS = 0;
115 : const sal_uInt16 SC_BASEITEM_NEXT_POS = 1;
116 : const sal_uInt16 SC_BASEITEM_USER_POS = 2;
117 :
118 : const sal_uInt16 SC_SORTNAME_POS = 0;
119 : const sal_uInt16 SC_SORTDATA_POS = 1;
120 :
121 : const long SC_SHOW_DEFAULT = 10;
122 :
123 : static const ScDPListBoxWrapper::MapEntryType spRefTypeMap[] =
124 : {
125 : { 0, DataPilotFieldReferenceType::NONE },
126 : { 1, DataPilotFieldReferenceType::ITEM_DIFFERENCE },
127 : { 2, DataPilotFieldReferenceType::ITEM_PERCENTAGE },
128 : { 3, DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE },
129 : { 4, DataPilotFieldReferenceType::RUNNING_TOTAL },
130 : { 5, DataPilotFieldReferenceType::ROW_PERCENTAGE },
131 : { 6, DataPilotFieldReferenceType::COLUMN_PERCENTAGE },
132 : { 7, DataPilotFieldReferenceType::TOTAL_PERCENTAGE },
133 : { 8, DataPilotFieldReferenceType::INDEX },
134 : { WRAPPER_LISTBOX_ENTRY_NOTFOUND, DataPilotFieldReferenceType::NONE }
135 : };
136 :
137 : static const ScDPListBoxWrapper::MapEntryType spLayoutMap[] =
138 : {
139 : { 0, DataPilotFieldLayoutMode::TABULAR_LAYOUT },
140 : { 1, DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP },
141 : { 2, DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM },
142 : { WRAPPER_LISTBOX_ENTRY_NOTFOUND, DataPilotFieldLayoutMode::TABULAR_LAYOUT }
143 : };
144 :
145 : static const ScDPListBoxWrapper::MapEntryType spShowFromMap[] =
146 : {
147 : { 0, DataPilotFieldShowItemsMode::FROM_TOP },
148 : { 1, DataPilotFieldShowItemsMode::FROM_BOTTOM },
149 : { WRAPPER_LISTBOX_ENTRY_NOTFOUND, DataPilotFieldShowItemsMode::FROM_TOP }
150 : };
151 :
152 : } // namespace
153 :
154 0 : ScDPFunctionListBox::ScDPFunctionListBox(vcl::Window* pParent, WinBits nStyle)
155 0 : : ListBox(pParent, nStyle)
156 : {
157 0 : FillFunctionNames();
158 0 : }
159 :
160 0 : extern "C" SAL_DLLPUBLIC_EXPORT vcl::Window* SAL_CALL makeScDPFunctionListBox(vcl::Window *pParent, VclBuilder::stringmap &rMap)
161 : {
162 0 : WinBits nWinStyle = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_SIMPLEMODE;
163 0 : OString sBorder = VclBuilder::extractCustomProperty(rMap);
164 0 : if (!sBorder.isEmpty())
165 0 : nWinStyle |= WB_BORDER;
166 0 : return new ScDPFunctionListBox(pParent, nWinStyle);
167 : }
168 :
169 0 : void ScDPFunctionListBox::SetSelection( sal_uInt16 nFuncMask )
170 : {
171 0 : if( (nFuncMask == PIVOT_FUNC_NONE) || (nFuncMask == PIVOT_FUNC_AUTO) )
172 0 : SetNoSelection();
173 : else
174 0 : for( sal_Int32 nEntry = 0, nCount = GetEntryCount(); nEntry < nCount; ++nEntry )
175 0 : SelectEntryPos( nEntry, (nFuncMask & spnFunctions[ nEntry ]) != 0 );
176 0 : }
177 :
178 0 : sal_uInt16 ScDPFunctionListBox::GetSelection() const
179 : {
180 0 : sal_uInt16 nFuncMask = PIVOT_FUNC_NONE;
181 0 : for( sal_Int32 nSel = 0, nCount = GetSelectEntryCount(); nSel < nCount; ++nSel )
182 0 : nFuncMask |= spnFunctions[ GetSelectEntryPos( nSel ) ];
183 0 : return nFuncMask;
184 : }
185 :
186 0 : void ScDPFunctionListBox::FillFunctionNames()
187 : {
188 : OSL_ENSURE( !GetEntryCount(), "ScDPMultiFuncListBox::FillFunctionNames - do not add texts to resource" );
189 0 : Clear();
190 0 : ResStringArray aArr( ScResId( SCSTR_DPFUNCLISTBOX ) );
191 0 : for( sal_uInt16 nIndex = 0, nCount = sal::static_int_cast<sal_uInt16>(aArr.Count()); nIndex < nCount; ++nIndex )
192 0 : InsertEntry( aArr.GetString( nIndex ) );
193 0 : }
194 :
195 0 : ScDPFunctionDlg::ScDPFunctionDlg(
196 : vcl::Window* pParent, const ScDPLabelDataVector& rLabelVec,
197 : const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData)
198 : : ModalDialog(pParent, "DataFieldDialog",
199 : "modules/scalc/ui/datafielddialog.ui")
200 : , mrLabelVec(rLabelVec)
201 0 : , mbEmptyItem(false)
202 : {
203 0 : get(mpFtName, "name");
204 0 : get(mpLbType, "type");
205 0 : mxLbTypeWrp.reset(new ScDPListBoxWrapper(*mpLbType, spRefTypeMap));
206 0 : get(mpLbFunc, "functions");
207 0 : mpLbFunc->set_height_request(mpLbFunc->GetTextHeight() * 8);
208 0 : get(mpFtBaseField, "basefieldft");
209 0 : get(mpLbBaseField, "basefield");
210 0 : get(mpFtBaseItem, "baseitemft");
211 0 : get(mpLbBaseItem, "baseitem");
212 0 : get(mpBtnOk, "ok");
213 :
214 0 : Init( rLabelData, rFuncData );
215 0 : }
216 :
217 0 : sal_uInt16 ScDPFunctionDlg::GetFuncMask() const
218 : {
219 0 : return mpLbFunc->GetSelection();
220 : }
221 :
222 0 : DataPilotFieldReference ScDPFunctionDlg::GetFieldRef() const
223 : {
224 0 : DataPilotFieldReference aRef;
225 :
226 0 : aRef.ReferenceType = mxLbTypeWrp->GetControlValue();
227 0 : aRef.ReferenceField = GetBaseFieldName(mpLbBaseField->GetSelectEntry());
228 :
229 0 : sal_Int32 nBaseItemPos = mpLbBaseItem->GetSelectEntryPos();
230 0 : switch( nBaseItemPos )
231 : {
232 : case SC_BASEITEM_PREV_POS:
233 0 : aRef.ReferenceItemType = DataPilotFieldReferenceItemType::PREVIOUS;
234 0 : break;
235 : case SC_BASEITEM_NEXT_POS:
236 0 : aRef.ReferenceItemType = DataPilotFieldReferenceItemType::NEXT;
237 0 : break;
238 : default:
239 : {
240 0 : aRef.ReferenceItemType = DataPilotFieldReferenceItemType::NAMED;
241 0 : if( !mbEmptyItem || (nBaseItemPos > SC_BASEITEM_USER_POS) )
242 0 : aRef.ReferenceItemName = GetBaseItemName(mpLbBaseItem->GetSelectEntry());
243 : }
244 : }
245 :
246 0 : return aRef;
247 : }
248 :
249 0 : void ScDPFunctionDlg::Init( const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData )
250 : {
251 : // list box
252 0 : sal_uInt16 nFuncMask = (rFuncData.mnFuncMask == PIVOT_FUNC_NONE) ? PIVOT_FUNC_SUM : rFuncData.mnFuncMask;
253 0 : mpLbFunc->SetSelection( nFuncMask );
254 :
255 : // field name
256 0 : mpFtName->SetText(rLabelData.getDisplayName());
257 :
258 : // handlers
259 0 : mpLbFunc->SetDoubleClickHdl( LINK( this, ScDPFunctionDlg, DblClickHdl ) );
260 0 : mpLbType->SetSelectHdl( LINK( this, ScDPFunctionDlg, SelectHdl ) );
261 0 : mpLbBaseField->SetSelectHdl( LINK( this, ScDPFunctionDlg, SelectHdl ) );
262 :
263 : // base field list box
264 0 : OUString aSelectedEntry;
265 0 : for( ScDPLabelDataVector::const_iterator aIt = mrLabelVec.begin(), aEnd = mrLabelVec.end(); aIt != aEnd; ++aIt )
266 : {
267 0 : mpLbBaseField->InsertEntry(aIt->getDisplayName());
268 : maBaseFieldNameMap.insert(
269 0 : NameMapType::value_type(aIt->getDisplayName(), aIt->maName));
270 0 : if (aIt->maName == rFuncData.maFieldRef.ReferenceField)
271 0 : aSelectedEntry = aIt->getDisplayName();
272 : }
273 :
274 : // base item list box
275 0 : mpLbBaseItem->SetSeparatorPos( SC_BASEITEM_USER_POS - 1 );
276 :
277 : // select field reference type
278 0 : mxLbTypeWrp->SetControlValue( rFuncData.maFieldRef.ReferenceType );
279 0 : SelectHdl( mpLbType ); // enables base field/item list boxes
280 :
281 : // select base field
282 0 : mpLbBaseField->SelectEntry(aSelectedEntry);
283 0 : if( mpLbBaseField->GetSelectEntryPos() >= mpLbBaseField->GetEntryCount() )
284 0 : mpLbBaseField->SelectEntryPos( 0 );
285 0 : SelectHdl( mpLbBaseField ); // fills base item list, selects base item
286 :
287 : // select base item
288 0 : switch( rFuncData.maFieldRef.ReferenceItemType )
289 : {
290 : case DataPilotFieldReferenceItemType::PREVIOUS:
291 0 : mpLbBaseItem->SelectEntryPos( SC_BASEITEM_PREV_POS );
292 0 : break;
293 : case DataPilotFieldReferenceItemType::NEXT:
294 0 : mpLbBaseItem->SelectEntryPos( SC_BASEITEM_NEXT_POS );
295 0 : break;
296 : default:
297 : {
298 0 : if( mbEmptyItem && rFuncData.maFieldRef.ReferenceItemName.isEmpty() )
299 : {
300 : // select special "(empty)" entry added before other items
301 0 : mpLbBaseItem->SelectEntryPos( SC_BASEITEM_USER_POS );
302 : }
303 : else
304 : {
305 0 : sal_Int32 nStartPos = mbEmptyItem ? (SC_BASEITEM_USER_POS + 1) : SC_BASEITEM_USER_POS;
306 0 : sal_Int32 nPos = FindBaseItemPos( rFuncData.maFieldRef.ReferenceItemName, nStartPos );
307 0 : if( nPos >= mpLbBaseItem->GetEntryCount() )
308 0 : nPos = (mpLbBaseItem->GetEntryCount() > SC_BASEITEM_USER_POS) ? SC_BASEITEM_USER_POS : SC_BASEITEM_PREV_POS;
309 0 : mpLbBaseItem->SelectEntryPos( nPos );
310 : }
311 : }
312 0 : }
313 0 : }
314 :
315 0 : const OUString& ScDPFunctionDlg::GetBaseFieldName(const OUString& rLayoutName) const
316 : {
317 0 : NameMapType::const_iterator itr = maBaseFieldNameMap.find(rLayoutName);
318 0 : return itr == maBaseFieldNameMap.end() ? rLayoutName : itr->second;
319 : }
320 :
321 0 : const OUString& ScDPFunctionDlg::GetBaseItemName(const OUString& rLayoutName) const
322 : {
323 0 : NameMapType::const_iterator itr = maBaseItemNameMap.find(rLayoutName);
324 0 : return itr == maBaseItemNameMap.end() ? rLayoutName : itr->second;
325 : }
326 :
327 0 : sal_Int32 ScDPFunctionDlg::FindBaseItemPos( const OUString& rEntry, sal_Int32 nStartPos ) const
328 : {
329 0 : sal_Int32 nPos = nStartPos;
330 0 : bool bFound = false;
331 0 : while (nPos < mpLbBaseItem->GetEntryCount())
332 : {
333 : // translate the displayed field name back to its original field name.
334 0 : const OUString& rName = GetBaseItemName(mpLbBaseItem->GetEntry(nPos));
335 0 : if (rName.equals(rEntry))
336 : {
337 0 : bFound = true;
338 0 : break;
339 : }
340 0 : ++nPos;
341 : }
342 0 : return bFound ? nPos : LISTBOX_ENTRY_NOTFOUND;
343 : }
344 :
345 0 : IMPL_LINK( ScDPFunctionDlg, SelectHdl, ListBox*, pLBox )
346 : {
347 0 : if( pLBox == mpLbType )
348 : {
349 : bool bEnableField, bEnableItem;
350 0 : switch( mxLbTypeWrp->GetControlValue() )
351 : {
352 : case DataPilotFieldReferenceType::ITEM_DIFFERENCE:
353 : case DataPilotFieldReferenceType::ITEM_PERCENTAGE:
354 : case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
355 0 : bEnableField = bEnableItem = true;
356 0 : break;
357 :
358 : case DataPilotFieldReferenceType::RUNNING_TOTAL:
359 0 : bEnableField = true;
360 0 : bEnableItem = false;
361 0 : break;
362 :
363 : default:
364 0 : bEnableField = bEnableItem = false;
365 : }
366 :
367 0 : bEnableField &= mpLbBaseField->GetEntryCount() > 0;
368 0 : mpFtBaseField->Enable( bEnableField );
369 0 : mpLbBaseField->Enable( bEnableField );
370 :
371 0 : bEnableItem &= bEnableField;
372 0 : mpFtBaseItem->Enable( bEnableItem );
373 0 : mpLbBaseItem->Enable( bEnableItem );
374 : }
375 0 : else if( pLBox == mpLbBaseField )
376 : {
377 : // keep "previous" and "next" entries
378 0 : while( mpLbBaseItem->GetEntryCount() > SC_BASEITEM_USER_POS )
379 0 : mpLbBaseItem->RemoveEntry( SC_BASEITEM_USER_POS );
380 :
381 : // update item list for current base field
382 0 : mbEmptyItem = false;
383 0 : size_t nBasePos = mpLbBaseField->GetSelectEntryPos();
384 0 : if( nBasePos < mrLabelVec.size() )
385 : {
386 0 : const vector<ScDPLabelData::Member>& rMembers = mrLabelVec[nBasePos].maMembers;
387 0 : mbEmptyItem = lclFillListBox(*mpLbBaseItem, rMembers, SC_BASEITEM_USER_POS);
388 : // build cache for base names.
389 0 : NameMapType aMap;
390 0 : vector<ScDPLabelData::Member>::const_iterator itr = rMembers.begin(), itrEnd = rMembers.end();
391 0 : for (; itr != itrEnd; ++itr)
392 0 : aMap.insert(NameMapType::value_type(itr->getDisplayName(), itr->maName));
393 0 : maBaseItemNameMap.swap(aMap);
394 : }
395 :
396 : // select base item
397 0 : sal_uInt16 nItemPos = (mpLbBaseItem->GetEntryCount() > SC_BASEITEM_USER_POS) ? SC_BASEITEM_USER_POS : SC_BASEITEM_PREV_POS;
398 0 : mpLbBaseItem->SelectEntryPos( nItemPos );
399 : }
400 0 : return 0;
401 : }
402 :
403 0 : IMPL_LINK_NOARG(ScDPFunctionDlg, DblClickHdl)
404 : {
405 0 : mpBtnOk->Click();
406 0 : return 0;
407 : }
408 :
409 0 : ScDPSubtotalDlg::ScDPSubtotalDlg( vcl::Window* pParent, ScDPObject& rDPObj,
410 : const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData,
411 : const ScDPNameVec& rDataFields, bool bEnableLayout )
412 : : ModalDialog(pParent, "PivotFieldDialog",
413 : "modules/scalc/ui/pivotfielddialog.ui")
414 : , mrDPObj(rDPObj)
415 : , mrDataFields(rDataFields)
416 : , maLabelData(rLabelData)
417 0 : , mbEnableLayout(bEnableLayout)
418 : {
419 0 : get(mpBtnOk, "ok");
420 0 : get(mpBtnOptions, "options");
421 0 : get(mpCbShowAll, "showall");
422 0 : get(mpFtName, "name");
423 0 : get(mpLbFunc, "functions");
424 0 : mpLbFunc->EnableMultiSelection(true);
425 0 : mpLbFunc->set_height_request(mpLbFunc->GetTextHeight() * 8);
426 0 : get(mpRbNone, "none");
427 0 : get(mpRbAuto, "auto");
428 0 : get(mpRbUser, "user");
429 :
430 0 : Init( rLabelData, rFuncData );
431 0 : }
432 :
433 0 : sal_uInt16 ScDPSubtotalDlg::GetFuncMask() const
434 : {
435 0 : sal_uInt16 nFuncMask = PIVOT_FUNC_NONE;
436 :
437 0 : if( mpRbAuto->IsChecked() )
438 0 : nFuncMask = PIVOT_FUNC_AUTO;
439 0 : else if( mpRbUser->IsChecked() )
440 0 : nFuncMask = mpLbFunc->GetSelection();
441 :
442 0 : return nFuncMask;
443 : }
444 :
445 0 : void ScDPSubtotalDlg::FillLabelData( ScDPLabelData& rLabelData ) const
446 : {
447 0 : rLabelData.mnFuncMask = GetFuncMask();
448 0 : rLabelData.mnUsedHier = maLabelData.mnUsedHier;
449 0 : rLabelData.mbShowAll = mpCbShowAll->IsChecked();
450 0 : rLabelData.maMembers = maLabelData.maMembers;
451 0 : rLabelData.maSortInfo = maLabelData.maSortInfo;
452 0 : rLabelData.maLayoutInfo = maLabelData.maLayoutInfo;
453 0 : rLabelData.maShowInfo = maLabelData.maShowInfo;
454 0 : }
455 :
456 0 : void ScDPSubtotalDlg::Init( const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData )
457 : {
458 : // field name
459 0 : mpFtName->SetText(rLabelData.getDisplayName());
460 :
461 : // radio buttons
462 0 : mpRbNone->SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
463 0 : mpRbAuto->SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
464 0 : mpRbUser->SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
465 :
466 0 : RadioButton* pRBtn = 0;
467 0 : switch( rFuncData.mnFuncMask )
468 : {
469 0 : case PIVOT_FUNC_NONE: pRBtn = mpRbNone; break;
470 0 : case PIVOT_FUNC_AUTO: pRBtn = mpRbAuto; break;
471 0 : default: pRBtn = mpRbUser;
472 : }
473 0 : pRBtn->Check();
474 0 : RadioClickHdl( pRBtn );
475 :
476 : // list box
477 0 : mpLbFunc->SetSelection( rFuncData.mnFuncMask );
478 0 : mpLbFunc->SetDoubleClickHdl( LINK( this, ScDPSubtotalDlg, DblClickHdl ) );
479 :
480 : // show all
481 0 : mpCbShowAll->Check( rLabelData.mbShowAll );
482 :
483 : // options
484 0 : mpBtnOptions->SetClickHdl( LINK( this, ScDPSubtotalDlg, ClickHdl ) );
485 0 : }
486 :
487 0 : IMPL_LINK( ScDPSubtotalDlg, RadioClickHdl, RadioButton*, pBtn )
488 : {
489 0 : mpLbFunc->Enable( pBtn == mpRbUser );
490 0 : return 0;
491 : }
492 :
493 0 : IMPL_LINK_NOARG(ScDPSubtotalDlg, DblClickHdl)
494 : {
495 0 : mpBtnOk->Click();
496 0 : return 0;
497 : }
498 :
499 0 : IMPL_LINK( ScDPSubtotalDlg, ClickHdl, PushButton*, pBtn )
500 : {
501 0 : if (pBtn == mpBtnOptions)
502 : {
503 0 : boost::scoped_ptr<ScDPSubtotalOptDlg> pDlg(new ScDPSubtotalOptDlg( this, mrDPObj, maLabelData, mrDataFields, mbEnableLayout ));
504 0 : if( pDlg->Execute() == RET_OK )
505 0 : pDlg->FillLabelData( maLabelData );
506 : }
507 0 : return 0;
508 : }
509 :
510 0 : ScDPSubtotalOptDlg::ScDPSubtotalOptDlg( vcl::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( vcl::Window* pParent, ScDPObject& rDPObj, sal_uInt16 nOrient ) :
761 : ModalDialog ( pParent, "ShowDetail", "modules/scalc/ui/showdetaildialog.ui" ),
762 0 : mrDPObj(rDPObj)
763 : {
764 0 : get(mpLbDims, "dimsTreeview");
765 0 : get(mpBtnOk, "ok");
766 :
767 0 : ScDPSaveData* pSaveData = rDPObj.GetSaveData();
768 0 : long nDimCount = rDPObj.GetDimCount();
769 0 : for (long nDim=0; nDim<nDimCount; nDim++)
770 : {
771 : bool bIsDataLayout;
772 0 : sal_Int32 nDimFlags = 0;
773 0 : OUString aName = rDPObj.GetDimName( nDim, bIsDataLayout, &nDimFlags );
774 0 : if ( !bIsDataLayout && !rDPObj.IsDuplicated( nDim ) && ScDPObject::IsOrientationAllowed( nOrient, nDimFlags ) )
775 : {
776 0 : const ScDPSaveDimension* pDimension = pSaveData ? pSaveData->GetExistingDimensionByName(aName) : 0;
777 0 : if ( !pDimension || (pDimension->GetOrientation() != nOrient) )
778 : {
779 0 : if (pDimension)
780 : {
781 0 : const OUString* pLayoutName = pDimension->GetLayoutName();
782 0 : if (pLayoutName)
783 0 : aName = *pLayoutName;
784 : }
785 0 : mpLbDims->InsertEntry( aName );
786 0 : maNameIndexMap.insert(DimNameIndexMap::value_type(aName, nDim));
787 : }
788 : }
789 0 : }
790 0 : if( mpLbDims->GetEntryCount() )
791 0 : mpLbDims->SelectEntryPos( 0 );
792 :
793 0 : mpLbDims->SetDoubleClickHdl( LINK( this, ScDPShowDetailDlg, DblClickHdl ) );
794 0 : }
795 :
796 0 : short ScDPShowDetailDlg::Execute()
797 : {
798 0 : return mpLbDims->GetEntryCount() ? ModalDialog::Execute() : static_cast<short>(RET_CANCEL);
799 : }
800 :
801 0 : OUString ScDPShowDetailDlg::GetDimensionName() const
802 : {
803 : // Look up the internal dimension name which may be different from the
804 : // displayed field name.
805 0 : OUString aSelectedName = mpLbDims->GetSelectEntry();
806 0 : DimNameIndexMap::const_iterator itr = maNameIndexMap.find(aSelectedName);
807 0 : if (itr == maNameIndexMap.end())
808 : // This should never happen!
809 0 : return aSelectedName;
810 :
811 0 : long nDim = itr->second;
812 0 : bool bIsDataLayout = false;
813 0 : return mrDPObj.GetDimName(nDim, bIsDataLayout);
814 : }
815 :
816 0 : IMPL_LINK( ScDPShowDetailDlg, DblClickHdl, ListBox*, pLBox )
817 : {
818 0 : if( pLBox == mpLbDims )
819 0 : mpBtnOk->Click();
820 0 : return 0;
821 0 : }
822 :
823 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|