fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / vcl / source / control / ctrl.cxx
blobc5de9cab7342c0663f54de6371301ea11bff7360
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <comphelper/processfactory.hxx>
23 #include <tools/rc.h>
24 #include <vcl/svapp.hxx>
25 #include <vcl/event.hxx>
26 #include <vcl/ctrl.hxx>
27 #include <vcl/decoview.hxx>
28 #include <vcl/salnativewidgets.hxx>
30 #include <textlayout.hxx>
31 #include <svdata.hxx>
32 #include <controldata.hxx>
35 using namespace vcl;
37 // =======================================================================
39 void Control::ImplInitControlData()
41 mbHasControlFocus = sal_False;
42 mpControlData = new ImplControlData;
45 // -----------------------------------------------------------------------
47 Control::Control( WindowType nType ) :
48 Window( nType )
50 ImplInitControlData();
53 // -----------------------------------------------------------------------
55 Control::Control( Window* pParent, WinBits nStyle ) :
56 Window( WINDOW_CONTROL )
58 ImplInitControlData();
59 ImplInit( pParent, nStyle, NULL );
62 Control::Control( Window* pParent, const ResId& rResId ) :
63 Window( WINDOW_CONTROL )
65 ImplInitControlData();
66 rResId.SetRT( RSC_CONTROL );
67 WinBits nStyle = ImplInitRes( rResId );
68 ImplInit( pParent, nStyle, NULL );
69 ImplLoadRes( rResId );
71 if ( !(nStyle & WB_HIDE) )
72 Show();
75 // -----------------------------------------------------------------------
77 Control::~Control()
79 delete mpControlData, mpControlData = NULL;
82 // -----------------------------------------------------------------------
84 void Control::GetFocus()
86 Window::GetFocus();
89 // -----------------------------------------------------------------------
91 void Control::LoseFocus()
93 Window::LoseFocus();
96 // -----------------------------------------------------------------------
98 void Control::Resize()
100 ImplClearLayoutData();
101 Window::Resize();
104 // -----------------------------------------------------------------------
106 void Control::FillLayoutData() const
110 // -----------------------------------------------------------------------
112 void Control::CreateLayoutData() const
114 DBG_ASSERT( !mpControlData->mpLayoutData, "Control::CreateLayoutData: should be called with non-existent layout data only!" );
115 mpControlData->mpLayoutData = new ::vcl::ControlLayoutData();
118 // -----------------------------------------------------------------------
120 bool Control::HasLayoutData() const
122 return mpControlData->mpLayoutData != NULL;
125 // -----------------------------------------------------------------------
127 ::vcl::ControlLayoutData* Control::GetLayoutData() const
129 return mpControlData->mpLayoutData;
132 // -----------------------------------------------------------------------
134 void Control::SetText( const OUString& rStr )
136 ImplClearLayoutData();
137 Window::SetText( rStr );
140 // -----------------------------------------------------------------------
142 Rectangle ControlLayoutData::GetCharacterBounds( long nIndex ) const
144 return (nIndex >= 0 && nIndex < (long) m_aUnicodeBoundRects.size()) ? m_aUnicodeBoundRects[ nIndex ] : Rectangle();
148 // -----------------------------------------------------------------------
150 Rectangle Control::GetCharacterBounds( long nIndex ) const
152 if( !HasLayoutData() )
153 FillLayoutData();
154 return mpControlData->mpLayoutData ? mpControlData->mpLayoutData->GetCharacterBounds( nIndex ) : Rectangle();
157 // -----------------------------------------------------------------------
159 long ControlLayoutData::GetIndexForPoint( const Point& rPoint ) const
161 long nIndex = -1;
162 for( long i = m_aUnicodeBoundRects.size()-1; i >= 0; i-- )
164 Point aTopLeft = m_aUnicodeBoundRects[i].TopLeft();
165 Point aBottomRight = m_aUnicodeBoundRects[i].BottomRight();
166 if (rPoint.X() >= aTopLeft.X() && rPoint.Y() >= aTopLeft.Y() &&
167 rPoint.X() <= aBottomRight.X() && rPoint.Y() <= aBottomRight.Y())
169 nIndex = i;
170 break;
173 return nIndex;
176 // -----------------------------------------------------------------------
178 long Control::GetIndexForPoint( const Point& rPoint ) const
180 if( ! HasLayoutData() )
181 FillLayoutData();
182 return mpControlData->mpLayoutData ? mpControlData->mpLayoutData->GetIndexForPoint( rPoint ) : -1;
185 // -----------------------------------------------------------------------
187 long ControlLayoutData::GetLineCount() const
189 long nLines = m_aLineIndices.size();
190 if( nLines == 0 && !m_aDisplayText.isEmpty() )
191 nLines = 1;
192 return nLines;
195 // -----------------------------------------------------------------------
197 Pair ControlLayoutData::GetLineStartEnd( long nLine ) const
199 Pair aPair( -1, -1 );
201 int nDisplayLines = m_aLineIndices.size();
202 if( nLine >= 0 && nLine < nDisplayLines )
204 aPair.A() = m_aLineIndices[nLine];
205 if( nLine+1 < nDisplayLines )
206 aPair.B() = m_aLineIndices[nLine+1]-1;
207 else
208 aPair.B() = m_aDisplayText.getLength()-1;
210 else if( nLine == 0 && nDisplayLines == 0 && !m_aDisplayText.isEmpty() )
212 // special case for single line controls so the implementations
213 // in that case do not have to fill in the line indices
214 aPair.A() = 0;
215 aPair.B() = m_aDisplayText.getLength()-1;
217 return aPair;
220 // -----------------------------------------------------------------------
222 Pair Control::GetLineStartEnd( long nLine ) const
224 if( !HasLayoutData() )
225 FillLayoutData();
226 return mpControlData->mpLayoutData ? mpControlData->mpLayoutData->GetLineStartEnd( nLine ) : Pair( -1, -1 );
229 // -----------------------------------------------------------------------
231 long ControlLayoutData::ToRelativeLineIndex( long nIndex ) const
233 // is the index sensible at all ?
234 if( nIndex >= 0 && nIndex < m_aDisplayText.getLength() )
236 int nDisplayLines = m_aLineIndices.size();
237 // if only 1 line exists, then absolute and relative index are
238 // identical -> do nothing
239 if( nDisplayLines > 1 )
241 int nLine;
242 for( nLine = nDisplayLines-1; nLine >= 0; nLine-- )
244 if( m_aLineIndices[nLine] <= nIndex )
246 nIndex -= m_aLineIndices[nLine];
247 break;
250 if( nLine < 0 )
252 DBG_ASSERT( nLine >= 0, "ToRelativeLineIndex failed" );
253 nIndex = -1;
257 else
258 nIndex = -1;
260 return nIndex;
263 // -----------------------------------------------------------------------
265 long Control::ToRelativeLineIndex( long nIndex ) const
267 if( !HasLayoutData() )
268 FillLayoutData();
269 return mpControlData->mpLayoutData ? mpControlData->mpLayoutData->ToRelativeLineIndex( nIndex ) : -1;
272 // -----------------------------------------------------------------------
274 OUString Control::GetDisplayText() const
276 if( !HasLayoutData() )
277 FillLayoutData();
278 return mpControlData->mpLayoutData ? OUString(mpControlData->mpLayoutData->m_aDisplayText) : GetText();
281 // -----------------------------------------------------------------------
283 long Control::Notify( NotifyEvent& rNEvt )
285 if ( rNEvt.GetType() == EVENT_GETFOCUS )
287 if ( !mbHasControlFocus )
289 mbHasControlFocus = sal_True;
290 StateChanged( STATE_CHANGE_CONTROL_FOCUS );
291 if ( ImplCallEventListenersAndHandler( VCLEVENT_CONTROL_GETFOCUS, maGetFocusHdl, this ) )
292 // been destroyed within the handler
293 return sal_True;
296 else
298 if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
300 Window* pFocusWin = Application::GetFocusWindow();
301 if ( !pFocusWin || !ImplIsWindowOrChild( pFocusWin ) )
303 mbHasControlFocus = sal_False;
304 StateChanged( STATE_CHANGE_CONTROL_FOCUS );
305 if ( ImplCallEventListenersAndHandler( VCLEVENT_CONTROL_LOSEFOCUS, maLoseFocusHdl, this ) )
306 // been destroyed within the handler
307 return sal_True;
312 return Window::Notify( rNEvt );
315 // -----------------------------------------------------------------------
317 void Control::StateChanged( StateChangedType nStateChange )
319 if( nStateChange == STATE_CHANGE_INITSHOW ||
320 nStateChange == STATE_CHANGE_VISIBLE ||
321 nStateChange == STATE_CHANGE_ZOOM ||
322 nStateChange == STATE_CHANGE_BORDER ||
323 nStateChange == STATE_CHANGE_CONTROLFONT
326 ImplClearLayoutData();
328 Window::StateChanged( nStateChange );
331 // -----------------------------------------------------------------------
333 void Control::AppendLayoutData( const Control& rSubControl ) const
335 if( !rSubControl.HasLayoutData() )
336 rSubControl.FillLayoutData();
337 if( !rSubControl.HasLayoutData() || rSubControl.mpControlData->mpLayoutData->m_aDisplayText.isEmpty() )
338 return;
340 long nCurrentIndex = mpControlData->mpLayoutData->m_aDisplayText.getLength();
341 mpControlData->mpLayoutData->m_aDisplayText += rSubControl.mpControlData->mpLayoutData->m_aDisplayText;
342 int nLines = rSubControl.mpControlData->mpLayoutData->m_aLineIndices.size();
343 int n;
344 mpControlData->mpLayoutData->m_aLineIndices.push_back( nCurrentIndex );
345 for( n = 1; n < nLines; n++ )
346 mpControlData->mpLayoutData->m_aLineIndices.push_back( rSubControl.mpControlData->mpLayoutData->m_aLineIndices[n] + nCurrentIndex );
347 int nRectangles = rSubControl.mpControlData->mpLayoutData->m_aUnicodeBoundRects.size();
348 Rectangle aRel = const_cast<Control&>(rSubControl).GetWindowExtentsRelative( const_cast<Control*>(this) );
349 for( n = 0; n < nRectangles; n++ )
351 Rectangle aRect = rSubControl.mpControlData->mpLayoutData->m_aUnicodeBoundRects[n];
352 aRect.Move( aRel.Left(), aRel.Top() );
353 mpControlData->mpLayoutData->m_aUnicodeBoundRects.push_back( aRect );
357 // -----------------------------------------------------------------
359 sal_Bool Control::ImplCallEventListenersAndHandler( sal_uLong nEvent, const Link& rHandler, void* pCaller )
361 ImplDelData aCheckDelete;
362 ImplAddDel( &aCheckDelete );
364 ImplCallEventListeners( nEvent );
365 if ( !aCheckDelete.IsDead() )
367 rHandler.Call( pCaller );
369 if ( !aCheckDelete.IsDead() )
371 ImplRemoveDel( &aCheckDelete );
372 return sal_False;
375 return sal_True;
378 // -----------------------------------------------------------------
380 void Control::SetLayoutDataParent( const Control* pParent ) const
382 if( HasLayoutData() )
383 mpControlData->mpLayoutData->m_pParent = pParent;
386 // -----------------------------------------------------------------
388 void Control::ImplClearLayoutData() const
390 delete mpControlData->mpLayoutData, mpControlData->mpLayoutData = NULL;
393 // -----------------------------------------------------------------------
395 void Control::ImplDrawFrame( OutputDevice* pDev, Rectangle& rRect )
397 // use a deco view to draw the frame
398 // However, since there happens a lot of magic there, we need to fake some (style) settings
399 // on the device
400 AllSettings aOriginalSettings( pDev->GetSettings() );
402 AllSettings aNewSettings( aOriginalSettings );
403 StyleSettings aStyle( aNewSettings.GetStyleSettings() );
405 // The *only known* clients of the Draw methods of the various VCL-controls are form controls:
406 // During print preview, and during printing, Draw is called. Thus, drawing always happens with a
407 // mono (colored) border
408 aStyle.SetOptions( aStyle.GetOptions() | STYLE_OPTION_MONO );
409 aStyle.SetMonoColor( GetSettings().GetStyleSettings().GetMonoColor() );
411 aNewSettings.SetStyleSettings( aStyle );
412 // #i67023# do not call data changed listeners for this fake
413 // since they may understandably invalidate on settings changed
414 pDev->OutputDevice::SetSettings( aNewSettings );
416 DecorationView aDecoView( pDev );
417 rRect = aDecoView.DrawFrame( rRect, FRAME_DRAW_WINDOWBORDER );
419 pDev->OutputDevice::SetSettings( aOriginalSettings );
422 // -----------------------------------------------------------------------
424 void Control::DataChanged( const DataChangedEvent& rDCEvt)
426 // we don't want to loose some style settings for controls created with the
427 // toolkit
428 if ( IsCreatedWithToolkit() &&
429 (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
430 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
432 const AllSettings* pOldSettings = rDCEvt.GetOldSettings();
434 AllSettings aSettings = GetSettings();
435 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
436 sal_uLong nNewOptions = aStyleSettings.GetOptions();
438 if ( pOldSettings && !(nNewOptions & STYLE_OPTION_MONO) && ( pOldSettings->GetStyleSettings().GetOptions() & STYLE_OPTION_MONO ) )
440 nNewOptions |= STYLE_OPTION_MONO;
441 aStyleSettings.SetOptions( nNewOptions );
442 aStyleSettings.SetMonoColor( pOldSettings->GetStyleSettings().GetMonoColor() );
443 aSettings.SetStyleSettings( aStyleSettings );
444 SetSettings( aSettings );
449 // -----------------------------------------------------------------
451 ControlLayoutData::~ControlLayoutData()
453 if( m_pParent )
454 m_pParent->ImplClearLayoutData();
457 // -----------------------------------------------------------------
459 Size Control::GetOptimalSize() const
461 return Size( GetTextWidth( GetText() ) + 2 * 12,
462 GetTextHeight() + 2 * 6 );
465 // -----------------------------------------------------------------
467 void Control::SetReferenceDevice( OutputDevice* _referenceDevice )
469 if ( mpControlData->mpReferenceDevice == _referenceDevice )
470 return;
472 mpControlData->mpReferenceDevice = _referenceDevice;
473 Invalidate();
476 // -----------------------------------------------------------------
478 OutputDevice* Control::GetReferenceDevice() const
480 return mpControlData->mpReferenceDevice;
483 // -----------------------------------------------------------------
485 const Font& Control::GetCanonicalFont( const StyleSettings& _rStyle ) const
487 return _rStyle.GetLabelFont();
490 // -----------------------------------------------------------------
491 const Color& Control::GetCanonicalTextColor( const StyleSettings& _rStyle ) const
493 return _rStyle.GetLabelTextColor();
496 // -----------------------------------------------------------------
497 void Control::ImplInitSettings( const sal_Bool _bFont, const sal_Bool _bForeground )
499 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
501 if ( _bFont )
503 Font aFont( GetCanonicalFont( rStyleSettings ) );
504 if ( IsControlFont() )
505 aFont.Merge( GetControlFont() );
506 SetZoomedPointFont( aFont );
509 if ( _bForeground || _bFont )
511 Color aColor;
512 if ( IsControlForeground() )
513 aColor = GetControlForeground();
514 else
515 aColor = GetCanonicalTextColor( rStyleSettings );
516 SetTextColor( aColor );
517 SetTextFillColor();
521 // -----------------------------------------------------------------
523 void Control::DrawControlText( OutputDevice& _rTargetDevice, Rectangle& _io_rRect, const OUString& _rStr,
524 sal_uInt16 _nStyle, MetricVector* _pVector, OUString* _pDisplayText ) const
526 #ifdef FS_DEBUG
527 if ( !_pVector )
529 static MetricVector aCharRects;
530 static String sDisplayText;
531 aCharRects.clear();
532 sDisplayText = String();
533 _pVector = &aCharRects;
534 _pDisplayText = &sDisplayText;
536 #endif
538 if ( !mpControlData->mpReferenceDevice || ( mpControlData->mpReferenceDevice == &_rTargetDevice ) )
540 _io_rRect = _rTargetDevice.GetTextRect( _io_rRect, _rStr, _nStyle );
541 _rTargetDevice.DrawText( _io_rRect, _rStr, _nStyle, _pVector, _pDisplayText );
543 else
545 ControlTextRenderer aRenderer( *this, _rTargetDevice, *mpControlData->mpReferenceDevice );
546 _io_rRect = aRenderer.DrawText( _io_rRect, _rStr, _nStyle, _pVector, _pDisplayText );
549 #ifdef FS_DEBUG
550 _rTargetDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
551 _rTargetDevice.SetLineColor( COL_LIGHTRED );
552 _rTargetDevice.SetFillColor();
553 for ( MetricVector::const_iterator cr = _pVector->begin();
554 cr != _pVector->end();
555 ++cr
558 _rTargetDevice.DrawRect( *cr );
560 _rTargetDevice.Pop();
561 #endif
564 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */