merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / control / ctrl.cxx
blobe7eb0cdb61c144a8e93f9c238888adde53ddaa3c
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: ctrl.cxx,v $
10 * $Revision: 1.25 $
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"
34 #ifndef _SV_RC_H
35 #include <tools/rc.h>
36 #endif
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>
47 using namespace vcl;
49 // =======================================================================
51 void Control::ImplInitControlData()
53 mbHasFocus = FALSE;
54 mpLayoutData = NULL;
57 // -----------------------------------------------------------------------
59 Control::Control( WindowType nType ) :
60 Window( 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) )
86 Show();
89 // -----------------------------------------------------------------------
91 Control::~Control()
93 delete mpLayoutData, mpLayoutData = NULL;
96 // -----------------------------------------------------------------------
98 void Control::GetFocus()
100 Window::GetFocus();
103 // -----------------------------------------------------------------------
105 void Control::LoseFocus()
107 Window::LoseFocus();
110 // -----------------------------------------------------------------------
112 void Control::Resize()
114 delete mpLayoutData, mpLayoutData = NULL;
115 Window::Resize();
118 // -----------------------------------------------------------------------
120 void Control::FillLayoutData() const
124 // -----------------------------------------------------------------------
126 void Control::SetText( const String& rStr )
128 delete mpLayoutData;
129 mpLayoutData = NULL;
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
145 if( ! mpLayoutData )
146 FillLayoutData();
147 return mpLayoutData ? mpLayoutData->GetCharacterBounds( nIndex ) : Rectangle();
150 // -----------------------------------------------------------------------
152 long ControlLayoutData::GetIndexForPoint( const Point& rPoint ) const
154 long nIndex = -1;
155 for( long i = m_aUnicodeBoundRects.size()-1; i >= 0; i-- )
157 if( m_aUnicodeBoundRects[ i ].IsInside( rPoint ) )
159 nIndex = i;
160 break;
163 return nIndex;
166 // -----------------------------------------------------------------------
168 long Control::GetIndexForPoint( const Point& rPoint ) const
170 if( ! mpLayoutData )
171 FillLayoutData();
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() )
181 nLines = 1;
182 return nLines;
185 // -----------------------------------------------------------------------
187 long Control::GetLineCount() const
189 if( ! mpLayoutData )
190 FillLayoutData();
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;
206 else
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
213 aPair.A() = 0;
214 aPair.B() = m_aDisplayText.Len()-1;
216 return aPair;
219 // -----------------------------------------------------------------------
221 Pair Control::GetLineStartEnd( long nLine ) const
223 if( ! mpLayoutData )
224 FillLayoutData();
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 )
240 int nLine;
241 for( nLine = nDisplayLines-1; nLine >= 0; nLine-- )
243 if( m_aLineIndices[nLine] <= nIndex )
245 nIndex -= m_aLineIndices[nLine];
246 break;
249 if( nLine < 0 )
251 DBG_ASSERT( nLine >= 0, "ToRelativeLineIndex failed" );
252 nIndex = -1;
256 else
257 nIndex = -1;
259 return nIndex;
262 // -----------------------------------------------------------------------
264 long Control::ToRelativeLineIndex( long nIndex ) const
266 if( ! mpLayoutData )
267 FillLayoutData();
268 return mpLayoutData ? mpLayoutData->ToRelativeLineIndex( nIndex ) : -1;
271 // -----------------------------------------------------------------------
273 String Control::GetDisplayText() const
275 if( ! mpLayoutData )
276 FillLayoutData();
277 return mpLayoutData ? mpLayoutData->m_aDisplayText : GetText();
280 // -----------------------------------------------------------------------
282 long Control::Notify( NotifyEvent& rNEvt )
284 if ( rNEvt.GetType() == EVENT_GETFOCUS )
286 if ( !mbHasFocus )
288 mbHasFocus = TRUE;
289 if ( ImplCallEventListenersAndHandler( VCLEVENT_CONTROL_GETFOCUS, maGetFocusHdl, this ) )
290 // been destroyed within the handler
291 return TRUE;
294 else
296 if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
298 Window* pFocusWin = Application::GetFocusWindow();
299 if ( !pFocusWin || !ImplIsWindowOrChild( pFocusWin ) )
301 mbHasFocus = FALSE;
302 if ( ImplCallEventListenersAndHandler( VCLEVENT_CONTROL_LOSEFOCUS, maLoseFocusHdl, this ) )
303 // been destroyed within the handler
304 return TRUE;
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
324 delete mpLayoutData;
325 mpLayoutData = NULL;
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() )
337 return;
339 long nCurrentIndex = mpLayoutData->m_aDisplayText.Len();
340 mpLayoutData->m_aDisplayText.Append( rSubControl.mpLayoutData->m_aDisplayText );
341 int nLines = rSubControl.mpLayoutData->m_aLineIndices.size();
342 int n;
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 );
371 return FALSE;
374 return TRUE;
377 // -----------------------------------------------------------------
379 void Control::SetLayoutDataParent( const Control* pParent ) const
381 if( mpLayoutData )
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
398 // on the device
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
426 // toolkit
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()
451 if( m_pParent )
452 m_pParent->ImplClearLayoutData();
455 // -----------------------------------------------------------------
457 Size Control::GetOptimalSize(WindowSizeType eType) const
459 switch (eType) {
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:
466 default:
467 return Size( LONG_MAX, LONG_MAX );