1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fieldwnd.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 #include <vcl/virdev.hxx>
37 #include <vcl/decoview.hxx>
38 #include <vcl/svapp.hxx>
40 #include <tools/debug.hxx>
42 #include "fieldwnd.hxx"
43 #include "pvlaydlg.hxx"
45 #include "AccessibleDataPilotControl.hxx"
46 #include "scresid.hxx"
50 #include <vcl/mnemonic.hxx>
52 const size_t INVALID_INDEX
= static_cast< size_t >( -1 );
54 //===================================================================
56 ScDPFieldWindow::ScDPFieldWindow(
57 ScDPLayoutDlg
* pDialog
,
59 ScDPFieldType eFieldType
,
60 FixedText
* pFtFieldCaption
) :
61 Control( pDialog
, rResId
),
63 pFtCaption( pFtFieldCaption
),
69 if (eType
!= TYPE_SELECT
&& pFtCaption
)
70 aName
= MnemonicGenerator::EraseAllMnemonicChars( pFtCaption
->GetText() );
73 ScDPFieldWindow::ScDPFieldWindow(
74 ScDPLayoutDlg
* pDialog
,
76 ScDPFieldType eFieldType
,
77 const String
& rName
) :
78 Control( pDialog
, rResId
),
89 void ScDPFieldWindow::Init()
91 aWndRect
= Rectangle( GetPosPixel(), GetSizePixel() );
92 nFieldSize
= (eType
== TYPE_SELECT
) ? PAGE_SIZE
: ((eType
== TYPE_PAGE
) ? MAX_PAGEFIELDS
: MAX_FIELDS
);
96 Size
aWinSize( aWndRect
.GetSize() );
97 Size
aTextSize( GetTextWidth( pFtCaption
->GetText() ), GetTextHeight() );
98 aTextPos
.X() = (aWinSize
.Width() - aTextSize
.Width()) / 2;
99 aTextPos
.Y() = (aWinSize
.Height() - aTextSize
.Height()) / 2;
105 __EXPORT
ScDPFieldWindow::~ScDPFieldWindow()
109 com::sun::star::uno::Reference
< com::sun::star::accessibility::XAccessible
> xTempAcc
= xAccessible
;
111 pAccessible
->dispose();
115 //-------------------------------------------------------------------
117 void ScDPFieldWindow::GetStyleSettings()
119 const StyleSettings
& rStyleSet
= GetSettings().GetStyleSettings();
120 aFaceColor
= rStyleSet
.GetFaceColor();
121 aWinColor
= rStyleSet
.GetWindowColor();
122 aTextColor
= rStyleSet
.GetButtonTextColor();
123 aWinTextColor
= rStyleSet
.GetWindowTextColor();
126 //-------------------------------------------------------------------
128 Point
ScDPFieldWindow::GetFieldPosition( size_t nIndex
) const
134 aPos
.X() = OWIDTH
* (nIndex
% (MAX_PAGEFIELDS
/ 2));
135 aPos
.Y() = OHEIGHT
* (nIndex
/ (MAX_PAGEFIELDS
/ 2));
138 aPos
.X() = OWIDTH
* (nIndex
% (MAX_FIELDS
/ 2));
139 aPos
.Y() = OHEIGHT
* (nIndex
/ (MAX_FIELDS
/ 2));
144 aPos
.Y() = OHEIGHT
* nIndex
;
147 aPos
.X() = (OWIDTH
+ SSPACE
) * (nIndex
/ LINE_SIZE
);
148 aPos
.Y() = (OHEIGHT
+ SSPACE
) * (nIndex
% LINE_SIZE
);
154 Size
ScDPFieldWindow::GetFieldSize() const
156 return Size( (eType
== TYPE_DATA
) ? GetSizePixel().Width() : OWIDTH
, OHEIGHT
);
159 Point
ScDPFieldWindow::GetLastPosition() const
161 return OutputToScreenPixel( GetFieldPosition( nFieldSize
- 1 ) );
164 bool ScDPFieldWindow::GetFieldIndex( const Point
& rPos
, size_t& rnIndex
) const
166 rnIndex
= INVALID_INDEX
;
167 if( (rPos
.X() >= 0) && (rPos
.Y() >= 0) )
173 rnIndex
= rPos
.Y() / OHEIGHT
;
177 size_t nRow
= rPos
.Y() / OHEIGHT
;
178 size_t nCol
= rPos
.X() / OWIDTH
;
179 rnIndex
= nRow
* MAX_PAGEFIELDS
/ 2 + nCol
;
184 size_t nRow
= rPos
.Y() / OHEIGHT
;
185 size_t nCol
= rPos
.X() / OWIDTH
;
186 rnIndex
= nRow
* MAX_FIELDS
/ 2 + nCol
;
191 size_t nRow
= rPos
.Y() / (OHEIGHT
+ SSPACE
);
192 size_t nCol
= rPos
.X() / (OWIDTH
+ SSPACE
);
193 // is not between controls?
194 if( (rPos
.Y() % (OHEIGHT
+ SSPACE
) < OHEIGHT
) && (rPos
.X() % (OWIDTH
+ SSPACE
) < OWIDTH
) )
195 rnIndex
= nCol
* LINE_SIZE
+ nRow
;
200 return IsValidIndex( rnIndex
);
203 //-------------------------------------------------------------------
205 void ScDPFieldWindow::DrawBackground( OutputDevice
& rDev
)
208 Size
aSize( GetSizePixel() );
210 if ( eType
== TYPE_SELECT
)
213 rDev
.SetFillColor( aFaceColor
);
214 rDev
.DrawRect( Rectangle( aPos0
, aSize
) );
218 rDev
.SetLineColor( aWinTextColor
);
219 rDev
.SetFillColor( aWinColor
);
220 rDev
.DrawRect( Rectangle( aPos0
, aSize
) );
222 rDev
.SetTextColor( aWinTextColor
);
224 /* Draw the caption text. This needs some special handling, because we
225 support hard line breaks here. This part will draw each line of the
228 xub_StrLen nTokenCnt
= GetText().GetTokenCount( '\n' );
229 long nY
= (aSize
.Height() - nTokenCnt
* rDev
.GetTextHeight()) / 2;
230 for( xub_StrLen nToken
= 0, nStringIx
= 0; nToken
< nTokenCnt
; ++nToken
)
232 String
aLine( GetText().GetToken( 0, '\n', nStringIx
) );
233 Point
aLinePos( (aSize
.Width() - rDev
.GetCtrlTextWidth( aLine
)) / 2, nY
);
234 rDev
.DrawCtrlText( aLinePos
, aLine
);
235 nY
+= rDev
.GetTextHeight();
240 void ScDPFieldWindow::DrawField(
241 OutputDevice
& rDev
, const Rectangle
& rRect
, const String
& rText
, bool bFocus
)
243 VirtualDevice
aVirDev( rDev
);
244 // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
245 aVirDev
.EnableRTL( IsRTLEnabled() );
247 Size
aDevSize( rRect
.GetSize() );
248 long nWidth
= aDevSize
.Width();
249 long nHeight
= aDevSize
.Height();
250 long nLabelWidth
= rDev
.GetTextWidth( rText
);
251 long nLabelHeight
= rDev
.GetTextHeight();
253 ((nWidth
> nLabelWidth
+ 6) ? (nWidth
- nLabelWidth
) / 2 : 3),
254 ((nHeight
> nLabelHeight
+ 6) ? (nHeight
- nLabelHeight
) / 2 : 3) );
256 aVirDev
.SetOutputSizePixel( aDevSize
);
257 aVirDev
.SetFont( rDev
.GetFont() );
258 DecorationView
aDecoView( &aVirDev
);
259 aDecoView
.DrawButton( Rectangle( Point( 0, 0 ), aDevSize
), bFocus
? BUTTON_DRAW_DEFAULT
: 0 );
260 aVirDev
.SetTextColor( aTextColor
);
261 aVirDev
.DrawText( aLabelPos
, rText
);
262 rDev
.DrawBitmap( rRect
.TopLeft(), aVirDev
.GetBitmap( Point( 0, 0 ), aDevSize
) );
265 void ScDPFieldWindow::Redraw()
267 VirtualDevice aVirDev
;
268 // #i97623# VirtualDevice is always LTR while other windows derive direction from parent
269 aVirDev
.EnableRTL( IsRTLEnabled() );
270 aVirDev
.SetMapMode( MAP_PIXEL
);
273 Size
aSize( GetSizePixel() );
274 Font
aFont( GetFont() ); // Font vom Window
275 aFont
.SetTransparent( TRUE
);
276 aVirDev
.SetFont( aFont
);
277 aVirDev
.SetOutputSizePixel( aSize
);
279 DrawBackground( aVirDev
);
281 if( !aFieldArr
.empty() && (nFieldSelected
>= aFieldArr
.size()) )
282 nFieldSelected
= aFieldArr
.size() - 1;
283 Rectangle
aFieldRect( aPos0
, GetFieldSize() );
284 for( size_t nIx
= 0; nIx
< aFieldArr
.size(); ++nIx
)
286 aFieldRect
.SetPos( GetFieldPosition( nIx
) );
287 bool bFocus
= HasFocus() && (nIx
== nFieldSelected
);
288 DrawField( aVirDev
, aFieldRect
, aFieldArr
[ nIx
], bFocus
);
290 DrawBitmap( aPos0
, aVirDev
.GetBitmap( aPos0
, aSize
) );
292 if( HasFocus() && (nFieldSelected
< aFieldArr
.size()) )
294 long nFieldWidth
= aFieldRect
.GetWidth();
295 long nSelectionWidth
= Min( GetTextWidth( aFieldArr
[ nFieldSelected
] ) + 4, nFieldWidth
- 6 );
296 Rectangle
aSelection(
297 GetFieldPosition( nFieldSelected
) + Point( (nFieldWidth
- nSelectionWidth
) / 2, 3 ),
298 Size( nSelectionWidth
, aFieldRect
.GetHeight() - 6 ) );
299 InvertTracking( aSelection
, SHOWTRACK_SMALL
| SHOWTRACK_WINDOW
);
305 void ScDPFieldWindow::UpdateStyle()
307 WinBits nMask
= ~(WB_TABSTOP
| WB_NOTABSTOP
);
308 SetStyle( (GetStyle() & nMask
) | (IsEmpty() ? WB_NOTABSTOP
: WB_TABSTOP
) );
311 //-------------------------------------------------------------------
313 bool ScDPFieldWindow::IsValidIndex( size_t nIndex
) const
315 return nIndex
< nFieldSize
;
318 bool ScDPFieldWindow::IsExistingIndex( size_t nIndex
) const
320 return nIndex
< aFieldArr
.size();
323 size_t ScDPFieldWindow::CalcNewFieldIndex( SCsCOL nDX
, SCsROW nDY
) const
325 size_t nNewField
= nFieldSelected
;
329 nNewField
+= static_cast<SCsCOLROW
>(nDX
) + nDY
* MAX_PAGEFIELDS
/ 2;
332 nNewField
+= static_cast<SCsCOLROW
>(nDX
) + nDY
* MAX_FIELDS
/ 2;
339 nNewField
+= static_cast<SCsCOLROW
>(nDX
) * LINE_SIZE
+ nDY
;
343 return IsExistingIndex( nNewField
) ? nNewField
: nFieldSelected
;
346 void ScDPFieldWindow::SetSelection( size_t nIndex
)
348 if( !aFieldArr
.empty() )
350 if( nFieldSelected
>= aFieldArr
.size() )
351 nFieldSelected
= aFieldArr
.size() - 1;
352 if( nFieldSelected
!= nIndex
)
354 sal_Int32
nOldSelected(nFieldSelected
);
355 nFieldSelected
= nIndex
;
358 if (pAccessible
&& HasFocus())
360 com::sun::star::uno::Reference
< com::sun::star::accessibility::XAccessible
> xTempAcc
= xAccessible
;
362 pAccessible
->FieldFocusChange(nOldSelected
, nFieldSelected
);
370 void ScDPFieldWindow::SetSelectionHome()
372 if( !aFieldArr
.empty() )
374 if( eType
== TYPE_SELECT
)
375 pDlg
->NotifyMoveSlider( KEY_HOME
);
380 void ScDPFieldWindow::SetSelectionEnd()
382 if( !aFieldArr
.empty() )
384 if( eType
== TYPE_SELECT
)
385 pDlg
->NotifyMoveSlider( KEY_END
);
386 SetSelection( aFieldArr
.size() - 1 );
390 void ScDPFieldWindow::MoveSelection( USHORT nKeyCode
, SCsCOL nDX
, SCsROW nDY
)
392 size_t nNewIndex
= CalcNewFieldIndex( nDX
, nDY
);
393 if( (eType
== TYPE_SELECT
) && (nNewIndex
== nFieldSelected
) )
395 if( pDlg
->NotifyMoveSlider( nKeyCode
) )
399 case KEY_UP
: nNewIndex
+= (LINE_SIZE
- 1); break;
400 case KEY_DOWN
: nNewIndex
-= (LINE_SIZE
- 1); break;
404 SetSelection( nNewIndex
);
407 void ScDPFieldWindow::ModifySelectionOffset( long nOffsetDiff
)
409 nFieldSelected
-= nOffsetDiff
;
413 void ScDPFieldWindow::SelectNext()
415 if( eType
== TYPE_SELECT
)
416 MoveSelection( KEY_DOWN
, 0, 1 );
419 void ScDPFieldWindow::GrabFocusWithSel( size_t nIndex
)
421 SetSelection( nIndex
);
426 void ScDPFieldWindow::MoveField( size_t nDestIndex
)
428 if( nDestIndex
!= nFieldSelected
)
430 // "recycle" existing functionality
431 pDlg
->NotifyMouseButtonDown( eType
, nFieldSelected
);
432 pDlg
->NotifyMouseButtonUp( OutputToScreenPixel( GetFieldPosition( nDestIndex
) ) );
436 void ScDPFieldWindow::MoveFieldRel( SCsCOL nDX
, SCsROW nDY
)
438 MoveField( CalcNewFieldIndex( nDX
, nDY
) );
441 //-------------------------------------------------------------------
443 void __EXPORT
ScDPFieldWindow::Paint( const Rectangle
& /* rRect */ )
445 // #124828# hiding the caption is now done from StateChanged
449 void ScDPFieldWindow::UseMnemonic()
451 // Now the FixedText has its mnemonic char. Grab the text and hide the
452 // FixedText to be able to handle tabstop and mnemonics separately.
455 SetText( pFtCaption
->GetText() );
459 // after reading the mnemonics, tab stop style bits can be updated
463 void __EXPORT
ScDPFieldWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
465 if( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) && (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
470 Control::DataChanged( rDCEvt
);
473 void __EXPORT
ScDPFieldWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
478 if( GetFieldIndex( rMEvt
.GetPosPixel(), nIndex
) && IsExistingIndex( nIndex
) )
480 GrabFocusWithSel( nIndex
);
482 if( rMEvt
.GetClicks() == 1 )
484 PointerStyle ePtr
= pDlg
->NotifyMouseButtonDown( eType
, nIndex
);
486 SetPointer( Pointer( ePtr
) );
489 pDlg
->NotifyDoubleClick( eType
, nIndex
);
494 void __EXPORT
ScDPFieldWindow::MouseButtonUp( const MouseEvent
& rMEvt
)
498 if( rMEvt
.GetClicks() == 1 )
500 pDlg
->NotifyMouseButtonUp( OutputToScreenPixel( rMEvt
.GetPosPixel() ) );
501 SetPointer( Pointer( POINTER_ARROW
) );
504 if( IsMouseCaptured() )
509 void __EXPORT
ScDPFieldWindow::MouseMove( const MouseEvent
& rMEvt
)
511 if( IsMouseCaptured() )
513 PointerStyle ePtr
= pDlg
->NotifyMouseMove( OutputToScreenPixel( rMEvt
.GetPosPixel() ) );
514 SetPointer( Pointer( ePtr
) );
518 void __EXPORT
ScDPFieldWindow::KeyInput( const KeyEvent
& rKEvt
)
520 const KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
521 USHORT nCode
= rKeyCode
.GetCode();
522 BOOL bKeyEvaluated
= FALSE
;
524 if( rKeyCode
.IsMod1() && (eType
!= TYPE_SELECT
) )
526 bKeyEvaluated
= TRUE
;
529 case KEY_UP
: MoveFieldRel( 0, -1 ); break;
530 case KEY_DOWN
: MoveFieldRel( 0, 1 ); break;
531 case KEY_LEFT
: MoveFieldRel( -1, 0 ); break;
532 case KEY_RIGHT
: MoveFieldRel( 1, 0 ); break;
533 case KEY_HOME
: MoveField( 0 ); break;
534 case KEY_END
: MoveField( aFieldArr
.size() - 1 ); break;
535 default: bKeyEvaluated
= FALSE
;
540 bKeyEvaluated
= TRUE
;
543 case KEY_UP
: MoveSelection( nCode
, 0, -1 ); break;
544 case KEY_DOWN
: MoveSelection( nCode
, 0, 1 ); break;
545 case KEY_LEFT
: MoveSelection( nCode
, -1, 0 ); break;
546 case KEY_RIGHT
: MoveSelection( nCode
, 1, 0 ); break;
547 case KEY_HOME
: SetSelectionHome(); break;
548 case KEY_END
: SetSelectionEnd(); break;
550 pDlg
->NotifyRemoveField( eType
, nFieldSelected
); break;
551 default: bKeyEvaluated
= FALSE
;
556 Control::KeyInput( rKEvt
);
559 void __EXPORT
ScDPFieldWindow::GetFocus()
563 if( GetGetFocusFlags() & GETFOCUS_MNEMONIC
) // move field on shortcut
564 pDlg
->NotifyMoveField( eType
);
565 else // else change focus
566 pDlg
->NotifyFieldFocus( eType
, TRUE
);
570 com::sun::star::uno::Reference
< com::sun::star::accessibility::XAccessible
> xTempAcc
= xAccessible
;
572 pAccessible
->GotFocus();
578 void __EXPORT
ScDPFieldWindow::LoseFocus()
580 Control::LoseFocus();
582 pDlg
->NotifyFieldFocus( eType
, FALSE
);
586 com::sun::star::uno::Reference
< com::sun::star::accessibility::XAccessible
> xTempAcc
= xAccessible
;
588 pAccessible
->LostFocus();
594 //-------------------------------------------------------------------
596 void ScDPFieldWindow::AddField( const String
& rText
, size_t nNewIndex
)
598 DBG_ASSERT( nNewIndex
== aFieldArr
.size(), "ScDPFieldWindow::AddField - invalid index" );
599 if( IsValidIndex( nNewIndex
) )
601 aFieldArr
.push_back( rText
);
604 com::sun::star::uno::Reference
< com::sun::star::accessibility::XAccessible
> xTempAcc
= xAccessible
;
606 pAccessible
->AddField(nNewIndex
);
613 void ScDPFieldWindow::DelField( size_t nDelIndex
)
615 if( IsExistingIndex( nDelIndex
) )
617 if (pAccessible
) // before decrement fieldcount
619 com::sun::star::uno::Reference
< com::sun::star::accessibility::XAccessible
> xTempAcc
= xAccessible
;
621 pAccessible
->RemoveField(nDelIndex
);
625 aFieldArr
.erase( aFieldArr
.begin() + nDelIndex
);
630 void ScDPFieldWindow::ClearFields()
632 if( eType
== TYPE_SELECT
|| eType
== TYPE_PAGE
|| eType
== TYPE_COL
|| eType
== TYPE_ROW
|| eType
== TYPE_DATA
)
634 com::sun::star::uno::Reference
< com::sun::star::accessibility::XAccessible
> xTempAcc
= xAccessible
;
635 if (!xTempAcc
.is() && pAccessible
)
638 for( size_t nIdx
= aFieldArr
.size(); nIdx
> 0; --nIdx
)
639 pAccessible
->RemoveField( nIdx
- 1 );
645 void ScDPFieldWindow::SetFieldText( const String
& rText
, size_t nIndex
)
647 if( IsExistingIndex( nIndex
) )
649 aFieldArr
[ nIndex
] = rText
;
654 com::sun::star::uno::Reference
< com::sun::star::accessibility::XAccessible
> xTempAcc
= xAccessible
;
656 pAccessible
->FieldNameChange(nIndex
);
663 const String
& ScDPFieldWindow::GetFieldText( size_t nIndex
) const
665 if( IsExistingIndex( nIndex
) )
666 return aFieldArr
[ nIndex
];
670 //-------------------------------------------------------------------
672 bool ScDPFieldWindow::AddField( const String
& rText
, const Point
& rPos
, size_t& rnIndex
)
674 if ( aFieldArr
.size() == nFieldSize
)
677 size_t nNewIndex
= 0;
678 if( GetFieldIndex( rPos
, nNewIndex
) )
680 if( nNewIndex
> aFieldArr
.size() )
681 nNewIndex
= aFieldArr
.size();
683 aFieldArr
.insert( aFieldArr
.begin() + nNewIndex
, rText
);
684 nFieldSelected
= nNewIndex
;
690 com::sun::star::uno::Reference
< com::sun::star::accessibility::XAccessible
> xTempAcc
= xAccessible
;
692 pAccessible
->AddField(nNewIndex
);
703 void ScDPFieldWindow::GetExistingIndex( const Point
& rPos
, size_t& rnIndex
)
705 if( !aFieldArr
.empty() && (eType
!= TYPE_SELECT
) && GetFieldIndex( rPos
, rnIndex
) )
707 if( rnIndex
>= aFieldArr
.size() )
708 rnIndex
= aFieldArr
.size() - 1;
714 String
ScDPFieldWindow::GetDescription() const
720 sDescription
= ScResId(STR_ACC_DATAPILOT_COL_DESCR
);
723 sDescription
= ScResId(STR_ACC_DATAPILOT_ROW_DESCR
);
726 sDescription
= ScResId(STR_ACC_DATAPILOT_DATA_DESCR
);
729 sDescription
= ScResId(STR_ACC_DATAPILOT_SEL_DESCR
);
733 // added to avoid warnings
739 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> ScDPFieldWindow::CreateAccessible()
742 new ScAccessibleDataPilotControl(GetAccessibleParentWindow()->GetAccessible(), this);
744 com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> xReturn
= pAccessible
;
747 xAccessible
= xReturn
;
752 //===================================================================