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 "fieldwnd.hxx"
39 :
40 : #include <comphelper/string.hxx>
41 : #include <vcl/decoview.hxx>
42 : #include <vcl/help.hxx>
43 : #include <vcl/svapp.hxx>
44 : #include <vcl/virdev.hxx>
45 : #include <vcl/mnemonic.hxx>
46 :
47 : #include "pvlaydlg.hxx"
48 : #include "dpuiglobal.hxx"
49 : #include "dpmacros.hxx"
50 : #include "AccessibleDataPilotControl.hxx"
51 : #include "scresid.hxx"
52 : #include "pivot.hrc"
53 :
54 : using namespace com::sun::star;
55 : using ::rtl::OUString;
56 : using ::std::vector;
57 : using ::com::sun::star::uno::Reference;
58 : using ::com::sun::star::uno::WeakReference;
59 : using ::com::sun::star::accessibility::XAccessible;
60 :
61 : const size_t PIVOTFIELD_INVALID = static_cast< size_t >(-1);
62 : const size_t INVALID_INDEX = static_cast<size_t>(-1);
63 :
64 : #if DEBUG_PIVOT_TABLE
65 : #include <iostream>
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 rtl::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 : rtl::OUString ScDPFieldControlBase::FieldName::getDisplayedText() const
91 : {
92 0 : rtl::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 rtl::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 rtl::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 rtl::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 : rtl::OUString ScDPFieldControlBase::GetFieldText( size_t nIndex ) const
298 : {
299 0 : if( IsExistingIndex( nIndex ) )
300 0 : return maFieldNames[nIndex].maText;
301 0 : return rtl::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 : for( xub_StrLen nToken = 0, nStringIx = 0; nToken < nTokenCnt; ++nToken )
585 : {
586 0 : String aLine( GetText().GetToken( 0, '\n', nStringIx ) );
587 0 : Point aLinePos( (aSize.Width() - rDev.GetCtrlTextWidth( aLine )) / 2, nY );
588 0 : rDev.DrawCtrlText( aLinePos, aLine );
589 0 : nY += rDev.GetTextHeight();
590 0 : }
591 0 : }
592 :
593 0 : void ScDPFieldControlBase::DrawField(
594 : OutputDevice& rDev, const Rectangle& rRect, FieldName& rText, bool bFocus )
595 : {
596 0 : const StyleSettings& rStyleSet = GetSettings().GetStyleSettings();
597 0 : Color aTextColor = rStyleSet.GetButtonTextColor();
598 :
599 0 : VirtualDevice aVirDev( rDev );
600 : // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
601 0 : aVirDev.EnableRTL( IsRTLEnabled() );
602 :
603 0 : rtl::OUString aText = rText.getDisplayedText();
604 :
605 0 : Size aDevSize( rRect.GetSize() );
606 0 : long nWidth = aDevSize.Width();
607 0 : long nHeight = aDevSize.Height();
608 0 : long nLabelWidth = rDev.GetTextWidth( aText );
609 0 : long nLabelHeight = rDev.GetTextHeight();
610 :
611 : // #i31600# if text is too long, cut and add ellipsis
612 0 : rText.mbFits = nLabelWidth + 6 <= nWidth;
613 0 : if (!rText.mbFits)
614 : {
615 0 : sal_Int32 nMinLen = 0;
616 0 : sal_Int32 nMaxLen = aText.getLength();
617 0 : bool bFits = false;
618 0 : do
619 : {
620 0 : sal_Int32 nCurrLen = (nMinLen + nMaxLen) / 2;
621 0 : rtl::OUStringBuffer aBuf(rText.maText.copy(0, nCurrLen));
622 0 : aBuf.appendAscii("...");
623 0 : aText = aBuf.makeStringAndClear();
624 0 : nLabelWidth = rDev.GetTextWidth( aText );
625 0 : bFits = nLabelWidth + 6 <= nWidth;
626 0 : (bFits ? nMinLen : nMaxLen) = nCurrLen;
627 : }
628 0 : while( !bFits || (nMinLen + 1 < nMaxLen) );
629 : }
630 0 : Point aLabelPos( (nWidth - nLabelWidth) / 2, ::std::max< long >( (nHeight - nLabelHeight) / 2, 3 ) );
631 :
632 0 : aVirDev.SetOutputSizePixel( aDevSize );
633 0 : aVirDev.SetFont( rDev.GetFont() );
634 0 : DecorationView aDecoView( &aVirDev );
635 0 : aDecoView.DrawButton( Rectangle( Point( 0, 0 ), aDevSize ), bFocus ? BUTTON_DRAW_DEFAULT : 0 );
636 0 : aVirDev.SetTextColor( aTextColor );
637 0 : aVirDev.DrawText( aLabelPos, aText );
638 0 : rDev.DrawBitmap( rRect.TopLeft(), aVirDev.GetBitmap( Point( 0, 0 ), aDevSize ) );
639 0 : }
640 :
641 0 : void ScDPFieldControlBase::AppendPaintable(Window* p)
642 : {
643 0 : maPaintables.push_back(p);
644 0 : }
645 :
646 0 : void ScDPFieldControlBase::DrawPaintables()
647 : {
648 0 : Rectangle aRect(GetPosPixel(), GetSizePixel());
649 0 : Paintables::iterator itr = maPaintables.begin(), itrEnd = maPaintables.end();
650 0 : for (; itr != itrEnd; ++itr)
651 : {
652 0 : Window* p = *itr;
653 0 : if (!p->IsVisible())
654 0 : continue;
655 :
656 0 : p->Paint(aRect);
657 : }
658 0 : }
659 :
660 0 : void ScDPFieldControlBase::DrawInvertSelection()
661 : {
662 0 : if (!HasFocus())
663 : return;
664 :
665 0 : if (mnFieldSelected >= maFieldNames.size())
666 : return;
667 :
668 0 : size_t nPos = GetDisplayPosition(mnFieldSelected);
669 0 : if (nPos == INVALID_INDEX)
670 : return;
671 :
672 0 : Size aFldSize = GetFieldSize();
673 0 : long nFldWidth = aFldSize.Width();
674 : long nSelWidth = std::min<long>(
675 0 : GetTextWidth(maFieldNames[mnFieldSelected].getDisplayedText()) + 4, nFldWidth - 6);
676 :
677 0 : Point aPos = GetFieldPosition(nPos);
678 0 : aPos += Point((nFldWidth - nSelWidth) / 2, 3);
679 0 : Size aSize(nSelWidth, aFldSize.Height() - 6);
680 :
681 0 : Rectangle aSel(aPos, aSize);
682 0 : InvertTracking(aSel, SHOWTRACK_SMALL | SHOWTRACK_WINDOW);
683 : }
684 :
685 0 : Size ScDPFieldControlBase::GetStdFieldBtnSize() const
686 : {
687 0 : return mpDlg->GetStdFieldBtnSize();
688 : }
689 :
690 0 : void ScDPFieldControlBase::MoveField( size_t nDestIndex )
691 : {
692 0 : if (nDestIndex != mnFieldSelected)
693 : {
694 0 : std::swap(maFieldNames[nDestIndex], maFieldNames[mnFieldSelected]);
695 0 : std::swap(maFuncData[nDestIndex], maFuncData[mnFieldSelected]);
696 0 : mnFieldSelected = nDestIndex;
697 : }
698 0 : }
699 :
700 0 : void ScDPFieldControlBase::MoveFieldRel( SCsCOL nDX, SCsROW nDY )
701 : {
702 0 : MoveField( CalcNewFieldIndex( nDX, nDY ) );
703 0 : }
704 :
705 0 : void ScDPFieldControlBase::MoveSelection(size_t nIndex)
706 : {
707 0 : FieldNames& rFields = GetFieldNames();
708 0 : if (rFields.empty())
709 0 : return;
710 :
711 0 : if (nIndex >= rFields.size())
712 : // Prevent it from going out-of-bound.
713 0 : nIndex = rFields.size() - 1;
714 :
715 0 : if( mnFieldSelected != nIndex )
716 : {
717 0 : size_t nOldSelected = mnFieldSelected;
718 0 : mnFieldSelected = nIndex;
719 0 : Invalidate();
720 :
721 0 : if (HasFocus())
722 0 : FieldFocusChanged(nOldSelected, mnFieldSelected);
723 : }
724 :
725 0 : ScrollToShowSelection();
726 : }
727 :
728 0 : void ScDPFieldControlBase::MoveSelection(SCsCOL nDX, SCsROW nDY)
729 : {
730 0 : size_t nNewIndex = CalcNewFieldIndex( nDX, nDY );
731 0 : MoveSelection( nNewIndex );
732 0 : }
733 :
734 0 : sal_uInt8 ScDPFieldControlBase::GetNextDupCount(const rtl::OUString& rFieldText) const
735 : {
736 0 : sal_uInt8 nMax = 0;
737 0 : FieldNames::const_iterator it = maFieldNames.begin(), itEnd = maFieldNames.end();
738 0 : for (; it != itEnd; ++it)
739 : {
740 0 : if (it->maText != rFieldText)
741 0 : continue;
742 :
743 0 : sal_uInt8 nNextUp = it->mnDupCount + 1;
744 0 : if (nMax < nNextUp)
745 0 : nMax = nNextUp;
746 : }
747 0 : return nMax;
748 : }
749 :
750 0 : sal_uInt8 ScDPFieldControlBase::GetNextDupCount(const ScPivotFuncData& rData, size_t nSelfIndex) const
751 : {
752 0 : sal_uInt8 nDupCount = 0;
753 0 : bool bFound = false;
754 0 : for (size_t i = 0, n = maFuncData.size(); i < n; ++i)
755 : {
756 0 : if (i == nSelfIndex)
757 : // Skip itself.
758 0 : continue;
759 :
760 0 : const ScPivotFuncData& r = maFuncData[i];
761 :
762 0 : if (r.mnCol != rData.mnCol || r.mnFuncMask != rData.mnFuncMask)
763 0 : continue;
764 :
765 0 : bFound = true;
766 0 : if (r.mnDupCount > nDupCount)
767 0 : nDupCount = r.mnDupCount;
768 : }
769 :
770 0 : return bFound ? nDupCount + 1 : 0;
771 : }
772 :
773 0 : void ScDPFieldControlBase::SelectNext()
774 : {
775 0 : MoveSelection(mnFieldSelected + 1);
776 0 : }
777 :
778 0 : void ScDPFieldControlBase::GrabFocusAndSelect( size_t nIndex )
779 : {
780 0 : MoveSelection( nIndex );
781 0 : if( !HasFocus() )
782 0 : GrabFocus();
783 0 : }
784 :
785 0 : const ScPivotFuncData& ScDPFieldControlBase::GetFuncData(size_t nIndex) const
786 : {
787 0 : return maFuncData.at(nIndex);
788 : }
789 :
790 0 : ScPivotFuncData& ScDPFieldControlBase::GetFuncData(size_t nIndex)
791 : {
792 0 : return maFuncData.at(nIndex);
793 : }
794 :
795 : namespace {
796 :
797 : class PushFuncItem : std::unary_function<ScPivotFuncData, void>
798 : {
799 : std::vector<ScDPFieldControlBase::FuncItem>& mrItems;
800 : public:
801 0 : PushFuncItem(std::vector<ScDPFieldControlBase::FuncItem>& rItems) : mrItems(rItems) {}
802 :
803 0 : void operator() (const ScPivotFuncData& r)
804 : {
805 : ScDPFieldControlBase::FuncItem aItem;
806 0 : aItem.mnCol = r.mnCol;
807 0 : aItem.mnFuncMask = r.mnFuncMask;
808 0 : mrItems.push_back(aItem);
809 0 : }
810 : };
811 :
812 : }
813 :
814 0 : void ScDPFieldControlBase::GetAllFuncItems(std::vector<FuncItem>& rItems) const
815 : {
816 0 : std::for_each(maFuncData.begin(), maFuncData.end(), PushFuncItem(rItems));
817 0 : }
818 :
819 : namespace {
820 :
821 : class PivotFieldInserter : public ::std::unary_function<ScPivotFuncData, void>
822 : {
823 : vector<ScPivotField>& mrFields;
824 : public:
825 0 : explicit PivotFieldInserter(vector<ScPivotField>& r, size_t nSize) : mrFields(r)
826 : {
827 0 : mrFields.reserve(nSize);
828 0 : }
829 :
830 0 : PivotFieldInserter(const PivotFieldInserter& r) : mrFields(r.mrFields) {}
831 :
832 0 : void operator() (const ScPivotFuncData& r)
833 : {
834 0 : ScPivotField aField;
835 0 : aField.nCol = r.mnCol;
836 0 : aField.mnOriginalDim = r.mnOriginalDim;
837 0 : aField.mnDupCount = r.mnDupCount;
838 0 : aField.nFuncMask = r.mnFuncMask;
839 0 : aField.maFieldRef = r.maFieldRef;
840 0 : mrFields.push_back(aField);
841 0 : }
842 : };
843 :
844 : }
845 :
846 0 : void ScDPFieldControlBase::ConvertToPivotArray(std::vector<ScPivotField>& rArray) const
847 : {
848 0 : for_each(maFuncData.begin(), maFuncData.end(), PivotFieldInserter(rArray, maFuncData.size()));
849 0 : }
850 :
851 : namespace {
852 :
853 : class EqualByDimOnly : std::unary_function<ScPivotFuncData, bool>
854 : {
855 : const ScPivotFuncData& mrData;
856 : long mnDim;
857 :
858 : public:
859 0 : EqualByDimOnly(const ScPivotFuncData& rData) : mrData(rData)
860 : {
861 0 : mnDim = rData.mnCol;
862 0 : if (rData.mnOriginalDim >= 0)
863 0 : mnDim = rData.mnOriginalDim;
864 0 : }
865 0 : bool operator() (const ScPivotFuncData& rData) const
866 : {
867 0 : long nDim = rData.mnCol;
868 0 : if (rData.mnOriginalDim >= 0)
869 0 : nDim = rData.mnOriginalDim;
870 :
871 0 : return nDim == mnDim;
872 : }
873 : };
874 :
875 : }
876 :
877 0 : size_t ScDPFieldControlBase::GetFieldIndexByData( const ScPivotFuncData& rData ) const
878 : {
879 0 : FuncDataType::const_iterator it = std::find_if(maFuncData.begin(), maFuncData.end(), EqualByDimOnly(rData));
880 0 : return it == maFuncData.end() ? PIVOTFIELD_INVALID : std::distance(maFuncData.begin(), it);
881 : }
882 :
883 : //=============================================================================
884 :
885 0 : ScDPHorFieldControl::ScDPHorFieldControl(
886 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
887 : ScDPFieldControlBase(pDialog, rResId, pCaption, pcHelpId),
888 : maScroll(this, WB_HORZ | WB_DRAG),
889 : mnFieldBtnRowCount(0),
890 0 : mnFieldBtnColCount(0)
891 : {
892 0 : maScroll.SetScrollHdl( LINK(this, ScDPHorFieldControl, ScrollHdl) );
893 0 : maScroll.SetEndScrollHdl( LINK(this, ScDPHorFieldControl, EndScrollHdl) );
894 0 : maScroll.Hide();
895 :
896 0 : AppendPaintable(&maScroll);
897 0 : }
898 :
899 0 : ScDPHorFieldControl::~ScDPHorFieldControl()
900 : {
901 0 : }
902 :
903 0 : Point ScDPHorFieldControl::GetFieldPosition( size_t nIndex )
904 : {
905 0 : Point aPos;
906 0 : Size aSize;
907 0 : GetFieldBtnPosSize(nIndex, aPos, aSize);
908 0 : return aPos;
909 : }
910 :
911 0 : Size ScDPHorFieldControl::GetFieldSize() const
912 : {
913 0 : return GetStdFieldBtnSize();
914 : }
915 :
916 0 : size_t ScDPHorFieldControl::GetFieldIndex( const Point& rPos )
917 : {
918 0 : if (rPos.X() < 0 || rPos.Y() < 0)
919 0 : return PIVOTFIELD_INVALID;
920 :
921 0 : Size aWndSize = GetSizePixel();
922 0 : if (rPos.X() > aWndSize.Width() || rPos.Y() > aWndSize.Height())
923 0 : return PIVOTFIELD_INVALID;
924 :
925 0 : size_t nX = rPos.X();
926 0 : size_t nY = rPos.Y();
927 0 : size_t nW = aWndSize.Width();
928 0 : size_t nH = aWndSize.Height();
929 :
930 0 : Size aFldSize = GetFieldSize();
931 0 : size_t nCurX = OUTER_MARGIN_HOR + aFldSize.Width() + ROW_FIELD_BTN_GAP/2;
932 0 : size_t nCurY = OUTER_MARGIN_VER + aFldSize.Height() + ROW_FIELD_BTN_GAP/2;
933 0 : size_t nCol = 0;
934 0 : size_t nRow = 0;
935 0 : while (nX > nCurX && nCurX <= nW)
936 : {
937 0 : nCurX += aFldSize.Width() + ROW_FIELD_BTN_GAP;
938 0 : ++nCol;
939 : }
940 0 : while (nY > nCurY && nCurY <= nH)
941 : {
942 0 : nCurY += aFldSize.Height() + ROW_FIELD_BTN_GAP;
943 0 : ++nRow;
944 : }
945 :
946 0 : size_t nOffset = maScroll.GetThumbPos();
947 0 : nCol += nOffset; // convert to logical column ID.
948 0 : size_t nIndex = nCol * mnFieldBtnRowCount + nRow;
949 0 : size_t nFldCount = GetFieldCount();
950 0 : if (nIndex > nFldCount)
951 0 : nIndex = nFldCount;
952 0 : return IsValidIndex(nIndex) ? nIndex : PIVOTFIELD_INVALID;
953 : }
954 :
955 0 : void ScDPHorFieldControl::Redraw()
956 : {
957 0 : VirtualDevice aVirDev;
958 : // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
959 0 : aVirDev.EnableRTL( IsRTLEnabled() );
960 0 : aVirDev.SetMapMode( MAP_PIXEL );
961 :
962 0 : Point aPos0;
963 0 : Size aSize( GetSizePixel() );
964 0 : Font aFont( GetFont() ); // Font vom Window
965 0 : aFont.SetTransparent( true );
966 0 : aVirDev.SetFont( aFont );
967 0 : aVirDev.SetOutputSizePixel( aSize );
968 :
969 0 : DrawBackground( aVirDev );
970 :
971 0 : FieldNames& rFields = GetFieldNames();
972 : {
973 0 : long nScrollOffset = maScroll.GetThumbPos();
974 0 : FieldNames::iterator itr = rFields.begin(), itrEnd = rFields.end();
975 0 : if (nScrollOffset)
976 0 : ::std::advance(itr, nScrollOffset*mnFieldBtnRowCount);
977 :
978 0 : for (size_t i = 0; itr != itrEnd; ++itr, ++i)
979 : {
980 0 : Point aFldPt;
981 0 : Size aFldSize;
982 0 : if (!GetFieldBtnPosSize(i, aFldPt, aFldSize))
983 : break;
984 :
985 0 : size_t nField = i + nScrollOffset*mnFieldBtnRowCount;
986 0 : bool bFocus = HasFocus() && (nField == GetSelectedField());
987 0 : DrawField(aVirDev, Rectangle(aFldPt, aFldSize), *itr, bFocus);
988 : }
989 : }
990 :
991 0 : DrawBitmap( aPos0, aVirDev.GetBitmap( aPos0, aSize ) );
992 0 : DrawPaintables();
993 0 : DrawInvertSelection();
994 0 : UpdateStyle();
995 0 : }
996 :
997 0 : void ScDPHorFieldControl::CalcSize()
998 : {
999 0 : Size aWndSize = GetSizePixel();
1000 :
1001 0 : long nScrollSize = GetSettings().GetStyleSettings().GetScrollBarSize();
1002 0 : maScroll.SetSizePixel(Size(aWndSize.Width() - OUTER_MARGIN_HOR*2, nScrollSize));
1003 0 : maScroll.SetPosPixel(Point(OUTER_MARGIN_HOR, aWndSize.Height() - OUTER_MARGIN_VER - nScrollSize));
1004 :
1005 0 : long nTotalH = aWndSize.Height() - nScrollSize - OUTER_MARGIN_VER*2;
1006 0 : long nTotalW = aWndSize.Width() - OUTER_MARGIN_HOR*2;
1007 0 : mnFieldBtnRowCount = nTotalH / (GetFieldSize().Height() + ROW_FIELD_BTN_GAP);
1008 0 : mnFieldBtnColCount = (nTotalW + ROW_FIELD_BTN_GAP) / (GetFieldSize().Width() + ROW_FIELD_BTN_GAP);
1009 :
1010 0 : maScroll.SetLineSize(1);
1011 0 : maScroll.SetVisibleSize(mnFieldBtnColCount);
1012 0 : maScroll.SetPageSize(mnFieldBtnColCount);
1013 0 : maScroll.SetRange(Range(0, mnFieldBtnColCount));
1014 0 : }
1015 :
1016 0 : bool ScDPHorFieldControl::IsValidIndex(size_t /*nIndex*/) const
1017 : {
1018 0 : return true;
1019 : }
1020 :
1021 0 : size_t ScDPHorFieldControl::CalcNewFieldIndex(SCsCOL nDX, SCsROW nDY) const
1022 : {
1023 0 : size_t nSel = GetSelectedField();
1024 0 : size_t nFldCount = GetFieldCount();
1025 0 : SCsROW nRow = nSel % mnFieldBtnRowCount;
1026 0 : SCsCOL nCol = nSel / mnFieldBtnRowCount;
1027 : SCsCOL nColUpper = static_cast<SCsCOL>(ceil(
1028 0 : static_cast<double>(nFldCount) / static_cast<double>(mnFieldBtnRowCount)) - 1);
1029 0 : SCsROW nRowUpper = mnFieldBtnRowCount - 1;
1030 :
1031 0 : nCol += nDX;
1032 0 : if (nCol < 0)
1033 0 : nCol = 0;
1034 0 : else if (nColUpper < nCol)
1035 0 : nCol = nColUpper;
1036 0 : nRow += nDY;
1037 0 : if (nRow < 0)
1038 0 : nRow = 0;
1039 0 : else if (nRowUpper < nRow)
1040 0 : nRow = nRowUpper;
1041 :
1042 0 : nSel = nCol*mnFieldBtnRowCount + nRow;
1043 0 : if (nSel >= nFldCount)
1044 0 : nSel = nFldCount - 1;
1045 :
1046 0 : return nSel;
1047 : }
1048 :
1049 0 : size_t ScDPHorFieldControl::GetDisplayPosition(size_t nIndex) const
1050 : {
1051 0 : size_t nColFirst = maScroll.GetThumbPos();
1052 0 : size_t nColLast = nColFirst + mnFieldBtnColCount - 1;
1053 0 : size_t nCol = nIndex / mnFieldBtnRowCount;
1054 0 : size_t nRow = nIndex % mnFieldBtnRowCount;
1055 0 : if (nCol < nColFirst || nColLast < nCol)
1056 : // index is outside the visible area.
1057 0 : return INVALID_INDEX;
1058 :
1059 0 : size_t nPos = (nCol - nColFirst)*mnFieldBtnRowCount + nRow;
1060 0 : return nPos;
1061 : }
1062 :
1063 0 : String ScDPHorFieldControl::GetDescription() const
1064 : {
1065 0 : return ScResId(STR_ACC_DATAPILOT_COL_DESCR);
1066 : }
1067 :
1068 0 : void ScDPHorFieldControl::ScrollToEnd()
1069 : {
1070 0 : maScroll.DoScroll(maScroll.GetRangeMax());
1071 0 : }
1072 :
1073 0 : void ScDPHorFieldControl::ScrollToShowSelection()
1074 : {
1075 0 : size_t nLower = maScroll.GetThumbPos();
1076 0 : size_t nUpper = nLower + mnFieldBtnColCount - 1;
1077 0 : size_t nCol = GetSelectedField() / mnFieldBtnRowCount;
1078 0 : if (nCol < nLower)
1079 : {
1080 : // scroll to left.
1081 0 : maScroll.DoScroll(nCol);
1082 : }
1083 0 : else if (nUpper < nCol)
1084 : {
1085 : // scroll to right.
1086 0 : maScroll.DoScroll(nCol - mnFieldBtnColCount + 1);
1087 : }
1088 0 : }
1089 :
1090 0 : void ScDPHorFieldControl::ResetScrollBar()
1091 : {
1092 0 : long nOldMax = maScroll.GetRangeMax();
1093 : long nNewMax = static_cast<long>(ceil(
1094 0 : static_cast<double>(GetFieldCount()) / static_cast<double>(mnFieldBtnRowCount)));
1095 :
1096 0 : if (nOldMax != nNewMax)
1097 : {
1098 0 : maScroll.SetRangeMax(nNewMax);
1099 0 : bool bShow = mnFieldBtnColCount*mnFieldBtnRowCount < GetFieldCount();
1100 0 : maScroll.Show(bShow);
1101 : }
1102 0 : }
1103 :
1104 0 : void ScDPHorFieldControl::HandleWheelScroll(long /*nNotch*/)
1105 : {
1106 : // not handled for horizontal field controls.
1107 0 : }
1108 :
1109 0 : bool ScDPHorFieldControl::GetFieldBtnPosSize(size_t nPos, Point& rPos, Size& rSize)
1110 : {
1111 0 : if (nPos >= mnFieldBtnColCount*mnFieldBtnRowCount)
1112 0 : return false;
1113 :
1114 0 : Point aPos = Point(OUTER_MARGIN_HOR, OUTER_MARGIN_VER);
1115 0 : size_t nRow = nPos % mnFieldBtnRowCount;
1116 0 : size_t nCol = nPos / mnFieldBtnRowCount;
1117 :
1118 0 : aPos.X() += nCol*(GetFieldSize().Width() + ROW_FIELD_BTN_GAP);
1119 0 : aPos.Y() += nRow*(GetFieldSize().Height() + ROW_FIELD_BTN_GAP);
1120 :
1121 0 : rPos = aPos;
1122 0 : rSize = GetFieldSize();
1123 0 : return true;
1124 : }
1125 :
1126 0 : void ScDPHorFieldControl::HandleScroll()
1127 : {
1128 0 : Redraw();
1129 0 : }
1130 :
1131 0 : IMPL_LINK_NOARG(ScDPHorFieldControl, ScrollHdl)
1132 : {
1133 0 : HandleScroll();
1134 0 : return 0;
1135 : }
1136 :
1137 0 : IMPL_LINK_NOARG(ScDPHorFieldControl, EndScrollHdl)
1138 : {
1139 0 : HandleScroll();
1140 0 : return 0;
1141 : }
1142 :
1143 : //=============================================================================
1144 :
1145 0 : ScDPPageFieldControl::ScDPPageFieldControl(
1146 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1147 0 : ScDPHorFieldControl(pDialog, rResId, pCaption, pcHelpId)
1148 : {
1149 0 : }
1150 :
1151 0 : ScDPPageFieldControl::~ScDPPageFieldControl()
1152 : {
1153 0 : }
1154 :
1155 0 : ScPivotFieldType ScDPPageFieldControl::GetFieldType() const
1156 : {
1157 0 : return PIVOTFIELDTYPE_PAGE;
1158 : }
1159 :
1160 0 : String ScDPPageFieldControl::GetDescription() const
1161 : {
1162 0 : return ScResId(STR_ACC_DATAPILOT_PAGE_DESCR);
1163 : }
1164 :
1165 : //=============================================================================
1166 :
1167 0 : ScDPColFieldControl::ScDPColFieldControl(
1168 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1169 0 : ScDPHorFieldControl(pDialog, rResId, pCaption, pcHelpId)
1170 : {
1171 0 : }
1172 :
1173 0 : ScDPColFieldControl::~ScDPColFieldControl()
1174 : {
1175 0 : }
1176 :
1177 0 : ScPivotFieldType ScDPColFieldControl::GetFieldType() const
1178 : {
1179 0 : return PIVOTFIELDTYPE_COL;
1180 : }
1181 :
1182 0 : String ScDPColFieldControl::GetDescription() const
1183 : {
1184 0 : return ScResId(STR_ACC_DATAPILOT_COL_DESCR);
1185 : }
1186 :
1187 : //=============================================================================
1188 :
1189 0 : ScDPRowFieldControl::ScDPRowFieldControl(
1190 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1191 : ScDPFieldControlBase(pDialog, rResId, pCaption, pcHelpId),
1192 : maScroll(this, WB_VERT | WB_DRAG),
1193 0 : mnColumnBtnCount(0)
1194 : {
1195 0 : maScroll.SetScrollHdl( LINK(this, ScDPRowFieldControl, ScrollHdl) );
1196 0 : maScroll.SetEndScrollHdl( LINK(this, ScDPRowFieldControl, EndScrollHdl) );
1197 0 : maScroll.Show(false);
1198 :
1199 0 : AppendPaintable(&maScroll);
1200 0 : }
1201 :
1202 0 : ScDPRowFieldControl::~ScDPRowFieldControl()
1203 : {
1204 0 : }
1205 :
1206 : //-------------------------------------------------------------------
1207 :
1208 0 : Point ScDPRowFieldControl::GetFieldPosition(size_t nIndex)
1209 : {
1210 0 : Point aPos;
1211 0 : Size aSize;
1212 0 : GetFieldBtnPosSize(nIndex, aPos, aSize);
1213 0 : return aPos;
1214 : }
1215 :
1216 0 : Size ScDPRowFieldControl::GetFieldSize() const
1217 : {
1218 0 : return GetStdFieldBtnSize();
1219 : }
1220 :
1221 0 : size_t ScDPRowFieldControl::GetFieldIndex( const Point& rPos )
1222 : {
1223 0 : if (rPos.X() < 0 || rPos.Y() < 0)
1224 0 : return PIVOTFIELD_INVALID;
1225 :
1226 0 : long nFldH = GetFieldSize().Height();
1227 0 : long nThreshold = OUTER_MARGIN_VER + nFldH + ROW_FIELD_BTN_GAP / 2;
1228 :
1229 0 : size_t nIndex = 0;
1230 0 : for (; nIndex < mnColumnBtnCount; ++nIndex)
1231 : {
1232 0 : if (rPos.Y() < nThreshold)
1233 0 : break;
1234 :
1235 0 : nThreshold += nFldH + ROW_FIELD_BTN_GAP;
1236 : }
1237 :
1238 0 : if (nIndex >= mnColumnBtnCount)
1239 0 : nIndex = mnColumnBtnCount - 1;
1240 :
1241 0 : nIndex += maScroll.GetThumbPos();
1242 0 : return IsValidIndex(nIndex) ? nIndex : PIVOTFIELD_INVALID;
1243 : }
1244 :
1245 0 : void ScDPRowFieldControl::Redraw()
1246 : {
1247 0 : VirtualDevice aVirDev;
1248 : // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
1249 0 : aVirDev.EnableRTL( IsRTLEnabled() );
1250 0 : aVirDev.SetMapMode( MAP_PIXEL );
1251 :
1252 0 : Point aPos0;
1253 0 : Size aWndSize = GetSizePixel();
1254 0 : Font aFont = GetFont();
1255 0 : aFont.SetTransparent(true);
1256 0 : aVirDev.SetFont(aFont);
1257 0 : aVirDev.SetOutputSizePixel(aWndSize);
1258 :
1259 0 : DrawBackground(aVirDev);
1260 :
1261 0 : FieldNames& rFields = GetFieldNames();
1262 : {
1263 0 : long nScrollOffset = maScroll.GetThumbPos();
1264 0 : FieldNames::iterator itr = rFields.begin(), itrEnd = rFields.end();
1265 0 : if (nScrollOffset)
1266 0 : ::std::advance(itr, nScrollOffset);
1267 :
1268 0 : for (size_t i = 0; itr != itrEnd; ++itr, ++i)
1269 : {
1270 0 : Point aFldPt;
1271 0 : Size aFldSize;
1272 0 : if (!GetFieldBtnPosSize(i, aFldPt, aFldSize))
1273 : break;
1274 :
1275 0 : size_t nField = i + nScrollOffset;
1276 0 : bool bFocus = HasFocus() && (nField == GetSelectedField());
1277 0 : DrawField(aVirDev, Rectangle(aFldPt, aFldSize), *itr, bFocus);
1278 : }
1279 : }
1280 :
1281 : // Create a bitmap from the virtual device, and place that bitmap onto
1282 : // this control.
1283 0 : DrawBitmap(aPos0, aVirDev.GetBitmap(aPos0, aWndSize));
1284 :
1285 0 : DrawPaintables();
1286 0 : DrawInvertSelection();
1287 0 : UpdateStyle();
1288 0 : }
1289 :
1290 0 : void ScDPRowFieldControl::CalcSize()
1291 : {
1292 0 : Size aWndSize = GetSizePixel();
1293 :
1294 0 : long nTotal = aWndSize.Height() - OUTER_MARGIN_VER;
1295 0 : mnColumnBtnCount = nTotal / (GetFieldSize().Height() + ROW_FIELD_BTN_GAP);
1296 :
1297 0 : long nScrollSize = GetSettings().GetStyleSettings().GetScrollBarSize();
1298 :
1299 0 : maScroll.SetSizePixel(Size(nScrollSize, aWndSize.Height() - OUTER_MARGIN_VER*2));
1300 0 : maScroll.SetPosPixel(Point(aWndSize.Width() - nScrollSize - OUTER_MARGIN_HOR, OUTER_MARGIN_VER));
1301 0 : maScroll.SetLineSize(1);
1302 0 : maScroll.SetVisibleSize(mnColumnBtnCount);
1303 0 : maScroll.SetPageSize(mnColumnBtnCount);
1304 0 : maScroll.SetRange(Range(0, mnColumnBtnCount));
1305 0 : maScroll.DoScroll(0);
1306 :
1307 0 : }
1308 :
1309 0 : bool ScDPRowFieldControl::IsValidIndex(size_t /*nIndex*/) const
1310 : {
1311 : // This method is here in case we decide to impose an arbitrary upper
1312 : // boundary on the number of fields.
1313 0 : return true;
1314 : }
1315 :
1316 0 : size_t ScDPRowFieldControl::CalcNewFieldIndex(SCsCOL /*nDX*/, SCsROW nDY) const
1317 : {
1318 0 : size_t nNewField = GetSelectedField();
1319 0 : nNewField += nDY;
1320 0 : return IsExistingIndex(nNewField) ? nNewField : GetSelectedField();
1321 : }
1322 :
1323 0 : size_t ScDPRowFieldControl::GetDisplayPosition(size_t nIndex) const
1324 : {
1325 0 : size_t nLower = maScroll.GetThumbPos();
1326 0 : size_t nUpper = nLower + mnColumnBtnCount;
1327 0 : if (nLower <= nIndex && nIndex <= nUpper)
1328 0 : return nIndex - nLower;
1329 :
1330 0 : return INVALID_INDEX;
1331 : }
1332 :
1333 : //-------------------------------------------------------------------
1334 :
1335 0 : String ScDPRowFieldControl::GetDescription() const
1336 : {
1337 0 : return ScResId(STR_ACC_DATAPILOT_ROW_DESCR);
1338 : }
1339 :
1340 0 : ScPivotFieldType ScDPRowFieldControl::GetFieldType() const
1341 : {
1342 0 : return PIVOTFIELDTYPE_ROW;
1343 : }
1344 :
1345 0 : void ScDPRowFieldControl::ScrollToEnd()
1346 : {
1347 0 : maScroll.DoScroll(maScroll.GetRangeMax());
1348 0 : }
1349 :
1350 0 : void ScDPRowFieldControl::ScrollToShowSelection()
1351 : {
1352 0 : size_t nLower = maScroll.GetThumbPos();
1353 0 : size_t nUpper = nLower + mnColumnBtnCount - 1;
1354 0 : size_t nSel = GetSelectedField();
1355 0 : if (nSel < nLower)
1356 : {
1357 : // scroll up
1358 0 : maScroll.DoScroll(nSel);
1359 : }
1360 0 : else if (nUpper < nSel)
1361 : {
1362 : // scroll down
1363 0 : size_t nD = nSel - nUpper;
1364 0 : maScroll.DoScroll(nLower + nD);
1365 : }
1366 0 : }
1367 :
1368 0 : void ScDPRowFieldControl::ResetScrollBar()
1369 : {
1370 0 : long nOldMax = maScroll.GetRangeMax();
1371 0 : long nNewMax = std::max<long>(mnColumnBtnCount, GetFieldCount());
1372 :
1373 0 : if (nOldMax != nNewMax)
1374 : {
1375 0 : maScroll.SetRangeMax(nNewMax);
1376 0 : maScroll.Show(GetFieldCount() > mnColumnBtnCount);
1377 : }
1378 0 : }
1379 :
1380 0 : void ScDPRowFieldControl::HandleWheelScroll(long nNotch)
1381 : {
1382 0 : maScroll.DoScroll(maScroll.GetThumbPos() - nNotch);
1383 0 : }
1384 :
1385 0 : bool ScDPRowFieldControl::GetFieldBtnPosSize(size_t nPos, Point& rPos, Size& rSize)
1386 : {
1387 0 : if (nPos >= mnColumnBtnCount)
1388 0 : return false;
1389 :
1390 0 : size_t nOffset = maScroll.GetThumbPos();
1391 0 : if (nPos + nOffset >= GetFieldCount())
1392 0 : return false;
1393 :
1394 0 : rSize = GetFieldSize();
1395 0 : rPos = Point(OUTER_MARGIN_HOR, OUTER_MARGIN_VER);
1396 0 : rPos.Y() += nPos * (rSize.Height() + ROW_FIELD_BTN_GAP);
1397 0 : return true;
1398 : }
1399 :
1400 0 : void ScDPRowFieldControl::HandleScroll()
1401 : {
1402 0 : Redraw();
1403 0 : }
1404 :
1405 0 : IMPL_LINK_NOARG(ScDPRowFieldControl, ScrollHdl)
1406 : {
1407 0 : HandleScroll();
1408 0 : return 0;
1409 : }
1410 :
1411 0 : IMPL_LINK_NOARG(ScDPRowFieldControl, EndScrollHdl)
1412 : {
1413 0 : HandleScroll();
1414 0 : return 0;
1415 : }
1416 :
1417 : //=============================================================================
1418 :
1419 0 : ScDPSelectFieldControl::ScDPSelectFieldControl(
1420 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1421 0 : ScDPHorFieldControl(pDialog, rResId, pCaption, pcHelpId)
1422 : {
1423 0 : SetName(String(ScResId(STR_SELECT)));
1424 0 : }
1425 :
1426 0 : ScDPSelectFieldControl::~ScDPSelectFieldControl()
1427 : {
1428 0 : }
1429 :
1430 0 : ScPivotFieldType ScDPSelectFieldControl::GetFieldType() const
1431 : {
1432 0 : return PIVOTFIELDTYPE_SELECT;
1433 : }
1434 :
1435 0 : String ScDPSelectFieldControl::GetDescription() const
1436 : {
1437 0 : return ScResId(STR_ACC_DATAPILOT_SEL_DESCR);
1438 : }
1439 :
1440 : //=============================================================================
1441 :
1442 0 : ScDPDataFieldControl::ScDPDataFieldControl(
1443 : ScPivotLayoutDlg* pDialog, const ResId& rResId, FixedText* pCaption, const char* pcHelpId) :
1444 0 : ScDPHorFieldControl(pDialog, rResId, pCaption, pcHelpId)
1445 : {
1446 0 : }
1447 :
1448 0 : ScDPDataFieldControl::~ScDPDataFieldControl()
1449 : {
1450 0 : }
1451 :
1452 0 : ScPivotFieldType ScDPDataFieldControl::GetFieldType() const
1453 : {
1454 0 : return PIVOTFIELDTYPE_DATA;
1455 : }
1456 :
1457 0 : Size ScDPDataFieldControl::GetFieldSize() const
1458 : {
1459 0 : Size aWndSize = GetSizePixel();
1460 0 : long nFieldObjWidth = static_cast<long>(aWndSize.Width() / 2.0 - OUTER_MARGIN_HOR - DATA_FIELD_BTN_GAP/2);
1461 0 : Size aFieldSize(nFieldObjWidth, FIELD_BTN_HEIGHT);
1462 0 : return aFieldSize;
1463 : }
1464 :
1465 0 : String ScDPDataFieldControl::GetDescription() const
1466 : {
1467 0 : return ScResId(STR_ACC_DATAPILOT_DATA_DESCR);
1468 15 : }
1469 :
1470 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|