Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*************************************************************************
3 : *
4 : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : *
6 : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : *
8 : * OpenOffice.org - a multi-platform office productivity suite
9 : *
10 : * This file is part of OpenOffice.org.
11 : *
12 : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : * it under the terms of the GNU Lesser General Public License version 3
14 : * only, as published by the Free Software Foundation.
15 : *
16 : * OpenOffice.org is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : * GNU Lesser General Public License version 3 for more details
20 : * (a copy is included in the LICENSE file that accompanied this code).
21 : *
22 : * You should have received a copy of the GNU Lesser General Public License
23 : * version 3 along with OpenOffice.org. If not, see
24 : * <http://www.openoffice.org/license.html>
25 : * for a copy of the LGPLv3 License.
26 : *
27 : * This file incorporates work covered by the following license notice:
28 : *
29 : * Licensed to the Apache Software Foundation (ASF) under one or more
30 : * contributor license agreements. See the NOTICE file distributed
31 : * with this work for additional information regarding copyright
32 : * ownership. The ASF licenses this file to you under the Apache
33 : * License, Version 2.0 (the "License"); you may not use this file
34 : * except in compliance with the License. You may obtain a copy of
35 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
36 : ************************************************************************/
37 :
38 : #include <config_lgpl.h>
39 :
40 : #include "fieldwnd.hxx"
41 :
42 : #include <comphelper/string.hxx>
43 : #include <vcl/decoview.hxx>
44 : #include <vcl/help.hxx>
45 : #include <vcl/svapp.hxx>
46 : #include <vcl/virdev.hxx>
47 : #include <vcl/mnemonic.hxx>
48 :
49 : #include "pvlaydlg.hxx"
50 : #include "dpuiglobal.hxx"
51 : #include "calcmacros.hxx"
52 : #include "AccessibleDataPilotControl.hxx"
53 : #include "scresid.hxx"
54 : #include "pivot.hrc"
55 :
56 : using namespace com::sun::star;
57 : using ::std::vector;
58 : using ::com::sun::star::uno::Reference;
59 : using ::com::sun::star::uno::WeakReference;
60 : using ::com::sun::star::accessibility::XAccessible;
61 :
62 : const size_t PIVOTFIELD_INVALID = static_cast< size_t >(-1);
63 : const size_t INVALID_INDEX = static_cast<size_t>(-1);
64 :
65 : #if DEBUG_PIVOT_TABLE
66 : using std::cout;
67 : using std::endl;
68 : #endif
69 :
70 : namespace {
71 :
72 : #if DEBUG_PIVOT_TABLE
73 : void DumpAllFuncData(const ScDPFieldControlBase::FuncDataType& rData)
74 : {
75 : cout << "---" << endl;
76 : ScDPFieldControlBase::FuncDataType::const_iterator it = rData.begin(), itEnd = rData.end();
77 : for (; it != itEnd; ++it)
78 : it->Dump();
79 : }
80 : #endif
81 :
82 : }
83 :
84 0 : ScDPFieldControlBase::FieldName::FieldName(const OUString& rText, bool bFits, sal_uInt8 nDupCount) :
85 0 : maText(rText), mbFits(bFits), mnDupCount(nDupCount) {}
86 :
87 0 : ScDPFieldControlBase::FieldName::FieldName(const FieldName& r) :
88 0 : maText(r.maText), mbFits(r.mbFits), mnDupCount(r.mnDupCount) {}
89 :
90 0 : OUString ScDPFieldControlBase::FieldName::getDisplayedText() const
91 : {
92 0 : OUStringBuffer aBuf(maText);
93 0 : if (mnDupCount > 0)
94 0 : aBuf.append(static_cast<sal_Int32>(mnDupCount+1));
95 0 : return aBuf.makeStringAndClear();
96 : }
97 :
98 0 : ScDPFieldControlBase::ScrollBar::ScrollBar(Window* pParent, WinBits nStyle) :
99 : ::ScrollBar(pParent, nStyle),
100 0 : mpParent(pParent)
101 : {
102 0 : }
103 :
104 0 : void ScDPFieldControlBase::ScrollBar::Command( const CommandEvent& rCEvt )
105 : {
106 0 : mpParent->Command(rCEvt);
107 0 : }
108 :
109 0 : ScDPFieldControlBase::AccessRef::AccessRef( const com::sun::star::uno::WeakReference< ::com::sun::star::accessibility::XAccessible > & rAccessible ) : mxRef( rAccessible ) {}
110 :
111 : // easy, safe access to the backing accessible for the lifetime of AccessRef
112 0 : ScAccessibleDataPilotControl *ScDPFieldControlBase::AccessRef::operator -> () const
113 : {
114 0 : if (!mxRef.is())
115 0 : return NULL;
116 0 : return static_cast< ScAccessibleDataPilotControl * >( mxRef.get() );
117 : }
118 :
119 0 : ScDPFieldControlBase::ScDPFieldControlBase(
120 : ScPivotLayoutDlg* pParent, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
121 : Control(pParent, rResId),
122 : mpDlg(pParent),
123 : mpCaption(pCaption),
124 0 : mnFieldSelected(0)
125 : {
126 0 : SetHelpId( pcHelpId );
127 :
128 0 : if (pCaption)
129 0 : maName = MnemonicGenerator::EraseAllMnemonicChars( pCaption->GetText() );
130 0 : }
131 :
132 0 : ScDPFieldControlBase::~ScDPFieldControlBase()
133 : {
134 0 : AccessRef aRef( mxAccessible );
135 0 : if( aRef.is() )
136 0 : aRef->dispose();
137 0 : }
138 :
139 0 : OUString ScDPFieldControlBase::GetName() const
140 : {
141 0 : return maName;
142 : }
143 :
144 0 : void ScDPFieldControlBase::SetName(const OUString& rName)
145 : {
146 0 : maName = rName;
147 0 : }
148 :
149 0 : bool ScDPFieldControlBase::IsExistingIndex( size_t nIndex ) const
150 : {
151 0 : return nIndex < maFieldNames.size();
152 : }
153 :
154 0 : void ScDPFieldControlBase::AppendField( const OUString& rText, const ScPivotFuncData& rFunc )
155 : {
156 0 : size_t nNewIndex = maFieldNames.size();
157 :
158 0 : sal_uInt8 nDupCount = GetNextDupCount(rText);
159 0 : maFieldNames.push_back(FieldName(rText, true, nDupCount));
160 0 : maFuncData.push_back(new ScPivotFuncData(rFunc));
161 :
162 0 : AccessRef xRef(mxAccessible);
163 0 : if ( xRef.is() )
164 0 : xRef->AddField(nNewIndex);
165 0 : }
166 :
167 0 : size_t ScDPFieldControlBase::AddField(
168 : const OUString& rText, const Point& rPos, const ScPivotFuncData& rFunc)
169 : {
170 0 : size_t nNewIndex = GetFieldIndex(rPos);
171 0 : if (nNewIndex == PIVOTFIELD_INVALID)
172 0 : return PIVOTFIELD_INVALID;
173 :
174 0 : if (nNewIndex > maFieldNames.size())
175 0 : nNewIndex = maFieldNames.size();
176 :
177 0 : sal_uInt8 nDupCount = GetNextDupCount(rText);
178 0 : maFieldNames.insert(maFieldNames.begin() + nNewIndex, FieldName(rText, true, nDupCount));
179 :
180 0 : maFuncData.insert(maFuncData.begin() + nNewIndex, new ScPivotFuncData(rFunc));
181 0 : maFuncData.back().mnDupCount = nDupCount;
182 :
183 0 : mnFieldSelected = nNewIndex;
184 0 : ResetScrollBar();
185 0 : Invalidate();
186 :
187 0 : AccessRef xRef( mxAccessible );
188 0 : if ( xRef.is() )
189 0 : xRef->AddField(nNewIndex);
190 :
191 0 : return nNewIndex;
192 : }
193 :
194 0 : bool ScDPFieldControlBase::MoveField(size_t nCurPos, const Point& rPos, size_t& rnIndex)
195 : {
196 0 : if (nCurPos >= maFieldNames.size())
197 : // out-of-bound
198 0 : return false;
199 :
200 0 : size_t nNewIndex = GetFieldIndex(rPos);
201 0 : if (nNewIndex == PIVOTFIELD_INVALID)
202 0 : return false;
203 :
204 0 : if (nNewIndex == nCurPos)
205 : // Nothing to do.
206 0 : return true;
207 :
208 0 : FieldName aName = maFieldNames[nCurPos];
209 0 : ScPivotFuncData aFunc = maFuncData[nCurPos];
210 0 : if (nNewIndex >= maFieldNames.size())
211 : {
212 : // Move to the back.
213 0 : maFieldNames.erase(maFieldNames.begin()+nCurPos);
214 0 : maFieldNames.push_back(aName);
215 0 : maFuncData.erase(maFuncData.begin()+nCurPos);
216 0 : maFuncData.push_back(new ScPivotFuncData(aFunc));
217 0 : rnIndex = maFieldNames.size()-1;
218 : }
219 : else
220 : {
221 0 : maFieldNames.erase(maFieldNames.begin()+nCurPos);
222 0 : maFuncData.erase(maFuncData.begin()+nCurPos);
223 0 : size_t nTmp = nNewIndex; // we need to keep the original index for accessible.
224 0 : if (nNewIndex > nCurPos)
225 0 : --nTmp;
226 :
227 0 : maFieldNames.insert(maFieldNames.begin()+nTmp, aName);
228 0 : maFuncData.insert(maFuncData.begin()+nTmp, new ScPivotFuncData(aFunc));
229 0 : rnIndex = nTmp;
230 : }
231 :
232 0 : ResetScrollBar();
233 0 : Invalidate();
234 :
235 0 : AccessRef xRef( mxAccessible );
236 0 : if ( xRef.is() )
237 0 : xRef->MoveField(nCurPos, nNewIndex);
238 :
239 0 : return true;
240 : }
241 :
242 0 : void ScDPFieldControlBase::DeleteFieldByIndex( size_t nIndex )
243 : {
244 0 : if (!IsExistingIndex(nIndex))
245 : // Nothing to delete.
246 0 : return;
247 :
248 0 : AccessRef xRef(mxAccessible);
249 0 : if (xRef.is())
250 0 : xRef->RemoveField(nIndex);
251 :
252 :
253 0 : maFieldNames.erase(maFieldNames.begin() + nIndex);
254 0 : if (mnFieldSelected >= maFieldNames.size())
255 0 : mnFieldSelected = maFieldNames.size() - 1;
256 :
257 0 : maFuncData.erase(maFuncData.begin() + nIndex);
258 :
259 0 : ResetScrollBar();
260 0 : Invalidate();
261 : }
262 :
263 0 : size_t ScDPFieldControlBase::GetFieldCount() const
264 : {
265 0 : return maFieldNames.size();
266 : }
267 :
268 0 : bool ScDPFieldControlBase::IsEmpty() const
269 : {
270 0 : return maFieldNames.empty();
271 : }
272 :
273 0 : void ScDPFieldControlBase::ClearFields()
274 : {
275 0 : AccessRef xRef( mxAccessible );
276 0 : if ( xRef.is() )
277 0 : for( size_t nIdx = maFieldNames.size(); nIdx > 0; --nIdx )
278 0 : xRef->RemoveField( nIdx - 1 );
279 :
280 0 : maFieldNames.clear();
281 0 : maFuncData.clear();
282 0 : }
283 :
284 0 : void ScDPFieldControlBase::SetFieldText(const OUString& rText, size_t nIndex, sal_uInt8 nDupCount)
285 : {
286 0 : if( IsExistingIndex( nIndex ) )
287 : {
288 0 : maFieldNames[nIndex] = FieldName(rText, true, nDupCount);
289 0 : Invalidate();
290 :
291 0 : AccessRef xRef( mxAccessible );
292 0 : if ( xRef.is() )
293 0 : xRef->FieldNameChange(nIndex);
294 : }
295 0 : }
296 :
297 0 : OUString ScDPFieldControlBase::GetFieldText( size_t nIndex ) const
298 : {
299 0 : if( IsExistingIndex( nIndex ) )
300 0 : return maFieldNames[nIndex].maText;
301 0 : return OUString();
302 : }
303 :
304 0 : void ScDPFieldControlBase::GetExistingIndex( const Point& rPos, size_t& rnIndex )
305 : {
306 0 : if (maFieldNames.empty() || GetFieldType() == PIVOTFIELDTYPE_SELECT)
307 : {
308 0 : rnIndex = 0;
309 0 : return;
310 : }
311 :
312 0 : rnIndex = GetFieldIndex(rPos);
313 0 : if (rnIndex == PIVOTFIELD_INVALID)
314 0 : rnIndex = 0;
315 : }
316 :
317 0 : size_t ScDPFieldControlBase::GetSelectedField() const
318 : {
319 0 : return mnFieldSelected;
320 : }
321 :
322 0 : vector<ScDPFieldControlBase::FieldName>& ScDPFieldControlBase::GetFieldNames()
323 : {
324 0 : return maFieldNames;
325 : }
326 :
327 0 : const vector<ScDPFieldControlBase::FieldName>& ScDPFieldControlBase::GetFieldNames() const
328 : {
329 0 : return maFieldNames;
330 : }
331 :
332 0 : void ScDPFieldControlBase::Paint( const Rectangle& /* rRect */ )
333 : {
334 : // hiding the caption is now done from StateChanged
335 0 : Redraw();
336 0 : }
337 :
338 0 : void ScDPFieldControlBase::StateChanged( StateChangedType nStateChange )
339 : {
340 0 : Control::StateChanged( nStateChange );
341 :
342 0 : if( nStateChange == STATE_CHANGE_INITSHOW )
343 : {
344 : /* After the fixed text associated to this control has received its
345 : unique mnemonic from VCL dialog initialization code, put this text
346 : into the field windows.
347 : #124828# Hiding the FixedTexts and clearing the tab stop style bits
348 : has to be done after assigning the mnemonics, but Paint() is too
349 : late, because the test tool may send key events to the dialog when
350 : it isn't visible. Mnemonics are assigned in Dialog::StateChanged()
351 : for STATE_CHANGE_INITSHOW, so this can be done immediately
352 : afterwards. */
353 :
354 0 : if ( mpCaption )
355 : {
356 0 : SetText( mpCaption->GetText() );
357 0 : mpCaption->Hide();
358 : }
359 : }
360 0 : }
361 :
362 0 : void ScDPFieldControlBase::DataChanged( const DataChangedEvent& rDCEvt )
363 : {
364 0 : Control::DataChanged( rDCEvt );
365 0 : if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
366 0 : Invalidate();
367 0 : }
368 :
369 0 : void ScDPFieldControlBase::Command( const CommandEvent& rCEvt )
370 : {
371 0 : if (rCEvt.GetCommand() == COMMAND_WHEEL)
372 : {
373 0 : const CommandWheelData* pData = rCEvt.GetWheelData();
374 0 : if (pData->GetMode() == COMMAND_WHEEL_SCROLL && !pData->IsHorz())
375 : {
376 : // Handle vertical mouse wheel scrolls.
377 0 : long nNotch = pData->GetNotchDelta(); // positive => up; negative => down
378 0 : HandleWheelScroll(nNotch);
379 : }
380 : }
381 0 : }
382 :
383 0 : void ScDPFieldControlBase::MouseButtonDown( const MouseEvent& rMEvt )
384 : {
385 0 : if( rMEvt.IsLeft() )
386 : {
387 0 : size_t nNewSelectIndex = GetFieldIndex( rMEvt.GetPosPixel() );
388 0 : if (nNewSelectIndex != PIVOTFIELD_INVALID && IsExistingIndex(nNewSelectIndex))
389 : {
390 : // grabbing after GetFieldIndex() will prevent to focus empty window
391 0 : GrabFocusAndSelect( nNewSelectIndex );
392 :
393 0 : if( rMEvt.GetClicks() == 1 )
394 : {
395 0 : PointerStyle ePtr = mpDlg->NotifyMouseButtonDown( GetFieldType(), nNewSelectIndex );
396 0 : CaptureMouse();
397 0 : SetPointer( Pointer( ePtr ) );
398 : }
399 : else
400 0 : mpDlg->NotifyDoubleClick( GetFieldType(), nNewSelectIndex );
401 : }
402 : }
403 0 : }
404 :
405 0 : void ScDPFieldControlBase::MouseButtonUp( const MouseEvent& rMEvt )
406 : {
407 0 : if( rMEvt.IsLeft() )
408 : {
409 0 : if( rMEvt.GetClicks() == 1 )
410 : {
411 0 : Point aScrPos = OutputToScreenPixel(rMEvt.GetPosPixel());
412 0 : ScPivotFieldType eToType = mpDlg->GetFieldTypeAtPoint(aScrPos);
413 :
414 0 : mpDlg->DropFieldItem(aScrPos, eToType);
415 0 : SetPointer( Pointer( POINTER_ARROW ) );
416 : }
417 :
418 0 : if( IsMouseCaptured() )
419 0 : ReleaseMouse();
420 : }
421 0 : }
422 :
423 0 : void ScDPFieldControlBase::MouseMove( const MouseEvent& rMEvt )
424 : {
425 0 : if( IsMouseCaptured() )
426 : {
427 0 : Point aScrPos = OutputToScreenPixel(rMEvt.GetPosPixel());
428 0 : ScPivotFieldType eFieldType = mpDlg->GetFieldTypeAtPoint(aScrPos);
429 0 : PointerStyle ePtr = mpDlg->GetPointerStyleAtPoint(aScrPos, eFieldType);
430 0 : SetPointer( Pointer( ePtr ) );
431 : }
432 0 : const FieldNames& rFields = GetFieldNames();
433 0 : size_t nIndex = GetFieldIndex(rMEvt.GetPosPixel());
434 : // does the string not fit on the screen ? show a helpful helptext instead
435 0 : if (nIndex != PIVOTFIELD_INVALID && (nIndex < rFields.size()) && !rFields[nIndex].mbFits)
436 : {
437 0 : Point aPos = OutputToScreenPixel( rMEvt.GetPosPixel() );
438 0 : Rectangle aRect( aPos, GetSizePixel() );
439 0 : String aHelpText = GetFieldText(nIndex);
440 0 : Help::ShowQuickHelp( this, aRect, aHelpText );
441 : }
442 0 : }
443 :
444 0 : void ScDPFieldControlBase::KeyInput( const KeyEvent& rKEvt )
445 : {
446 0 : const KeyCode& rKeyCode = rKEvt.GetKeyCode();
447 0 : sal_uInt16 nCode = rKeyCode.GetCode();
448 :
449 :
450 0 : const FieldNames& rFields = GetFieldNames();
451 0 : bool bFieldMove = ( rKeyCode.IsMod1() && (GetFieldType() != PIVOTFIELDTYPE_SELECT) );
452 0 : bool bKeyEvaluated = true;
453 : void (ScDPFieldControlBase::*pMoveXY) (SCsCOL nDX, SCsROW nDY);
454 0 : if (bFieldMove)
455 0 : pMoveXY = &ScDPFieldControlBase::MoveFieldRel;
456 : else
457 0 : pMoveXY = &ScDPFieldControlBase::MoveSelection;
458 0 : switch( nCode )
459 : {
460 0 : case KEY_UP: (this->*pMoveXY)( 0, -1 ); break;
461 0 : case KEY_DOWN: (this->*pMoveXY)( 0, 1 ); break;
462 0 : case KEY_LEFT: (this->*pMoveXY)( -1, 0 ); break;
463 0 : case KEY_RIGHT: (this->*pMoveXY)( 1, 0 ); break;
464 : case KEY_HOME:
465 0 : if (bFieldMove)
466 0 : MoveField( 0 );
467 : else
468 : {
469 0 : if( !rFields.empty() )
470 0 : MoveSelection( 0 );
471 : }
472 0 : break;
473 : case KEY_END:
474 0 : if (bFieldMove)
475 0 : MoveField( rFields.size() - 1 );
476 : else
477 : {
478 0 : if( !rFields.empty() )
479 0 : MoveSelection( rFields.size() - 1 );
480 : }
481 0 : break;
482 : default:
483 0 : if ( !bFieldMove && nCode == KEY_DELETE )
484 0 : mpDlg->NotifyRemoveField( GetFieldType(), mnFieldSelected );
485 : else
486 0 : bKeyEvaluated = false;
487 0 : break;
488 : }
489 :
490 0 : if (bKeyEvaluated)
491 : {
492 0 : ScrollToShowSelection();
493 0 : Invalidate();
494 : }
495 : else
496 0 : Control::KeyInput( rKEvt );
497 0 : }
498 :
499 0 : void ScDPFieldControlBase::GetFocus()
500 : {
501 0 : Control::GetFocus();
502 0 : Invalidate();
503 0 : if( GetGetFocusFlags() & GETFOCUS_MNEMONIC )
504 : {
505 0 : size_t nOldCount = GetFieldCount();
506 0 : mpDlg->NotifyMoveFieldToEnd( GetFieldType() );
507 0 : if (GetFieldCount() > nOldCount)
508 : // Scroll to the end only when a new field is inserted.
509 0 : ScrollToEnd();
510 : }
511 : else // notify change focus
512 0 : mpDlg->NotifyFieldFocus( GetFieldType(), true );
513 :
514 0 : AccessRef xRef( mxAccessible );
515 0 : if( xRef.is() )
516 0 : xRef->GotFocus();
517 0 : }
518 :
519 0 : void ScDPFieldControlBase::LoseFocus()
520 : {
521 0 : Control::LoseFocus();
522 0 : Invalidate();
523 0 : mpDlg->NotifyFieldFocus( GetFieldType(), false );
524 :
525 0 : AccessRef xRef( mxAccessible );
526 0 : if( xRef.is() )
527 0 : xRef->LostFocus();
528 0 : }
529 :
530 0 : Reference<XAccessible> ScDPFieldControlBase::CreateAccessible()
531 : {
532 0 : com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible > xReturn(new ScAccessibleDataPilotControl(GetAccessibleParentWindow()->GetAccessible(), this));
533 :
534 0 : mxAccessible = xReturn;
535 0 : AccessRef xRef( mxAccessible );
536 0 : xRef->Init();
537 :
538 0 : return xReturn;
539 : }
540 :
541 0 : void ScDPFieldControlBase::FieldFocusChanged(size_t nOldSelected, size_t nFieldSelected)
542 : {
543 0 : AccessRef xRef( mxAccessible );
544 0 : if ( xRef.is() )
545 0 : xRef->FieldFocusChange(nOldSelected, nFieldSelected);
546 0 : }
547 :
548 0 : void ScDPFieldControlBase::UpdateStyle()
549 : {
550 0 : WinBits nMask = ~(WB_TABSTOP | WB_NOTABSTOP);
551 0 : SetStyle( (GetStyle() & nMask) | (IsEmpty() ? WB_NOTABSTOP : WB_TABSTOP) );
552 0 : }
553 :
554 0 : void ScDPFieldControlBase::DrawBackground( OutputDevice& rDev )
555 : {
556 0 : const StyleSettings& rStyleSet = GetSettings().GetStyleSettings();
557 0 : Color aFaceColor = rStyleSet.GetFaceColor();
558 0 : Color aWinColor = rStyleSet.GetWindowColor();
559 0 : Color aWinTextColor = rStyleSet.GetWindowTextColor();
560 :
561 0 : Point aPos0;
562 0 : Size aSize( GetSizePixel() );
563 :
564 0 : if (mpCaption)
565 : {
566 0 : rDev.SetLineColor( aWinTextColor );
567 0 : rDev.SetFillColor( aWinColor );
568 : }
569 : else
570 : {
571 0 : rDev.SetLineColor( aFaceColor );
572 0 : rDev.SetFillColor( aFaceColor );
573 : }
574 0 : rDev.DrawRect( Rectangle( aPos0, aSize ) );
575 :
576 0 : rDev.SetTextColor( aWinTextColor );
577 :
578 : /* Draw the caption text. This needs some special handling, because we
579 : support hard line breaks here. This part will draw each line of the
580 : text for itself. */
581 :
582 0 : xub_StrLen nTokenCnt = comphelper::string::getTokenCount(GetText(), '\n');
583 0 : long nY = (aSize.Height() - nTokenCnt * rDev.GetTextHeight()) / 2;
584 0 : sal_Int32 nStringIx = 0;
585 0 : for( xub_StrLen nToken = 0; nToken < nTokenCnt; ++nToken )
586 : {
587 0 : String aLine( GetText().getToken( 0, '\n', nStringIx ) );
588 0 : Point aLinePos( (aSize.Width() - rDev.GetCtrlTextWidth( aLine )) / 2, nY );
589 0 : rDev.DrawCtrlText( aLinePos, aLine );
590 0 : nY += rDev.GetTextHeight();
591 0 : }
592 0 : }
593 :
594 0 : void ScDPFieldControlBase::DrawField(
595 : OutputDevice& rDev, const Rectangle& rRect, FieldName& rText, bool bFocus )
596 : {
597 0 : const StyleSettings& rStyleSet = GetSettings().GetStyleSettings();
598 0 : Color aTextColor = rStyleSet.GetButtonTextColor();
599 :
600 0 : VirtualDevice aVirDev( rDev );
601 : // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
602 0 : aVirDev.EnableRTL( IsRTLEnabled() );
603 :
604 0 : OUString aText = rText.getDisplayedText();
605 :
606 0 : Size aDevSize( rRect.GetSize() );
607 0 : long nWidth = aDevSize.Width();
608 0 : long nHeight = aDevSize.Height();
609 0 : long nLabelWidth = rDev.GetTextWidth( aText );
610 0 : long nLabelHeight = rDev.GetTextHeight();
611 :
612 : // #i31600# if text is too long, cut and add ellipsis
613 0 : rText.mbFits = nLabelWidth + 6 <= nWidth;
614 0 : if (!rText.mbFits)
615 : {
616 0 : sal_Int32 nMinLen = 0;
617 0 : sal_Int32 nMaxLen = aText.getLength();
618 0 : bool bFits = false;
619 0 : do
620 : {
621 0 : sal_Int32 nCurrLen = (nMinLen + nMaxLen) / 2;
622 0 : OUStringBuffer aBuf(rText.maText.copy(0, nCurrLen));
623 0 : aBuf.appendAscii("...");
624 0 : aText = aBuf.makeStringAndClear();
625 0 : nLabelWidth = rDev.GetTextWidth( aText );
626 0 : bFits = nLabelWidth + 6 <= nWidth;
627 0 : (bFits ? nMinLen : nMaxLen) = nCurrLen;
628 : }
629 0 : while( !bFits || (nMinLen + 1 < nMaxLen) );
630 : }
631 0 : Point aLabelPos( (nWidth - nLabelWidth) / 2, ::std::max< long >( (nHeight - nLabelHeight) / 2, 3 ) );
632 :
633 0 : aVirDev.SetOutputSizePixel( aDevSize );
634 0 : aVirDev.SetFont( rDev.GetFont() );
635 0 : DecorationView aDecoView( &aVirDev );
636 0 : aDecoView.DrawButton( Rectangle( Point( 0, 0 ), aDevSize ), bFocus ? BUTTON_DRAW_DEFAULT : 0 );
637 0 : aVirDev.SetTextColor( aTextColor );
638 0 : aVirDev.DrawText( aLabelPos, aText );
639 0 : rDev.DrawBitmap( rRect.TopLeft(), aVirDev.GetBitmap( Point( 0, 0 ), aDevSize ) );
640 0 : }
641 :
642 0 : void ScDPFieldControlBase::AppendPaintable(Window* p)
643 : {
644 0 : maPaintables.push_back(p);
645 0 : }
646 :
647 0 : void ScDPFieldControlBase::DrawPaintables()
648 : {
649 0 : Rectangle aRect(GetPosPixel(), GetSizePixel());
650 0 : Paintables::iterator itr = maPaintables.begin(), itrEnd = maPaintables.end();
651 0 : for (; itr != itrEnd; ++itr)
652 : {
653 0 : Window* p = *itr;
654 0 : if (!p->IsVisible())
655 0 : continue;
656 :
657 0 : p->Paint(aRect);
658 : }
659 0 : }
660 :
661 0 : void ScDPFieldControlBase::DrawInvertSelection()
662 : {
663 0 : if (!HasFocus())
664 0 : return;
665 :
666 0 : if (mnFieldSelected >= maFieldNames.size())
667 0 : return;
668 :
669 0 : size_t nPos = GetDisplayPosition(mnFieldSelected);
670 0 : if (nPos == INVALID_INDEX)
671 0 : return;
672 :
673 0 : Size aFldSize = GetFieldSize();
674 0 : long nFldWidth = aFldSize.Width();
675 : long nSelWidth = std::min<long>(
676 0 : GetTextWidth(maFieldNames[mnFieldSelected].getDisplayedText()) + 4, nFldWidth - 6);
677 :
678 0 : Point aPos = GetFieldPosition(nPos);
679 0 : aPos += Point((nFldWidth - nSelWidth) / 2, 3);
680 0 : Size aSize(nSelWidth, aFldSize.Height() - 6);
681 :
682 0 : Rectangle aSel(aPos, aSize);
683 0 : InvertTracking(aSel, SHOWTRACK_SMALL | SHOWTRACK_WINDOW);
684 : }
685 :
686 0 : Size ScDPFieldControlBase::GetStdFieldBtnSize() const
687 : {
688 0 : return mpDlg->GetStdFieldBtnSize();
689 : }
690 :
691 0 : void ScDPFieldControlBase::MoveField( size_t nDestIndex )
692 : {
693 0 : if (nDestIndex != mnFieldSelected)
694 : {
695 0 : std::swap(maFieldNames[nDestIndex], maFieldNames[mnFieldSelected]);
696 0 : std::swap(maFuncData[nDestIndex], maFuncData[mnFieldSelected]);
697 0 : mnFieldSelected = nDestIndex;
698 : }
699 0 : }
700 :
701 0 : void ScDPFieldControlBase::MoveFieldRel( SCsCOL nDX, SCsROW nDY )
702 : {
703 0 : MoveField( CalcNewFieldIndex( nDX, nDY ) );
704 0 : }
705 :
706 0 : void ScDPFieldControlBase::MoveSelection(size_t nIndex)
707 : {
708 0 : FieldNames& rFields = GetFieldNames();
709 0 : if (rFields.empty())
710 0 : return;
711 :
712 0 : if (nIndex >= rFields.size())
713 : // Prevent it from going out-of-bound.
714 0 : nIndex = rFields.size() - 1;
715 :
716 0 : if( mnFieldSelected != nIndex )
717 : {
718 0 : size_t nOldSelected = mnFieldSelected;
719 0 : mnFieldSelected = nIndex;
720 0 : Invalidate();
721 :
722 0 : if (HasFocus())
723 0 : FieldFocusChanged(nOldSelected, mnFieldSelected);
724 : }
725 :
726 0 : ScrollToShowSelection();
727 : }
728 :
729 0 : void ScDPFieldControlBase::MoveSelection(SCsCOL nDX, SCsROW nDY)
730 : {
731 0 : size_t nNewIndex = CalcNewFieldIndex( nDX, nDY );
732 0 : MoveSelection( nNewIndex );
733 0 : }
734 :
735 0 : sal_uInt8 ScDPFieldControlBase::GetNextDupCount(const OUString& rFieldText) const
736 : {
737 0 : sal_uInt8 nMax = 0;
738 0 : FieldNames::const_iterator it = maFieldNames.begin(), itEnd = maFieldNames.end();
739 0 : for (; it != itEnd; ++it)
740 : {
741 0 : if (it->maText != rFieldText)
742 0 : continue;
743 :
744 0 : sal_uInt8 nNextUp = it->mnDupCount + 1;
745 0 : if (nMax < nNextUp)
746 0 : nMax = nNextUp;
747 : }
748 0 : return nMax;
749 : }
750 :
751 0 : sal_uInt8 ScDPFieldControlBase::GetNextDupCount(const ScPivotFuncData& rData, size_t nSelfIndex) const
752 : {
753 0 : sal_uInt8 nDupCount = 0;
754 0 : bool bFound = false;
755 0 : for (size_t i = 0, n = maFuncData.size(); i < n; ++i)
756 : {
757 0 : if (i == nSelfIndex)
758 : // Skip itself.
759 0 : continue;
760 :
761 0 : const ScPivotFuncData& r = maFuncData[i];
762 :
763 0 : if (r.mnCol != rData.mnCol || r.mnFuncMask != rData.mnFuncMask)
764 0 : continue;
765 :
766 0 : bFound = true;
767 0 : if (r.mnDupCount > nDupCount)
768 0 : nDupCount = r.mnDupCount;
769 : }
770 :
771 0 : return bFound ? nDupCount + 1 : 0;
772 : }
773 :
774 0 : void ScDPFieldControlBase::SelectNext()
775 : {
776 0 : MoveSelection(mnFieldSelected + 1);
777 0 : }
778 :
779 0 : void ScDPFieldControlBase::GrabFocusAndSelect( size_t nIndex )
780 : {
781 0 : MoveSelection( nIndex );
782 0 : if( !HasFocus() )
783 0 : GrabFocus();
784 0 : }
785 :
786 0 : const ScPivotFuncData& ScDPFieldControlBase::GetFuncData(size_t nIndex) const
787 : {
788 0 : return maFuncData.at(nIndex);
789 : }
790 :
791 0 : ScPivotFuncData& ScDPFieldControlBase::GetFuncData(size_t nIndex)
792 : {
793 0 : return maFuncData.at(nIndex);
794 : }
795 :
796 : namespace {
797 :
798 : class PushFuncItem : std::unary_function<ScPivotFuncData, void>
799 : {
800 : std::vector<ScDPFieldControlBase::FuncItem>& mrItems;
801 : public:
802 0 : PushFuncItem(std::vector<ScDPFieldControlBase::FuncItem>& rItems) : mrItems(rItems) {}
803 :
804 0 : void operator() (const ScPivotFuncData& r)
805 : {
806 : ScDPFieldControlBase::FuncItem aItem;
807 0 : aItem.mnCol = r.mnCol;
808 0 : aItem.mnFuncMask = r.mnFuncMask;
809 0 : mrItems.push_back(aItem);
810 0 : }
811 : };
812 :
813 : }
814 :
815 0 : void ScDPFieldControlBase::GetAllFuncItems(std::vector<FuncItem>& rItems) const
816 : {
817 0 : std::for_each(maFuncData.begin(), maFuncData.end(), PushFuncItem(rItems));
818 0 : }
819 :
820 : namespace {
821 :
822 : class PivotFieldInserter : public ::std::unary_function<ScPivotFuncData, void>
823 : {
824 : vector<ScPivotField>& mrFields;
825 : public:
826 0 : explicit PivotFieldInserter(vector<ScPivotField>& r, size_t nSize) : mrFields(r)
827 : {
828 0 : mrFields.reserve(nSize);
829 0 : }
830 :
831 0 : PivotFieldInserter(const PivotFieldInserter& r) : mrFields(r.mrFields) {}
832 :
833 0 : void operator() (const ScPivotFuncData& r)
834 : {
835 0 : ScPivotField aField;
836 0 : aField.nCol = r.mnCol;
837 0 : aField.mnOriginalDim = r.mnOriginalDim;
838 0 : aField.mnDupCount = r.mnDupCount;
839 0 : aField.nFuncMask = r.mnFuncMask;
840 0 : aField.maFieldRef = r.maFieldRef;
841 0 : mrFields.push_back(aField);
842 0 : }
843 : };
844 :
845 : }
846 :
847 0 : void ScDPFieldControlBase::ConvertToPivotArray(std::vector<ScPivotField>& rArray) const
848 : {
849 0 : for_each(maFuncData.begin(), maFuncData.end(), PivotFieldInserter(rArray, maFuncData.size()));
850 0 : }
851 :
852 : namespace {
853 :
854 : class EqualByDimOnly : std::unary_function<ScPivotFuncData, bool>
855 : {
856 : const ScPivotFuncData& mrData;
857 : long mnDim;
858 :
859 : public:
860 0 : EqualByDimOnly(const ScPivotFuncData& rData) : mrData(rData)
861 : {
862 0 : mnDim = rData.mnCol;
863 0 : if (rData.mnOriginalDim >= 0)
864 0 : mnDim = rData.mnOriginalDim;
865 0 : }
866 0 : bool operator() (const ScPivotFuncData& rData) const
867 : {
868 0 : long nDim = rData.mnCol;
869 0 : if (rData.mnOriginalDim >= 0)
870 0 : nDim = rData.mnOriginalDim;
871 :
872 0 : return nDim == mnDim;
873 : }
874 : };
875 :
876 : }
877 :
878 0 : size_t ScDPFieldControlBase::GetFieldIndexByData( const ScPivotFuncData& rData ) const
879 : {
880 0 : FuncDataType::const_iterator it = std::find_if(maFuncData.begin(), maFuncData.end(), EqualByDimOnly(rData));
881 0 : return it == maFuncData.end() ? PIVOTFIELD_INVALID : std::distance(maFuncData.begin(), it);
882 : }
883 :
884 : //=============================================================================
885 :
886 0 : ScDPHorFieldControl::ScDPHorFieldControl(
887 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
888 : ScDPFieldControlBase(pDialog, rResId, pCaption, pcHelpId),
889 : maScroll(this, WB_HORZ | WB_DRAG),
890 : mnFieldBtnRowCount(0),
891 0 : mnFieldBtnColCount(0)
892 : {
893 0 : maScroll.SetScrollHdl( LINK(this, ScDPHorFieldControl, ScrollHdl) );
894 0 : maScroll.SetEndScrollHdl( LINK(this, ScDPHorFieldControl, EndScrollHdl) );
895 0 : maScroll.Hide();
896 :
897 0 : AppendPaintable(&maScroll);
898 0 : }
899 :
900 0 : ScDPHorFieldControl::~ScDPHorFieldControl()
901 : {
902 0 : }
903 :
904 0 : Point ScDPHorFieldControl::GetFieldPosition( size_t nIndex )
905 : {
906 0 : Point aPos;
907 0 : Size aSize;
908 0 : GetFieldBtnPosSize(nIndex, aPos, aSize);
909 0 : return aPos;
910 : }
911 :
912 0 : Size ScDPHorFieldControl::GetFieldSize() const
913 : {
914 0 : return GetStdFieldBtnSize();
915 : }
916 :
917 0 : size_t ScDPHorFieldControl::GetFieldIndex( const Point& rPos )
918 : {
919 0 : if (rPos.X() < 0 || rPos.Y() < 0)
920 0 : return PIVOTFIELD_INVALID;
921 :
922 0 : Size aWndSize = GetSizePixel();
923 0 : if (rPos.X() > aWndSize.Width() || rPos.Y() > aWndSize.Height())
924 0 : return PIVOTFIELD_INVALID;
925 :
926 0 : size_t nX = rPos.X();
927 0 : size_t nY = rPos.Y();
928 0 : size_t nW = aWndSize.Width();
929 0 : size_t nH = aWndSize.Height();
930 :
931 0 : Size aFldSize = GetFieldSize();
932 0 : size_t nCurX = OUTER_MARGIN_HOR + aFldSize.Width() + ROW_FIELD_BTN_GAP/2;
933 0 : size_t nCurY = OUTER_MARGIN_VER + aFldSize.Height() + ROW_FIELD_BTN_GAP/2;
934 0 : size_t nCol = 0;
935 0 : size_t nRow = 0;
936 0 : while (nX > nCurX && nCurX <= nW)
937 : {
938 0 : nCurX += aFldSize.Width() + ROW_FIELD_BTN_GAP;
939 0 : ++nCol;
940 : }
941 0 : while (nY > nCurY && nCurY <= nH)
942 : {
943 0 : nCurY += aFldSize.Height() + ROW_FIELD_BTN_GAP;
944 0 : ++nRow;
945 : }
946 :
947 0 : size_t nOffset = maScroll.GetThumbPos();
948 0 : nCol += nOffset; // convert to logical column ID.
949 0 : size_t nIndex = nCol * mnFieldBtnRowCount + nRow;
950 0 : size_t nFldCount = GetFieldCount();
951 0 : if (nIndex > nFldCount)
952 0 : nIndex = nFldCount;
953 0 : return IsValidIndex(nIndex) ? nIndex : PIVOTFIELD_INVALID;
954 : }
955 :
956 0 : void ScDPHorFieldControl::Redraw()
957 : {
958 0 : VirtualDevice aVirDev;
959 : // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
960 0 : aVirDev.EnableRTL( IsRTLEnabled() );
961 0 : aVirDev.SetMapMode( MAP_PIXEL );
962 :
963 0 : Point aPos0;
964 0 : Size aSize( GetSizePixel() );
965 0 : Font aFont( GetFont() ); // Font vom Window
966 0 : aFont.SetTransparent( true );
967 0 : aVirDev.SetFont( aFont );
968 0 : aVirDev.SetOutputSizePixel( aSize );
969 :
970 0 : DrawBackground( aVirDev );
971 :
972 0 : FieldNames& rFields = GetFieldNames();
973 : {
974 0 : long nScrollOffset = maScroll.GetThumbPos();
975 0 : FieldNames::iterator itr = rFields.begin(), itrEnd = rFields.end();
976 0 : if (nScrollOffset)
977 0 : ::std::advance(itr, nScrollOffset*mnFieldBtnRowCount);
978 :
979 0 : for (size_t i = 0; itr != itrEnd; ++itr, ++i)
980 : {
981 0 : Point aFldPt;
982 0 : Size aFldSize;
983 0 : if (!GetFieldBtnPosSize(i, aFldPt, aFldSize))
984 0 : break;
985 :
986 0 : size_t nField = i + nScrollOffset*mnFieldBtnRowCount;
987 0 : bool bFocus = HasFocus() && (nField == GetSelectedField());
988 0 : DrawField(aVirDev, Rectangle(aFldPt, aFldSize), *itr, bFocus);
989 : }
990 : }
991 :
992 0 : DrawBitmap( aPos0, aVirDev.GetBitmap( aPos0, aSize ) );
993 0 : DrawPaintables();
994 0 : DrawInvertSelection();
995 0 : UpdateStyle();
996 0 : }
997 :
998 0 : void ScDPHorFieldControl::CalcSize()
999 : {
1000 0 : Size aWndSize = GetSizePixel();
1001 :
1002 0 : long nScrollSize = GetSettings().GetStyleSettings().GetScrollBarSize();
1003 0 : maScroll.SetSizePixel(Size(aWndSize.Width() - OUTER_MARGIN_HOR*2, nScrollSize));
1004 0 : maScroll.SetPosPixel(Point(OUTER_MARGIN_HOR, aWndSize.Height() - OUTER_MARGIN_VER - nScrollSize));
1005 :
1006 0 : long nTotalH = aWndSize.Height() - nScrollSize - OUTER_MARGIN_VER*2;
1007 0 : long nTotalW = aWndSize.Width() - OUTER_MARGIN_HOR*2;
1008 0 : mnFieldBtnRowCount = nTotalH / (GetFieldSize().Height() + ROW_FIELD_BTN_GAP);
1009 0 : mnFieldBtnColCount = (nTotalW + ROW_FIELD_BTN_GAP) / (GetFieldSize().Width() + ROW_FIELD_BTN_GAP);
1010 :
1011 0 : maScroll.SetLineSize(1);
1012 0 : maScroll.SetVisibleSize(mnFieldBtnColCount);
1013 0 : maScroll.SetPageSize(mnFieldBtnColCount);
1014 0 : maScroll.SetRange(Range(0, mnFieldBtnColCount));
1015 0 : }
1016 :
1017 0 : bool ScDPHorFieldControl::IsValidIndex(size_t /*nIndex*/) const
1018 : {
1019 0 : return true;
1020 : }
1021 :
1022 0 : size_t ScDPHorFieldControl::CalcNewFieldIndex(SCsCOL nDX, SCsROW nDY) const
1023 : {
1024 0 : size_t nSel = GetSelectedField();
1025 0 : size_t nFldCount = GetFieldCount();
1026 0 : SCsROW nRow = nSel % mnFieldBtnRowCount;
1027 0 : SCsCOL nCol = nSel / mnFieldBtnRowCount;
1028 : SCsCOL nColUpper = static_cast<SCsCOL>(ceil(
1029 0 : static_cast<double>(nFldCount) / static_cast<double>(mnFieldBtnRowCount)) - 1);
1030 0 : SCsROW nRowUpper = mnFieldBtnRowCount - 1;
1031 :
1032 0 : nCol += nDX;
1033 0 : if (nCol < 0)
1034 0 : nCol = 0;
1035 0 : else if (nColUpper < nCol)
1036 0 : nCol = nColUpper;
1037 0 : nRow += nDY;
1038 0 : if (nRow < 0)
1039 0 : nRow = 0;
1040 0 : else if (nRowUpper < nRow)
1041 0 : nRow = nRowUpper;
1042 :
1043 0 : nSel = nCol*mnFieldBtnRowCount + nRow;
1044 0 : if (nSel >= nFldCount)
1045 0 : nSel = nFldCount - 1;
1046 :
1047 0 : return nSel;
1048 : }
1049 :
1050 0 : size_t ScDPHorFieldControl::GetDisplayPosition(size_t nIndex) const
1051 : {
1052 0 : size_t nColFirst = maScroll.GetThumbPos();
1053 0 : size_t nColLast = nColFirst + mnFieldBtnColCount - 1;
1054 0 : size_t nCol = nIndex / mnFieldBtnRowCount;
1055 0 : size_t nRow = nIndex % mnFieldBtnRowCount;
1056 0 : if (nCol < nColFirst || nColLast < nCol)
1057 : // index is outside the visible area.
1058 0 : return INVALID_INDEX;
1059 :
1060 0 : size_t nPos = (nCol - nColFirst)*mnFieldBtnRowCount + nRow;
1061 0 : return nPos;
1062 : }
1063 :
1064 0 : String ScDPHorFieldControl::GetDescription() const
1065 : {
1066 0 : return ScResId(STR_ACC_DATAPILOT_COL_DESCR);
1067 : }
1068 :
1069 0 : void ScDPHorFieldControl::ScrollToEnd()
1070 : {
1071 0 : maScroll.DoScroll(maScroll.GetRangeMax());
1072 0 : }
1073 :
1074 0 : void ScDPHorFieldControl::ScrollToShowSelection()
1075 : {
1076 0 : size_t nLower = maScroll.GetThumbPos();
1077 0 : size_t nUpper = nLower + mnFieldBtnColCount - 1;
1078 0 : size_t nCol = GetSelectedField() / mnFieldBtnRowCount;
1079 0 : if (nCol < nLower)
1080 : {
1081 : // scroll to left.
1082 0 : maScroll.DoScroll(nCol);
1083 : }
1084 0 : else if (nUpper < nCol)
1085 : {
1086 : // scroll to right.
1087 0 : maScroll.DoScroll(nCol - mnFieldBtnColCount + 1);
1088 : }
1089 0 : }
1090 :
1091 0 : void ScDPHorFieldControl::ResetScrollBar()
1092 : {
1093 0 : long nOldMax = maScroll.GetRangeMax();
1094 : long nNewMax = static_cast<long>(ceil(
1095 0 : static_cast<double>(GetFieldCount()) / static_cast<double>(mnFieldBtnRowCount)));
1096 :
1097 0 : if (nOldMax != nNewMax)
1098 : {
1099 0 : maScroll.SetRangeMax(nNewMax);
1100 0 : bool bShow = mnFieldBtnColCount*mnFieldBtnRowCount < GetFieldCount();
1101 0 : maScroll.Show(bShow);
1102 : }
1103 0 : }
1104 :
1105 0 : void ScDPHorFieldControl::HandleWheelScroll(long /*nNotch*/)
1106 : {
1107 : // not handled for horizontal field controls.
1108 0 : }
1109 :
1110 0 : bool ScDPHorFieldControl::GetFieldBtnPosSize(size_t nPos, Point& rPos, Size& rSize)
1111 : {
1112 0 : if (nPos >= mnFieldBtnColCount*mnFieldBtnRowCount)
1113 0 : return false;
1114 :
1115 0 : Point aPos = Point(OUTER_MARGIN_HOR, OUTER_MARGIN_VER);
1116 0 : size_t nRow = nPos % mnFieldBtnRowCount;
1117 0 : size_t nCol = nPos / mnFieldBtnRowCount;
1118 :
1119 0 : aPos.X() += nCol*(GetFieldSize().Width() + ROW_FIELD_BTN_GAP);
1120 0 : aPos.Y() += nRow*(GetFieldSize().Height() + ROW_FIELD_BTN_GAP);
1121 :
1122 0 : rPos = aPos;
1123 0 : rSize = GetFieldSize();
1124 0 : return true;
1125 : }
1126 :
1127 0 : void ScDPHorFieldControl::HandleScroll()
1128 : {
1129 0 : Redraw();
1130 0 : }
1131 :
1132 0 : IMPL_LINK_NOARG(ScDPHorFieldControl, ScrollHdl)
1133 : {
1134 0 : HandleScroll();
1135 0 : return 0;
1136 : }
1137 :
1138 0 : IMPL_LINK_NOARG(ScDPHorFieldControl, EndScrollHdl)
1139 : {
1140 0 : HandleScroll();
1141 0 : return 0;
1142 : }
1143 :
1144 : //=============================================================================
1145 :
1146 0 : ScDPPageFieldControl::ScDPPageFieldControl(
1147 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1148 0 : ScDPHorFieldControl(pDialog, rResId, pCaption, pcHelpId)
1149 : {
1150 0 : }
1151 :
1152 0 : ScDPPageFieldControl::~ScDPPageFieldControl()
1153 : {
1154 0 : }
1155 :
1156 0 : ScPivotFieldType ScDPPageFieldControl::GetFieldType() const
1157 : {
1158 0 : return PIVOTFIELDTYPE_PAGE;
1159 : }
1160 :
1161 0 : String ScDPPageFieldControl::GetDescription() const
1162 : {
1163 0 : return ScResId(STR_ACC_DATAPILOT_PAGE_DESCR);
1164 : }
1165 :
1166 : //=============================================================================
1167 :
1168 0 : ScDPColFieldControl::ScDPColFieldControl(
1169 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1170 0 : ScDPHorFieldControl(pDialog, rResId, pCaption, pcHelpId)
1171 : {
1172 0 : }
1173 :
1174 0 : ScDPColFieldControl::~ScDPColFieldControl()
1175 : {
1176 0 : }
1177 :
1178 0 : ScPivotFieldType ScDPColFieldControl::GetFieldType() const
1179 : {
1180 0 : return PIVOTFIELDTYPE_COL;
1181 : }
1182 :
1183 0 : String ScDPColFieldControl::GetDescription() const
1184 : {
1185 0 : return ScResId(STR_ACC_DATAPILOT_COL_DESCR);
1186 : }
1187 :
1188 : //=============================================================================
1189 :
1190 0 : ScDPRowFieldControl::ScDPRowFieldControl(
1191 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1192 : ScDPFieldControlBase(pDialog, rResId, pCaption, pcHelpId),
1193 : maScroll(this, WB_VERT | WB_DRAG),
1194 0 : mnColumnBtnCount(0)
1195 : {
1196 0 : maScroll.SetScrollHdl( LINK(this, ScDPRowFieldControl, ScrollHdl) );
1197 0 : maScroll.SetEndScrollHdl( LINK(this, ScDPRowFieldControl, EndScrollHdl) );
1198 0 : maScroll.Show(false);
1199 :
1200 0 : AppendPaintable(&maScroll);
1201 0 : }
1202 :
1203 0 : ScDPRowFieldControl::~ScDPRowFieldControl()
1204 : {
1205 0 : }
1206 :
1207 : //-------------------------------------------------------------------
1208 :
1209 0 : Point ScDPRowFieldControl::GetFieldPosition(size_t nIndex)
1210 : {
1211 0 : Point aPos;
1212 0 : Size aSize;
1213 0 : GetFieldBtnPosSize(nIndex, aPos, aSize);
1214 0 : return aPos;
1215 : }
1216 :
1217 0 : Size ScDPRowFieldControl::GetFieldSize() const
1218 : {
1219 0 : return GetStdFieldBtnSize();
1220 : }
1221 :
1222 0 : size_t ScDPRowFieldControl::GetFieldIndex( const Point& rPos )
1223 : {
1224 0 : if (rPos.X() < 0 || rPos.Y() < 0)
1225 0 : return PIVOTFIELD_INVALID;
1226 :
1227 0 : long nFldH = GetFieldSize().Height();
1228 0 : long nThreshold = OUTER_MARGIN_VER + nFldH + ROW_FIELD_BTN_GAP / 2;
1229 :
1230 0 : size_t nIndex = 0;
1231 0 : for (; nIndex < mnColumnBtnCount; ++nIndex)
1232 : {
1233 0 : if (rPos.Y() < nThreshold)
1234 0 : break;
1235 :
1236 0 : nThreshold += nFldH + ROW_FIELD_BTN_GAP;
1237 : }
1238 :
1239 0 : if (nIndex >= mnColumnBtnCount)
1240 0 : nIndex = mnColumnBtnCount - 1;
1241 :
1242 0 : nIndex += maScroll.GetThumbPos();
1243 0 : return IsValidIndex(nIndex) ? nIndex : PIVOTFIELD_INVALID;
1244 : }
1245 :
1246 0 : void ScDPRowFieldControl::Redraw()
1247 : {
1248 0 : VirtualDevice aVirDev;
1249 : // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
1250 0 : aVirDev.EnableRTL( IsRTLEnabled() );
1251 0 : aVirDev.SetMapMode( MAP_PIXEL );
1252 :
1253 0 : Point aPos0;
1254 0 : Size aWndSize = GetSizePixel();
1255 0 : Font aFont = GetFont();
1256 0 : aFont.SetTransparent(true);
1257 0 : aVirDev.SetFont(aFont);
1258 0 : aVirDev.SetOutputSizePixel(aWndSize);
1259 :
1260 0 : DrawBackground(aVirDev);
1261 :
1262 0 : FieldNames& rFields = GetFieldNames();
1263 : {
1264 0 : long nScrollOffset = maScroll.GetThumbPos();
1265 0 : FieldNames::iterator itr = rFields.begin(), itrEnd = rFields.end();
1266 0 : if (nScrollOffset)
1267 0 : ::std::advance(itr, nScrollOffset);
1268 :
1269 0 : for (size_t i = 0; itr != itrEnd; ++itr, ++i)
1270 : {
1271 0 : Point aFldPt;
1272 0 : Size aFldSize;
1273 0 : if (!GetFieldBtnPosSize(i, aFldPt, aFldSize))
1274 0 : break;
1275 :
1276 0 : size_t nField = i + nScrollOffset;
1277 0 : bool bFocus = HasFocus() && (nField == GetSelectedField());
1278 0 : DrawField(aVirDev, Rectangle(aFldPt, aFldSize), *itr, bFocus);
1279 : }
1280 : }
1281 :
1282 : // Create a bitmap from the virtual device, and place that bitmap onto
1283 : // this control.
1284 0 : DrawBitmap(aPos0, aVirDev.GetBitmap(aPos0, aWndSize));
1285 :
1286 0 : DrawPaintables();
1287 0 : DrawInvertSelection();
1288 0 : UpdateStyle();
1289 0 : }
1290 :
1291 0 : void ScDPRowFieldControl::CalcSize()
1292 : {
1293 0 : Size aWndSize = GetSizePixel();
1294 :
1295 0 : long nTotal = aWndSize.Height() - OUTER_MARGIN_VER;
1296 0 : mnColumnBtnCount = nTotal / (GetFieldSize().Height() + ROW_FIELD_BTN_GAP);
1297 :
1298 0 : long nScrollSize = GetSettings().GetStyleSettings().GetScrollBarSize();
1299 :
1300 0 : maScroll.SetSizePixel(Size(nScrollSize, aWndSize.Height() - OUTER_MARGIN_VER*2));
1301 0 : maScroll.SetPosPixel(Point(aWndSize.Width() - nScrollSize - OUTER_MARGIN_HOR, OUTER_MARGIN_VER));
1302 0 : maScroll.SetLineSize(1);
1303 0 : maScroll.SetVisibleSize(mnColumnBtnCount);
1304 0 : maScroll.SetPageSize(mnColumnBtnCount);
1305 0 : maScroll.SetRange(Range(0, mnColumnBtnCount));
1306 0 : maScroll.DoScroll(0);
1307 :
1308 0 : }
1309 :
1310 0 : bool ScDPRowFieldControl::IsValidIndex(size_t /*nIndex*/) const
1311 : {
1312 : // This method is here in case we decide to impose an arbitrary upper
1313 : // boundary on the number of fields.
1314 0 : return true;
1315 : }
1316 :
1317 0 : size_t ScDPRowFieldControl::CalcNewFieldIndex(SCsCOL /*nDX*/, SCsROW nDY) const
1318 : {
1319 0 : size_t nNewField = GetSelectedField();
1320 0 : nNewField += nDY;
1321 0 : return IsExistingIndex(nNewField) ? nNewField : GetSelectedField();
1322 : }
1323 :
1324 0 : size_t ScDPRowFieldControl::GetDisplayPosition(size_t nIndex) const
1325 : {
1326 0 : size_t nLower = maScroll.GetThumbPos();
1327 0 : size_t nUpper = nLower + mnColumnBtnCount;
1328 0 : if (nLower <= nIndex && nIndex <= nUpper)
1329 0 : return nIndex - nLower;
1330 :
1331 0 : return INVALID_INDEX;
1332 : }
1333 :
1334 : //-------------------------------------------------------------------
1335 :
1336 0 : String ScDPRowFieldControl::GetDescription() const
1337 : {
1338 0 : return ScResId(STR_ACC_DATAPILOT_ROW_DESCR);
1339 : }
1340 :
1341 0 : ScPivotFieldType ScDPRowFieldControl::GetFieldType() const
1342 : {
1343 0 : return PIVOTFIELDTYPE_ROW;
1344 : }
1345 :
1346 0 : void ScDPRowFieldControl::ScrollToEnd()
1347 : {
1348 0 : maScroll.DoScroll(maScroll.GetRangeMax());
1349 0 : }
1350 :
1351 0 : void ScDPRowFieldControl::ScrollToShowSelection()
1352 : {
1353 0 : size_t nLower = maScroll.GetThumbPos();
1354 0 : size_t nUpper = nLower + mnColumnBtnCount - 1;
1355 0 : size_t nSel = GetSelectedField();
1356 0 : if (nSel < nLower)
1357 : {
1358 : // scroll up
1359 0 : maScroll.DoScroll(nSel);
1360 : }
1361 0 : else if (nUpper < nSel)
1362 : {
1363 : // scroll down
1364 0 : size_t nD = nSel - nUpper;
1365 0 : maScroll.DoScroll(nLower + nD);
1366 : }
1367 0 : }
1368 :
1369 0 : void ScDPRowFieldControl::ResetScrollBar()
1370 : {
1371 0 : long nOldMax = maScroll.GetRangeMax();
1372 0 : long nNewMax = std::max<long>(mnColumnBtnCount, GetFieldCount());
1373 :
1374 0 : if (nOldMax != nNewMax)
1375 : {
1376 0 : maScroll.SetRangeMax(nNewMax);
1377 0 : maScroll.Show(GetFieldCount() > mnColumnBtnCount);
1378 : }
1379 0 : }
1380 :
1381 0 : void ScDPRowFieldControl::HandleWheelScroll(long nNotch)
1382 : {
1383 0 : maScroll.DoScroll(maScroll.GetThumbPos() - nNotch);
1384 0 : }
1385 :
1386 0 : bool ScDPRowFieldControl::GetFieldBtnPosSize(size_t nPos, Point& rPos, Size& rSize)
1387 : {
1388 0 : if (nPos >= mnColumnBtnCount)
1389 0 : return false;
1390 :
1391 0 : size_t nOffset = maScroll.GetThumbPos();
1392 0 : if (nPos + nOffset >= GetFieldCount())
1393 0 : return false;
1394 :
1395 0 : rSize = GetFieldSize();
1396 0 : rPos = Point(OUTER_MARGIN_HOR, OUTER_MARGIN_VER);
1397 0 : rPos.Y() += nPos * (rSize.Height() + ROW_FIELD_BTN_GAP);
1398 0 : return true;
1399 : }
1400 :
1401 0 : void ScDPRowFieldControl::HandleScroll()
1402 : {
1403 0 : Redraw();
1404 0 : }
1405 :
1406 0 : IMPL_LINK_NOARG(ScDPRowFieldControl, ScrollHdl)
1407 : {
1408 0 : HandleScroll();
1409 0 : return 0;
1410 : }
1411 :
1412 0 : IMPL_LINK_NOARG(ScDPRowFieldControl, EndScrollHdl)
1413 : {
1414 0 : HandleScroll();
1415 0 : return 0;
1416 : }
1417 :
1418 : //=============================================================================
1419 :
1420 0 : ScDPSelectFieldControl::ScDPSelectFieldControl(
1421 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1422 0 : ScDPHorFieldControl(pDialog, rResId, pCaption, pcHelpId)
1423 : {
1424 0 : SetName(String(ScResId(STR_SELECT)));
1425 0 : }
1426 :
1427 0 : ScDPSelectFieldControl::~ScDPSelectFieldControl()
1428 : {
1429 0 : }
1430 :
1431 0 : ScPivotFieldType ScDPSelectFieldControl::GetFieldType() const
1432 : {
1433 0 : return PIVOTFIELDTYPE_SELECT;
1434 : }
1435 :
1436 0 : String ScDPSelectFieldControl::GetDescription() const
1437 : {
1438 0 : return ScResId(STR_ACC_DATAPILOT_SEL_DESCR);
1439 : }
1440 :
1441 : //=============================================================================
1442 :
1443 0 : ScDPDataFieldControl::ScDPDataFieldControl(
1444 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1445 0 : ScDPHorFieldControl(pDialog, rResId, pCaption, pcHelpId)
1446 : {
1447 0 : }
1448 :
1449 0 : ScDPDataFieldControl::~ScDPDataFieldControl()
1450 : {
1451 0 : }
1452 :
1453 0 : ScPivotFieldType ScDPDataFieldControl::GetFieldType() const
1454 : {
1455 0 : return PIVOTFIELDTYPE_DATA;
1456 : }
1457 :
1458 0 : Size ScDPDataFieldControl::GetFieldSize() const
1459 : {
1460 0 : Size aWndSize = GetSizePixel();
1461 0 : long nFieldObjWidth = static_cast<long>(aWndSize.Width() / 2.0 - OUTER_MARGIN_HOR - DATA_FIELD_BTN_GAP/2);
1462 0 : Size aFieldSize(nFieldObjWidth, FIELD_BTN_HEIGHT);
1463 0 : return aFieldSize;
1464 : }
1465 :
1466 0 : String ScDPDataFieldControl::GetDescription() const
1467 : {
1468 0 : return ScResId(STR_ACC_DATAPILOT_DATA_DESCR);
1469 93 : }
1470 :
1471 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|