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: ctrl.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_vcl.hxx"
37 #include <vcl/svdata.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/event.hxx>
40 #include <vcl/ctrl.hxx>
41 #include <vcl/decoview.hxx>
42 #include <vcl/controllayout.hxx>
43 #include <vcl/salnativewidgets.hxx>
49 // =======================================================================
51 void Control::ImplInitControlData()
57 // -----------------------------------------------------------------------
59 Control::Control( WindowType nType
) :
62 ImplInitControlData();
65 // -----------------------------------------------------------------------
67 Control::Control( Window
* pParent
, WinBits nStyle
) :
68 Window( WINDOW_CONTROL
)
70 ImplInitControlData();
71 Window::ImplInit( pParent
, nStyle
, NULL
);
74 // -----------------------------------------------------------------------
76 Control::Control( Window
* pParent
, const ResId
& rResId
) :
77 Window( WINDOW_CONTROL
)
79 ImplInitControlData();
80 rResId
.SetRT( RSC_CONTROL
);
81 WinBits nStyle
= ImplInitRes( rResId
);
82 ImplInit( pParent
, nStyle
, NULL
);
83 ImplLoadRes( rResId
);
85 if ( !(nStyle
& WB_HIDE
) )
89 // -----------------------------------------------------------------------
93 delete mpLayoutData
, mpLayoutData
= NULL
;
96 // -----------------------------------------------------------------------
98 void Control::GetFocus()
103 // -----------------------------------------------------------------------
105 void Control::LoseFocus()
110 // -----------------------------------------------------------------------
112 void Control::Resize()
114 delete mpLayoutData
, mpLayoutData
= NULL
;
118 // -----------------------------------------------------------------------
120 void Control::FillLayoutData() const
124 // -----------------------------------------------------------------------
126 void Control::SetText( const String
& rStr
)
130 Window::SetText( rStr
);
133 // -----------------------------------------------------------------------
135 Rectangle
ControlLayoutData::GetCharacterBounds( long nIndex
) const
137 return (nIndex
>= 0 && nIndex
< (long) m_aUnicodeBoundRects
.size()) ? m_aUnicodeBoundRects
[ nIndex
] : Rectangle();
141 // -----------------------------------------------------------------------
143 Rectangle
Control::GetCharacterBounds( long nIndex
) const
147 return mpLayoutData
? mpLayoutData
->GetCharacterBounds( nIndex
) : Rectangle();
150 // -----------------------------------------------------------------------
152 long ControlLayoutData::GetIndexForPoint( const Point
& rPoint
) const
155 for( long i
= m_aUnicodeBoundRects
.size()-1; i
>= 0; i
-- )
157 if( m_aUnicodeBoundRects
[ i
].IsInside( rPoint
) )
166 // -----------------------------------------------------------------------
168 long Control::GetIndexForPoint( const Point
& rPoint
) const
172 return mpLayoutData
? mpLayoutData
->GetIndexForPoint( rPoint
) : -1;
175 // -----------------------------------------------------------------------
177 long ControlLayoutData::GetLineCount() const
179 long nLines
= m_aLineIndices
.size();
180 if( nLines
== 0 && m_aDisplayText
.Len() )
185 // -----------------------------------------------------------------------
187 long Control::GetLineCount() const
191 return mpLayoutData
? mpLayoutData
->GetLineCount() : 0;
194 // -----------------------------------------------------------------------
196 Pair
ControlLayoutData::GetLineStartEnd( long nLine
) const
198 Pair
aPair( -1, -1 );
200 int nDisplayLines
= m_aLineIndices
.size();
201 if( nLine
>= 0 && nLine
< nDisplayLines
)
203 aPair
.A() = m_aLineIndices
[nLine
];
204 if( nLine
+1 < nDisplayLines
)
205 aPair
.B() = m_aLineIndices
[nLine
+1]-1;
207 aPair
.B() = m_aDisplayText
.Len()-1;
209 else if( nLine
== 0 && nDisplayLines
== 0 && m_aDisplayText
.Len() )
211 // special case for single line controls so the implementations
212 // in that case do not have to fill in the line indices
214 aPair
.B() = m_aDisplayText
.Len()-1;
219 // -----------------------------------------------------------------------
221 Pair
Control::GetLineStartEnd( long nLine
) const
225 return mpLayoutData
? mpLayoutData
->GetLineStartEnd( nLine
) : Pair( -1, -1 );
228 // -----------------------------------------------------------------------
230 long ControlLayoutData::ToRelativeLineIndex( long nIndex
) const
232 // is the index sensible at all ?
233 if( nIndex
>= 0 && nIndex
< m_aDisplayText
.Len() )
235 int nDisplayLines
= m_aLineIndices
.size();
236 // if only 1 line exists, then absolute and relative index are
237 // identical -> do nothing
238 if( nDisplayLines
> 1 )
241 for( nLine
= nDisplayLines
-1; nLine
>= 0; nLine
-- )
243 if( m_aLineIndices
[nLine
] <= nIndex
)
245 nIndex
-= m_aLineIndices
[nLine
];
251 DBG_ASSERT( nLine
>= 0, "ToRelativeLineIndex failed" );
262 // -----------------------------------------------------------------------
264 long Control::ToRelativeLineIndex( long nIndex
) const
268 return mpLayoutData
? mpLayoutData
->ToRelativeLineIndex( nIndex
) : -1;
271 // -----------------------------------------------------------------------
273 String
Control::GetDisplayText() const
277 return mpLayoutData
? mpLayoutData
->m_aDisplayText
: GetText();
280 // -----------------------------------------------------------------------
282 long Control::Notify( NotifyEvent
& rNEvt
)
284 if ( rNEvt
.GetType() == EVENT_GETFOCUS
)
289 if ( ImplCallEventListenersAndHandler( VCLEVENT_CONTROL_GETFOCUS
, maGetFocusHdl
, this ) )
290 // been destroyed within the handler
296 if ( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
298 Window
* pFocusWin
= Application::GetFocusWindow();
299 if ( !pFocusWin
|| !ImplIsWindowOrChild( pFocusWin
) )
302 if ( ImplCallEventListenersAndHandler( VCLEVENT_CONTROL_LOSEFOCUS
, maLoseFocusHdl
, this ) )
303 // been destroyed within the handler
309 return Window::Notify( rNEvt
);
312 // -----------------------------------------------------------------------
314 void Control::StateChanged( StateChangedType nStateChange
)
316 if( nStateChange
== STATE_CHANGE_INITSHOW
||
317 nStateChange
== STATE_CHANGE_VISIBLE
||
318 nStateChange
== STATE_CHANGE_FORMAT
||
319 nStateChange
== STATE_CHANGE_ZOOM
||
320 nStateChange
== STATE_CHANGE_BORDER
||
321 nStateChange
== STATE_CHANGE_CONTROLFONT
327 Window::StateChanged( nStateChange
);
330 // -----------------------------------------------------------------------
332 void Control::AppendLayoutData( const Control
& rSubControl
) const
334 if( ! rSubControl
.mpLayoutData
)
335 rSubControl
.FillLayoutData();
336 if( ! rSubControl
.mpLayoutData
|| ! rSubControl
.mpLayoutData
->m_aDisplayText
.Len() )
339 long nCurrentIndex
= mpLayoutData
->m_aDisplayText
.Len();
340 mpLayoutData
->m_aDisplayText
.Append( rSubControl
.mpLayoutData
->m_aDisplayText
);
341 int nLines
= rSubControl
.mpLayoutData
->m_aLineIndices
.size();
343 mpLayoutData
->m_aLineIndices
.push_back( nCurrentIndex
);
344 for( n
= 1; n
< nLines
; n
++ )
345 mpLayoutData
->m_aLineIndices
.push_back( rSubControl
.mpLayoutData
->m_aLineIndices
[n
] + nCurrentIndex
);
346 int nRectangles
= rSubControl
.mpLayoutData
->m_aUnicodeBoundRects
.size();
347 Rectangle aRel
= const_cast<Control
&>(rSubControl
).GetWindowExtentsRelative( const_cast<Control
*>(this) );
348 for( n
= 0; n
< nRectangles
; n
++ )
350 Rectangle aRect
= rSubControl
.mpLayoutData
->m_aUnicodeBoundRects
[n
];
351 aRect
.Move( aRel
.Left(), aRel
.Top() );
352 mpLayoutData
->m_aUnicodeBoundRects
.push_back( aRect
);
356 // -----------------------------------------------------------------
358 BOOL
Control::ImplCallEventListenersAndHandler( ULONG nEvent
, const Link
& rHandler
, void* pCaller
)
360 ImplDelData aCheckDelete
;
361 ImplAddDel( &aCheckDelete
);
363 ImplCallEventListeners( nEvent
);
364 if ( !aCheckDelete
.IsDelete() )
366 rHandler
.Call( pCaller
);
368 if ( !aCheckDelete
.IsDelete() )
370 ImplRemoveDel( &aCheckDelete
);
377 // -----------------------------------------------------------------
379 void Control::SetLayoutDataParent( const Control
* pParent
) const
382 mpLayoutData
->m_pParent
= pParent
;
385 // -----------------------------------------------------------------
387 void Control::ImplClearLayoutData() const
389 delete mpLayoutData
, mpLayoutData
= NULL
;
392 // -----------------------------------------------------------------------
394 void Control::ImplDrawFrame( OutputDevice
* pDev
, Rectangle
& rRect
)
396 // use a deco view to draw the frame
397 // However, since there happens a lot of magic there, we need to fake some (style) settings
399 AllSettings
aOriginalSettings( pDev
->GetSettings() );
401 AllSettings
aNewSettings( aOriginalSettings
);
402 StyleSettings
aStyle( aNewSettings
.GetStyleSettings() );
404 // The *only known* clients of the Draw methods of the various VCL-controls are form controls:
405 // During print preview, and during printing, Draw is called. Thus, drawing always happens with a
406 // mono (colored) border
407 aStyle
.SetOptions( aStyle
.GetOptions() | STYLE_OPTION_MONO
);
408 aStyle
.SetMonoColor( GetSettings().GetStyleSettings().GetMonoColor() );
410 aNewSettings
.SetStyleSettings( aStyle
);
411 // #i67023# do not call data changed listeners for this fake
412 // since they may understandably invalidate on settings changed
413 pDev
->OutputDevice::SetSettings( aNewSettings
);
415 DecorationView
aDecoView( pDev
);
416 rRect
= aDecoView
.DrawFrame( rRect
, FRAME_DRAW_WINDOWBORDER
);
418 pDev
->OutputDevice::SetSettings( aOriginalSettings
);
421 // -----------------------------------------------------------------------
423 void Control::DataChanged( const DataChangedEvent
& rDCEvt
)
425 // we don't want to loose some style settings for controls created with the
427 if ( IsCreatedWithToolkit() &&
428 (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
429 (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
431 AllSettings aSettings
= GetSettings();
432 StyleSettings aStyleSettings
= aSettings
.GetStyleSettings();
433 ULONG nOldOptions
= rDCEvt
.GetOldSettings()->GetStyleSettings().GetOptions();
434 ULONG nNewOptions
= aStyleSettings
.GetOptions();
436 if ( !(nNewOptions
& STYLE_OPTION_MONO
) && ( nOldOptions
& STYLE_OPTION_MONO
) )
438 nNewOptions
|= STYLE_OPTION_MONO
;
439 aStyleSettings
.SetOptions( nNewOptions
);
440 aStyleSettings
.SetMonoColor( rDCEvt
.GetOldSettings()->GetStyleSettings().GetMonoColor() );
441 aSettings
.SetStyleSettings( aStyleSettings
);
442 SetSettings( aSettings
);
447 // -----------------------------------------------------------------
449 ControlLayoutData::~ControlLayoutData()
452 m_pParent
->ImplClearLayoutData();
455 // -----------------------------------------------------------------
457 Size
Control::GetOptimalSize(WindowSizeType eType
) const
460 case WINDOWSIZE_MINIMUM
:
461 return Size( GetTextWidth( GetText() ) + 2 * 12,
462 GetTextHeight() + 2 * 6 );
463 case WINDOWSIZE_PREFERRED
:
464 return GetOptimalSize( WINDOWSIZE_MINIMUM
);
465 case WINDOWSIZE_MAXIMUM
:
467 return Size( LONG_MAX
, LONG_MAX
);