merge the formfield patch from ooo-build
[ooovba.git] / svx / source / dialog / dialcontrol.cxx
blob001bcb04b8b94505981c4f53315a45d8015a5795
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dialcontrol.cxx,v $
10 * $Revision: 1.7 $
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_svx.hxx"
33 #include "dialcontrol.hxx"
35 #include <math.h>
36 #include <vcl/virdev.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/bitmap.hxx>
39 #include <vcl/field.hxx>
40 #include <svtools/colorcfg.hxx>
42 namespace svx {
44 // ============================================================================
46 const long DIAL_OUTER_WIDTH = 8;
48 // ============================================================================
50 class DialControlBmp : public VirtualDevice
52 public:
53 explicit DialControlBmp( Window& rParent );
55 void InitBitmap( const Size& rSize, const Font& rFont );
56 void CopyBackground( const DialControlBmp& rSrc );
57 void DrawBackground( const Size& rSize, bool bEnabled );
58 void DrawElements( const String& rText, sal_Int32 nAngle );
60 private:
61 const Color& GetBackgroundColor() const;
62 const Color& GetTextColor() const;
63 const Color& GetScaleLineColor() const;
64 const Color& GetButtonLineColor() const;
65 const Color& GetButtonFillColor( bool bMain ) const;
67 void Init( const Size& rSize );
68 void DrawBackground();
70 Window& mrParent;
71 Rectangle maRect;
72 long mnCenterX;
73 long mnCenterY;
74 bool mbEnabled;
77 // ----------------------------------------------------------------------------
79 DialControlBmp::DialControlBmp( Window& rParent ) :
80 VirtualDevice( rParent, 0, 0 ),
81 mrParent( rParent ),
82 mbEnabled( true )
84 EnableRTL( FALSE );
87 void DialControlBmp::InitBitmap( const Size& rSize, const Font& rFont )
89 Init( rSize );
90 SetFont( rFont );
93 void DialControlBmp::CopyBackground( const DialControlBmp& rSrc )
95 Init( rSrc.maRect.GetSize() );
96 mbEnabled = rSrc.mbEnabled;
97 Point aPos;
98 DrawBitmapEx( aPos, rSrc.GetBitmapEx( aPos, maRect.GetSize() ) );
101 void DialControlBmp::DrawBackground( const Size& rSize, bool bEnabled )
103 Init( rSize );
104 mbEnabled = bEnabled;
105 DrawBackground();
108 void DialControlBmp::DrawElements( const String& rText, sal_Int32 nAngle )
110 // *** rotated text ***
112 Font aFont( GetFont() );
113 aFont.SetColor( GetTextColor() );
114 aFont.SetOrientation( static_cast< short >( (nAngle + 5) / 10 ) ); // Font uses 1/10 degrees
115 aFont.SetWeight( WEIGHT_BOLD );
116 SetFont( aFont );
118 double fAngle = nAngle * F_PI180 / 100.0;
119 double fSin = sin( fAngle );
120 double fCos = cos( fAngle );
121 double fWidth = GetTextWidth( rText ) / 2.0;
122 double fHeight = GetTextHeight() / 2.0;
123 long nX = static_cast< long >( mnCenterX - fWidth * fCos - fHeight * fSin );
124 long nY = static_cast< long >( mnCenterY + fWidth * fSin - fHeight * fCos );
125 Rectangle aRect( nX, nY, 2 * mnCenterX - nX, 2 * mnCenterY - nY );
126 DrawText( aRect, rText, mbEnabled ? 0 : TEXT_DRAW_DISABLE );
128 // *** drag button ***
130 bool bMain = (nAngle % 4500) != 0;
131 SetLineColor( GetButtonLineColor() );
132 SetFillColor( GetButtonFillColor( bMain ) );
134 nX = mnCenterX - static_cast< long >( (DIAL_OUTER_WIDTH / 2 - mnCenterX) * fCos );
135 nY = mnCenterY - static_cast< long >( (mnCenterY - DIAL_OUTER_WIDTH / 2) * fSin );
136 long nSize = bMain ? (DIAL_OUTER_WIDTH / 4) : (DIAL_OUTER_WIDTH / 2 - 1);
137 DrawEllipse( Rectangle( nX - nSize, nY - nSize, nX + nSize, nY + nSize ) );
140 // private --------------------------------------------------------------------
142 const Color& DialControlBmp::GetBackgroundColor() const
144 return GetSettings().GetStyleSettings().GetDialogColor();
147 const Color& DialControlBmp::GetTextColor() const
149 return GetSettings().GetStyleSettings().GetLabelTextColor();
152 const Color& DialControlBmp::GetScaleLineColor() const
154 const StyleSettings& rSett = GetSettings().GetStyleSettings();
155 return mbEnabled ? rSett.GetButtonTextColor() : rSett.GetDisableColor();
158 const Color& DialControlBmp::GetButtonLineColor() const
160 const StyleSettings& rSett = GetSettings().GetStyleSettings();
161 return mbEnabled ? rSett.GetButtonTextColor() : rSett.GetDisableColor();
164 const Color& DialControlBmp::GetButtonFillColor( bool bMain ) const
166 const StyleSettings& rSett = GetSettings().GetStyleSettings();
167 return mbEnabled ? (bMain ? rSett.GetMenuColor() : rSett.GetHighlightColor()) : rSett.GetDisableColor();
170 void DialControlBmp::Init( const Size& rSize )
172 SetSettings( mrParent.GetSettings() );
173 maRect.SetPos( Point( 0, 0 ) );
174 maRect.SetSize( rSize );
175 mnCenterX = rSize.Width() / 2;
176 mnCenterY = rSize.Height() / 2;
177 SetOutputSize( rSize );
178 SetBackground();
181 void DialControlBmp::DrawBackground()
183 // *** background with 3D effect ***
185 SetLineColor();
186 SetFillColor();
187 Erase();
189 EnableRTL( TRUE ); // #107807# draw 3D effect in correct direction
191 sal_uInt8 nDiff = mbEnabled ? 0x18 : 0x10;
192 Color aColor;
194 aColor = GetBackgroundColor();
195 SetFillColor( aColor );
196 DrawPie( maRect, maRect.TopRight(), maRect.TopCenter() );
197 DrawPie( maRect, maRect.BottomLeft(), maRect.BottomCenter() );
199 aColor.DecreaseLuminance( nDiff );
200 SetFillColor( aColor );
201 DrawPie( maRect, maRect.BottomCenter(), maRect.TopRight() );
203 aColor.DecreaseLuminance( nDiff );
204 SetFillColor( aColor );
205 DrawPie( maRect, maRect.BottomRight(), maRect.RightCenter() );
207 aColor = GetBackgroundColor();
208 aColor.IncreaseLuminance( nDiff );
209 SetFillColor( aColor );
210 DrawPie( maRect, maRect.TopCenter(), maRect.BottomLeft() );
212 aColor.IncreaseLuminance( nDiff );
213 SetFillColor( aColor );
214 DrawPie( maRect, maRect.TopLeft(), maRect.LeftCenter() );
216 EnableRTL( FALSE );
218 // *** calibration ***
220 Point aStartPos( mnCenterX, mnCenterY );
221 Color aFullColor( GetScaleLineColor() );
222 Color aLightColor( GetBackgroundColor() );
223 aLightColor.Merge( aFullColor, 128 );
225 for( int nAngle = 0; nAngle < 360; nAngle += 15 )
227 SetLineColor( (nAngle % 45) ? aLightColor : aFullColor );
228 double fAngle = nAngle * F_PI180;
229 long nX = static_cast< long >( -mnCenterX * cos( fAngle ) );
230 long nY = static_cast< long >( mnCenterY * sin( fAngle ) );
231 DrawLine( aStartPos, Point( mnCenterX - nX, mnCenterY - nY ) );
234 // *** clear inner area ***
236 SetLineColor();
237 SetFillColor( GetBackgroundColor() );
238 DrawEllipse( Rectangle( maRect.Left() + DIAL_OUTER_WIDTH, maRect.Top() + DIAL_OUTER_WIDTH,
239 maRect.Right() - DIAL_OUTER_WIDTH, maRect.Bottom() - DIAL_OUTER_WIDTH ) );
242 // ============================================================================
244 struct DialControl_Impl
246 DialControlBmp maBmpEnabled;
247 DialControlBmp maBmpDisabled;
248 DialControlBmp maBmpBuffered;
249 Link maModifyHdl;
250 NumericField* mpLinkField;
251 Size maWinSize;
252 Font maWinFont;
253 sal_Int32 mnAngle;
254 sal_Int32 mnOldAngle;
255 long mnCenterX;
256 long mnCenterY;
257 bool mbNoRot;
259 explicit DialControl_Impl( Window& rParent );
260 void Init( const Size& rWinSize, const Font& rWinFont );
263 // ----------------------------------------------------------------------------
265 DialControl_Impl::DialControl_Impl( Window& rParent ) :
266 maBmpEnabled( rParent ),
267 maBmpDisabled( rParent ),
268 maBmpBuffered( rParent ),
269 mpLinkField( 0 ),
270 mnAngle( 0 ),
271 mbNoRot( false )
275 void DialControl_Impl::Init( const Size& rWinSize, const Font& rWinFont )
277 // "(x - 1) | 1" creates odd value <= x, to have a well-defined center pixel position
278 maWinSize = Size( (rWinSize.Width() - 1) | 1, (rWinSize.Height() - 1) | 1 );
279 maWinFont = rWinFont;
281 mnCenterX = maWinSize.Width() / 2;
282 mnCenterY = maWinSize.Height() / 2;
283 maWinFont.SetTransparent( TRUE );
285 maBmpEnabled.DrawBackground( maWinSize, true );
286 maBmpDisabled.DrawBackground( maWinSize, false );
287 maBmpBuffered.InitBitmap( maWinSize, maWinFont );
290 // ============================================================================
292 DialControl::DialControl( Window* pParent, const Size& rSize, const Font& rFont, WinBits nWinStyle ) :
293 Control( pParent, nWinStyle ),
294 mpImpl( new DialControl_Impl( *this ) )
296 Init( rSize, rFont );
299 DialControl::DialControl( Window* pParent, const Size& rSize, WinBits nWinStyle ) :
300 Control( pParent, nWinStyle ),
301 mpImpl( new DialControl_Impl( *this ) )
303 if( pParent )
304 Init( rSize, pParent->GetFont() );
305 else
306 Init( rSize );
309 DialControl::DialControl( Window* pParent, const ResId& rResId ) :
310 Control( pParent, rResId ),
311 mpImpl( new DialControl_Impl( *this ) )
313 Init( GetOutputSizePixel() );
316 DialControl::~DialControl()
320 void DialControl::Paint( const Rectangle& )
322 Point aPos;
323 DrawBitmapEx( aPos, mpImpl->maBmpBuffered.GetBitmapEx( aPos, mpImpl->maWinSize ) );
326 void DialControl::StateChanged( StateChangedType nStateChange )
328 if( nStateChange == STATE_CHANGE_ENABLE )
329 InvalidateControl();
331 // update the linked edit field
332 if( mpImpl->mpLinkField )
334 NumericField& rField = *mpImpl->mpLinkField;
335 switch( nStateChange )
337 case STATE_CHANGE_VISIBLE: rField.Show( IsVisible() ); break;
338 case STATE_CHANGE_ENABLE: rField.Enable( IsEnabled() ); break;
342 Control::StateChanged( nStateChange );
345 void DialControl::DataChanged( const DataChangedEvent& rDCEvt )
347 if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
349 Init( mpImpl->maWinSize, mpImpl->maWinFont );
350 InvalidateControl();
352 Control::DataChanged( rDCEvt );
355 void DialControl::MouseButtonDown( const MouseEvent& rMEvt )
357 if( rMEvt.IsLeft() )
359 GrabFocus();
360 CaptureMouse();
361 mpImpl->mnOldAngle = mpImpl->mnAngle;
362 HandleMouseEvent( rMEvt.GetPosPixel(), true );
364 Control::MouseButtonDown( rMEvt );
367 void DialControl::MouseMove( const MouseEvent& rMEvt )
369 if( IsMouseCaptured() && rMEvt.IsLeft() )
370 HandleMouseEvent( rMEvt.GetPosPixel(), false );
371 Control::MouseMove(rMEvt );
374 void DialControl::MouseButtonUp( const MouseEvent& rMEvt )
376 if( IsMouseCaptured() )
378 ReleaseMouse();
379 if( mpImpl->mpLinkField )
380 mpImpl->mpLinkField->GrabFocus();
382 Control::MouseButtonUp( rMEvt );
385 void DialControl::KeyInput( const KeyEvent& rKEvt )
387 const KeyCode& rKCode = rKEvt.GetKeyCode();
388 if( !rKCode.GetModifier() && (rKCode.GetCode() == KEY_ESCAPE) )
389 HandleEscapeEvent();
390 else
391 Control::KeyInput( rKEvt );
394 void DialControl::LoseFocus()
396 // release captured mouse
397 HandleEscapeEvent();
398 Control::LoseFocus();
401 bool DialControl::HasRotation() const
403 return !mpImpl->mbNoRot;
406 void DialControl::SetNoRotation()
408 if( !mpImpl->mbNoRot )
410 mpImpl->mbNoRot = true;
411 InvalidateControl();
412 if( mpImpl->mpLinkField )
413 mpImpl->mpLinkField->SetText( String() );
417 sal_Int32 DialControl::GetRotation() const
419 return mpImpl->mnAngle;
422 void DialControl::SetRotation( sal_Int32 nAngle )
424 ImplSetRotation( nAngle, false );
427 void DialControl::SetLinkedField( NumericField* pField )
429 // remove modify handler from old linked field
430 ImplSetFieldLink( Link() );
431 // remember the new linked field
432 mpImpl->mpLinkField = pField;
433 // set modify handler at new linked field
434 ImplSetFieldLink( LINK( this, DialControl, LinkedFieldModifyHdl ) );
437 NumericField* DialControl::GetLinkedField() const
439 return mpImpl->mpLinkField;
442 void DialControl::SetModifyHdl( const Link& rLink )
444 mpImpl->maModifyHdl = rLink;
447 const Link& DialControl::GetModifyHdl() const
449 return mpImpl->maModifyHdl;
452 // private --------------------------------------------------------------------
454 void DialControl::Init( const Size& rWinSize, const Font& rWinFont )
456 mpImpl->Init( rWinSize, rWinFont );
457 EnableRTL( FALSE ); // #107807# don't mirror mouse handling
458 SetOutputSizePixel( mpImpl->maWinSize );
459 SetBackground();
462 void DialControl::Init( const Size& rWinSize )
464 Font aFont( OutputDevice::GetDefaultFont(
465 DEFAULTFONT_UI_SANS, Application::GetSettings().GetUILanguage(), DEFAULTFONT_FLAGS_ONLYONE ) );
466 Init( rWinSize, aFont );
469 void DialControl::InvalidateControl()
471 mpImpl->maBmpBuffered.CopyBackground( IsEnabled() ? mpImpl->maBmpEnabled : mpImpl->maBmpDisabled );
472 if( !mpImpl->mbNoRot )
473 mpImpl->maBmpBuffered.DrawElements( GetText(), mpImpl->mnAngle );
474 Invalidate();
477 void DialControl::ImplSetRotation( sal_Int32 nAngle, bool bBroadcast )
479 bool bOldSel = mpImpl->mbNoRot;
480 mpImpl->mbNoRot = false;
482 while( nAngle < 0 ) nAngle += 36000;
483 nAngle = (((nAngle + 50) / 100) * 100) % 36000;
484 if( !bOldSel || (mpImpl->mnAngle != nAngle) )
486 mpImpl->mnAngle = nAngle;
487 InvalidateControl();
488 if( mpImpl->mpLinkField )
489 mpImpl->mpLinkField->SetValue( static_cast< long >( GetRotation() / 100 ) );
490 if( bBroadcast )
491 mpImpl->maModifyHdl.Call( this );
495 void DialControl::ImplSetFieldLink( const Link& rLink )
497 if( mpImpl->mpLinkField )
499 NumericField& rField = *mpImpl->mpLinkField;
500 rField.SetModifyHdl( rLink );
501 rField.SetUpHdl( rLink );
502 rField.SetDownHdl( rLink );
503 rField.SetFirstHdl( rLink );
504 rField.SetLastHdl( rLink );
505 rField.SetLoseFocusHdl( rLink );
509 void DialControl::HandleMouseEvent( const Point& rPos, bool bInitial )
511 long nX = rPos.X() - mpImpl->mnCenterX;
512 long nY = mpImpl->mnCenterY - rPos.Y();
513 double fH = sqrt( static_cast< double >( nX ) * nX + static_cast< double >( nY ) * nY );
514 if( fH != 0.0 )
516 double fAngle = acos( nX / fH );
517 sal_Int32 nAngle = static_cast< sal_Int32 >( fAngle / F_PI180 * 100.0 );
518 if( nY < 0 )
519 nAngle = 36000 - nAngle;
520 if( bInitial ) // round to entire 15 degrees
521 nAngle = ((nAngle + 750) / 1500) * 1500;
522 ImplSetRotation( nAngle, true );
526 void DialControl::HandleEscapeEvent()
528 if( IsMouseCaptured() )
530 ReleaseMouse();
531 ImplSetRotation( mpImpl->mnOldAngle, true );
532 if( mpImpl->mpLinkField )
533 mpImpl->mpLinkField->GrabFocus();
537 IMPL_LINK( DialControl, LinkedFieldModifyHdl, NumericField*, pField )
539 if( pField )
540 ImplSetRotation( static_cast< sal_Int32 >( pField->GetValue() * 100 ), false );
541 return 0;
544 // ============================================================================
546 DialControlWrapper::DialControlWrapper( DialControl& rDial ) :
547 SingleControlWrapperType( rDial )
551 bool DialControlWrapper::IsControlDontKnow() const
553 return !GetControl().HasRotation();
556 void DialControlWrapper::SetControlDontKnow( bool bSet )
558 if( bSet )
559 GetControl().SetNoRotation();
562 sal_Int32 DialControlWrapper::GetControlValue() const
564 return GetControl().GetRotation();
567 void DialControlWrapper::SetControlValue( sal_Int32 nValue )
569 GetControl().SetRotation( nValue );
572 // ============================================================================
574 } // namespace svx