Files
libreoffice/vcl/source/edit/vclmedit.cxx
Stephan Bergmann f6ec07a396 loplugin:cstylecast: deal with remaining pointer casts
Change-Id: I07bf1403e6b992807541a499b786d47f835b2f81
2015-06-08 16:29:41 +02:00

1594 lines
49 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <tools/rc.h>
#include <vcl/builder.hxx>
#include <vcl/decoview.hxx>
#include <vcl/svapp.hxx>
#include <vcl/vclmedit.hxx>
#include <vcl/xtextedt.hxx>
#include <svl/undo.hxx>
#include <svl/lstner.hxx>
#include <svl/smplhint.hxx>
#include <svids.hrc>
#include <vcl/scrbar.hxx>
#include <vcl/settings.hxx>
class TextWindow : public vcl::Window
{
private:
ExtTextEngine* mpExtTextEngine;
ExtTextView* mpExtTextView;
bool mbInMBDown;
bool mbFocusSelectionHide;
bool mbIgnoreTab;
bool mbActivePopup;
bool mbSelectOnTab;
bool mbTextSelectable;
public:
explicit TextWindow( vcl::Window* pParent );
virtual ~TextWindow();
virtual void dispose() SAL_OVERRIDE;
ExtTextEngine* GetTextEngine() const { return mpExtTextEngine; }
ExtTextView* GetTextView() const { return mpExtTextView; }
virtual void MouseMove( const MouseEvent& rMEvt ) SAL_OVERRIDE;
virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
virtual void MouseButtonUp( const MouseEvent& rMEvt ) SAL_OVERRIDE;
virtual void KeyInput( const KeyEvent& rKEvent ) SAL_OVERRIDE;
virtual void Command( const CommandEvent& rCEvt ) SAL_OVERRIDE;
virtual void Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect) SAL_OVERRIDE;
virtual void Resize() SAL_OVERRIDE;
virtual void GetFocus() SAL_OVERRIDE;
virtual void LoseFocus() SAL_OVERRIDE;
void SetAutoFocusHide( bool bAutoHide ) { mbFocusSelectionHide = bAutoHide; }
void SetIgnoreTab( bool bIgnore ) { mbIgnoreTab = bIgnore; }
void DisableSelectionOnFocus() { mbSelectOnTab = false; }
};
class ImpVclMEdit : public SfxListener
{
private:
VclPtr<VclMultiLineEdit> pVclMultiLineEdit;
VclPtr<TextWindow> mpTextWindow;
VclPtr<ScrollBar> mpHScrollBar;
VclPtr<ScrollBar> mpVScrollBar;
VclPtr<ScrollBarBox> mpScrollBox;
Point maTextWindowOffset;
sal_Int32 mnTextWidth;
mutable Selection maSelection;
protected:
virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE;
void ImpUpdateSrollBarVis( WinBits nWinStyle );
void ImpInitScrollBars();
void ImpSetScrollBarRanges();
void ImpSetHScrollBarThumbPos();
DECL_LINK( ScrollHdl, ScrollBar* );
public:
ImpVclMEdit( VclMultiLineEdit* pVclMultiLineEdit, WinBits nWinStyle );
virtual ~ImpVclMEdit();
void SetModified( bool bMod );
bool IsModified() const;
void SetReadOnly( bool bRdOnly );
bool IsReadOnly() const;
void SetMaxTextLen(sal_Int32 nLen);
sal_Int32 GetMaxTextLen() const;
void SetMaxTextWidth( sal_uLong nMaxWidth );
void InsertText( const OUString& rStr );
OUString GetSelected() const;
OUString GetSelected( LineEnd aSeparator ) const;
void SetSelection( const Selection& rSelection );
const Selection& GetSelection() const;
void Cut();
void Copy();
void Paste();
void SetText( const OUString& rStr );
OUString GetText() const;
OUString GetText( LineEnd aSeparator ) const;
OUString GetTextLines( LineEnd aSeparator ) const;
void Resize();
void GetFocus();
bool HandleCommand( const CommandEvent& rCEvt );
void Enable( bool bEnable );
Size CalcMinimumSize() const;
Size CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const;
void GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const;
void SetAlign( WinBits nWinStyle );
void InitFromStyle( WinBits nWinStyle );
TextWindow* GetTextWindow() { return mpTextWindow; }
ScrollBar* GetHScrollBar() { return mpHScrollBar; }
ScrollBar* GetVScrollBar() { return mpVScrollBar; }
};
ImpVclMEdit::ImpVclMEdit( VclMultiLineEdit* pEdt, WinBits nWinStyle )
:mpHScrollBar(NULL)
,mpVScrollBar(NULL)
,mpScrollBox(NULL)
{
pVclMultiLineEdit = pEdt;
mnTextWidth = 0;
mpTextWindow = VclPtr<TextWindow>::Create( pEdt );
mpTextWindow->Show();
InitFromStyle( nWinStyle );
StartListening( *mpTextWindow->GetTextEngine() );
}
void ImpVclMEdit::ImpUpdateSrollBarVis( WinBits nWinStyle )
{
const bool bHaveVScroll = (nullptr != mpVScrollBar);
const bool bHaveHScroll = (nullptr != mpHScrollBar);
const bool bHaveScrollBox = (nullptr != mpScrollBox);
bool bNeedVScroll = ( nWinStyle & WB_VSCROLL ) == WB_VSCROLL;
const bool bNeedHScroll = ( nWinStyle & WB_HSCROLL ) == WB_HSCROLL;
const bool bAutoVScroll = ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL;
if ( !bNeedVScroll && bAutoVScroll )
{
TextEngine& rEngine( *mpTextWindow->GetTextEngine() );
sal_uLong nOverallTextHeight(0);
for ( sal_uLong i=0; i<rEngine.GetParagraphCount(); ++i )
nOverallTextHeight += rEngine.GetTextHeight( i );
if ( nOverallTextHeight > (sal_uLong)mpTextWindow->GetOutputSizePixel().Height() )
bNeedVScroll = true;
}
const bool bNeedScrollBox = bNeedVScroll && bNeedHScroll;
bool bScrollbarsChanged = false;
if ( bHaveVScroll != bNeedVScroll )
{
mpVScrollBar.disposeAndClear();
mpVScrollBar = bNeedVScroll ? VclPtr<ScrollBar>::Create( pVclMultiLineEdit, WB_VSCROLL|WB_DRAG ) : nullptr;
if ( bNeedVScroll )
{
mpVScrollBar->Show();
mpVScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
}
bScrollbarsChanged = true;
}
if ( bHaveHScroll != bNeedHScroll )
{
mpHScrollBar.disposeAndClear();
mpHScrollBar = bNeedHScroll ? VclPtr<ScrollBar>::Create( pVclMultiLineEdit, WB_HSCROLL|WB_DRAG ) : nullptr;
if ( bNeedHScroll )
{
mpHScrollBar->Show();
mpHScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
}
bScrollbarsChanged = true;
}
if ( bHaveScrollBox != bNeedScrollBox )
{
mpScrollBox.disposeAndClear();
mpScrollBox = bNeedScrollBox ? VclPtr<ScrollBarBox>::Create( pVclMultiLineEdit, WB_SIZEABLE ) : nullptr;
if ( bNeedScrollBox )
mpScrollBox->Show();
}
if ( bScrollbarsChanged )
{
ImpInitScrollBars();
Resize();
}
}
void ImpVclMEdit::InitFromStyle( WinBits nWinStyle )
{
ImpUpdateSrollBarVis( nWinStyle );
SetAlign( nWinStyle );
if ( nWinStyle & WB_NOHIDESELECTION )
mpTextWindow->SetAutoFocusHide( false );
else
mpTextWindow->SetAutoFocusHide( true );
if ( nWinStyle & WB_READONLY )
mpTextWindow->GetTextView()->SetReadOnly( true );
else
mpTextWindow->GetTextView()->SetReadOnly( false );
if ( nWinStyle & WB_IGNORETAB )
{
mpTextWindow->SetIgnoreTab( true );
}
else
{
mpTextWindow->SetIgnoreTab( false );
// #103667# VclMultiLineEdit has the flag, but focusable window also needs this flag
WinBits nStyle = mpTextWindow->GetStyle();
nStyle |= WB_NODIALOGCONTROL;
mpTextWindow->SetStyle( nStyle );
}
}
ImpVclMEdit::~ImpVclMEdit()
{
EndListening( *mpTextWindow->GetTextEngine() );
mpTextWindow.disposeAndClear();
mpHScrollBar.disposeAndClear();
mpVScrollBar.disposeAndClear();
mpScrollBox.disposeAndClear();
pVclMultiLineEdit.disposeAndClear();
}
void ImpVclMEdit::ImpSetScrollBarRanges()
{
if ( mpVScrollBar )
{
sal_uLong nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
mpVScrollBar->SetRange( Range( 0, (long)nTextHeight-1 ) );
}
if ( mpHScrollBar )
{
// sal_uLong nTextWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
// Es gibt kein Notify bei Breiten-Aenderung...
// sal_uLong nW = Max( (sal_uLong)mpTextWindow->GetOutputSizePixel().Width()*5, (sal_uLong)nTextWidth );
// mpHScrollBar->SetRange( Range( 0, (long)nW ) );
mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
}
}
void ImpVclMEdit::ImpInitScrollBars()
{
static const sal_Unicode sampleChar = { 'x' };
if ( mpHScrollBar || mpVScrollBar )
{
ImpSetScrollBarRanges();
Size aCharBox;
aCharBox.Width() = mpTextWindow->GetTextWidth( OUString(sampleChar) );
aCharBox.Height() = mpTextWindow->GetTextHeight();
Size aOutSz = mpTextWindow->GetOutputSizePixel();
if ( mpHScrollBar )
{
mpHScrollBar->SetVisibleSize( aOutSz.Width() );
mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 );
mpHScrollBar->SetLineSize( aCharBox.Width()*10 );
ImpSetHScrollBarThumbPos();
}
if ( mpVScrollBar )
{
mpVScrollBar->SetVisibleSize( aOutSz.Height() );
mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 );
mpVScrollBar->SetLineSize( aCharBox.Height() );
mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
}
}
}
void ImpVclMEdit::ImpSetHScrollBarThumbPos()
{
long nX = mpTextWindow->GetTextView()->GetStartDocPos().X();
if ( !mpTextWindow->GetTextEngine()->IsRightToLeft() )
mpHScrollBar->SetThumbPos( nX );
else
mpHScrollBar->SetThumbPos( mnTextWidth - mpHScrollBar->GetVisibleSize() - nX );
}
IMPL_LINK( ImpVclMEdit, ScrollHdl, ScrollBar*, pCurScrollBar )
{
long nDiffX = 0, nDiffY = 0;
if ( pCurScrollBar == mpVScrollBar )
nDiffY = mpTextWindow->GetTextView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
else if ( pCurScrollBar == mpHScrollBar )
nDiffX = mpTextWindow->GetTextView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
mpTextWindow->GetTextView()->Scroll( nDiffX, nDiffY );
// mpTextWindow->GetTextView()->ShowCursor( false, true );
return 0;
}
void ImpVclMEdit::SetAlign( WinBits nWinStyle )
{
bool bRTL = AllSettings::GetLayoutRTL();
mpTextWindow->GetTextEngine()->SetRightToLeft( bRTL );
if ( nWinStyle & WB_CENTER )
mpTextWindow->GetTextEngine()->SetTextAlign( TXTALIGN_CENTER );
else if ( nWinStyle & WB_RIGHT )
mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_RIGHT : TXTALIGN_LEFT );
else if ( nWinStyle & WB_LEFT )
mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_LEFT : TXTALIGN_RIGHT );
}
void ImpVclMEdit::SetModified( bool bMod )
{
mpTextWindow->GetTextEngine()->SetModified( bMod );
}
bool ImpVclMEdit::IsModified() const
{
return mpTextWindow->GetTextEngine()->IsModified();
}
void ImpVclMEdit::SetReadOnly( bool bRdOnly )
{
mpTextWindow->GetTextView()->SetReadOnly( bRdOnly );
// TODO: Adjust color?
}
bool ImpVclMEdit::IsReadOnly() const
{
return mpTextWindow->GetTextView()->IsReadOnly();
}
void ImpVclMEdit::SetMaxTextLen(sal_Int32 nLen)
{
mpTextWindow->GetTextEngine()->SetMaxTextLen(nLen);
}
sal_Int32 ImpVclMEdit::GetMaxTextLen() const
{
return mpTextWindow->GetTextEngine()->GetMaxTextLen();
}
void ImpVclMEdit::InsertText( const OUString& rStr )
{
mpTextWindow->GetTextView()->InsertText( rStr );
}
OUString ImpVclMEdit::GetSelected() const
{
return mpTextWindow->GetTextView()->GetSelected();
}
OUString ImpVclMEdit::GetSelected( LineEnd aSeparator ) const
{
return mpTextWindow->GetTextView()->GetSelected( aSeparator );
}
void ImpVclMEdit::SetMaxTextWidth( sal_uLong nMaxWidth )
{
mpTextWindow->GetTextEngine()->SetMaxTextWidth( nMaxWidth );
}
void ImpVclMEdit::Resize()
{
size_t nIteration = 1;
do
{
WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
ImpUpdateSrollBarVis( nWinStyle );
Size aSz = pVclMultiLineEdit->GetOutputSizePixel();
Size aEditSize = aSz;
long nSBWidth = pVclMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize();
nSBWidth = pVclMultiLineEdit->CalcZoom( nSBWidth );
if ( mpHScrollBar )
aSz.Height() -= nSBWidth+1;
if ( mpVScrollBar )
aSz.Width() -= nSBWidth+1;
if ( !mpHScrollBar )
mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() );
else
mpHScrollBar->setPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth );
Point aTextWindowPos( maTextWindowOffset );
if ( mpVScrollBar )
{
if( AllSettings::GetLayoutRTL() )
{
mpVScrollBar->setPosSizePixel( 0, 0, nSBWidth, aSz.Height() );
aTextWindowPos.X() += nSBWidth;
}
else
mpVScrollBar->setPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() );
}
if ( mpScrollBox )
mpScrollBox->setPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth );
Size aTextWindowSize( aSz );
aTextWindowSize.Width() -= maTextWindowOffset.X();
aTextWindowSize.Height() -= maTextWindowOffset.Y();
if ( aTextWindowSize.Width() < 0 )
aTextWindowSize.Width() = 0;
if ( aTextWindowSize.Height() < 0 )
aTextWindowSize.Height() = 0;
Size aOldTextWindowSize( mpTextWindow->GetSizePixel() );
mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize );
if ( aOldTextWindowSize == aTextWindowSize )
break;
// Changing the text window size might effectively have changed the need for
// scrollbars, so do another iteration.
++nIteration;
OSL_ENSURE( nIteration < 3, "ImpVclMEdit::Resize: isn't this expected to terminate with the second iteration?" );
} while ( nIteration <= 3 ); // artificial break after four iterations
ImpInitScrollBars();
}
void ImpVclMEdit::GetFocus()
{
mpTextWindow->GrabFocus();
}
void ImpVclMEdit::Cut()
{
if ( !mpTextWindow->GetTextView()->IsReadOnly() )
mpTextWindow->GetTextView()->Cut();
}
void ImpVclMEdit::Copy()
{
mpTextWindow->GetTextView()->Copy();
}
void ImpVclMEdit::Paste()
{
if ( !mpTextWindow->GetTextView()->IsReadOnly() )
mpTextWindow->GetTextView()->Paste();
}
void ImpVclMEdit::SetText( const OUString& rStr )
{
bool bWasModified = mpTextWindow->GetTextEngine()->IsModified();
mpTextWindow->GetTextEngine()->SetText( rStr );
if ( !bWasModified )
mpTextWindow->GetTextEngine()->SetModified( false );
mpTextWindow->GetTextView()->SetSelection( TextSelection() );
WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
ImpUpdateSrollBarVis( nWinStyle );
}
OUString ImpVclMEdit::GetText() const
{
return mpTextWindow->GetTextEngine()->GetText();
}
OUString ImpVclMEdit::GetText( LineEnd aSeparator ) const
{
return mpTextWindow->GetTextEngine()->GetText( aSeparator );
}
OUString ImpVclMEdit::GetTextLines( LineEnd aSeparator ) const
{
return mpTextWindow->GetTextEngine()->GetTextLines( aSeparator );
}
void ImpVclMEdit::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
const TextHint* pTextHint = dynamic_cast<const TextHint*>(&rHint);
if ( pTextHint )
{
if( pTextHint->GetId() == TEXT_HINT_VIEWSCROLLED )
{
if ( mpHScrollBar )
ImpSetHScrollBarThumbPos();
if ( mpVScrollBar )
mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
}
else if( pTextHint->GetId() == TEXT_HINT_TEXTHEIGHTCHANGED )
{
if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() )
{
long nOutHeight = mpTextWindow->GetOutputSizePixel().Height();
long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
if ( nTextHeight < nOutHeight )
mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() );
}
ImpSetScrollBarRanges();
}
else if( pTextHint->GetId() == TEXT_HINT_TEXTFORMATTED )
{
if ( mpHScrollBar )
{
sal_Int32 nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
if ( nWidth != mnTextWidth )
{
mnTextWidth = nWidth;
mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
ImpSetHScrollBarThumbPos();
}
}
}
else if( pTextHint->GetId() == TEXT_HINT_MODIFIED )
{
ImpUpdateSrollBarVis(pVclMultiLineEdit->GetStyle());
pVclMultiLineEdit->Modify();
}
else if( pTextHint->GetId() == TEXT_HINT_VIEWSELECTIONCHANGED )
{
pVclMultiLineEdit->SelectionChanged();
}
else if( pTextHint->GetId() == TEXT_HINT_VIEWCARETCHANGED )
{
pVclMultiLineEdit->CaretChanged();
}
}
}
void ImpVclMEdit::SetSelection( const Selection& rSelection )
{
OUString aText = mpTextWindow->GetTextEngine()->GetText();
Selection aNewSelection( rSelection );
if ( aNewSelection.Min() < 0 )
aNewSelection.Min() = 0;
else if ( aNewSelection.Min() > aText.getLength() )
aNewSelection.Min() = aText.getLength();
if ( aNewSelection.Max() < 0 )
aNewSelection.Max() = 0;
else if ( aNewSelection.Max() > aText.getLength() )
aNewSelection.Max() = aText.getLength();
long nEnd = std::max( aNewSelection.Min(), aNewSelection.Max() );
TextSelection aTextSel;
sal_uLong nPara = 0;
sal_uInt16 nChar = 0;
sal_uInt16 x = 0;
while ( x <= nEnd )
{
if ( x == aNewSelection.Min() )
aTextSel.GetStart() = TextPaM( nPara, nChar );
if ( x == aNewSelection.Max() )
aTextSel.GetEnd() = TextPaM( nPara, nChar );
if ( ( x < aText.getLength() ) && ( aText[ x ] == '\n' ) )
{
nPara++;
nChar = 0;
}
else
nChar++;
x++;
}
mpTextWindow->GetTextView()->SetSelection( aTextSel );
}
const Selection& ImpVclMEdit::GetSelection() const
{
maSelection = Selection();
TextSelection aTextSel( mpTextWindow->GetTextView()->GetSelection() );
aTextSel.Justify();
// flatten selection => every line-break a character
ExtTextEngine* pExtTextEngine = mpTextWindow->GetTextEngine();
// paragraphs before
sal_uLong n;
for ( n = 0; n < aTextSel.GetStart().GetPara(); n++ )
{
maSelection.Min() += pExtTextEngine->GetTextLen( n );
maSelection.Min()++;
}
// first paragraph with selection
maSelection.Max() = maSelection.Min();
maSelection.Min() += aTextSel.GetStart().GetIndex();
for ( n = aTextSel.GetStart().GetPara(); n < aTextSel.GetEnd().GetPara(); n++ )
{
maSelection.Max() += pExtTextEngine->GetTextLen( n );
maSelection.Max()++;
}
maSelection.Max() += aTextSel.GetEnd().GetIndex();
return maSelection;
}
Size ImpVclMEdit::CalcMinimumSize() const
{
Size aSz( mpTextWindow->GetTextEngine()->CalcTextWidth(),
mpTextWindow->GetTextEngine()->GetTextHeight() );
if ( mpHScrollBar )
aSz.Height() += mpHScrollBar->GetSizePixel().Height();
if ( mpVScrollBar )
aSz.Width() += mpVScrollBar->GetSizePixel().Width();
return aSz;
}
Size ImpVclMEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
{
static const sal_Unicode sampleChar = 'X';
Size aSz;
Size aCharSz;
aCharSz.Width() = mpTextWindow->GetTextWidth( OUString(sampleChar) );
aCharSz.Height() = mpTextWindow->GetTextHeight();
if ( nLines )
aSz.Height() = nLines*aCharSz.Height();
else
aSz.Height() = mpTextWindow->GetTextEngine()->GetTextHeight();
if ( nColumns )
aSz.Width() = nColumns*aCharSz.Width();
else
aSz.Width() = mpTextWindow->GetTextEngine()->CalcTextWidth();
if ( mpHScrollBar )
aSz.Height() += mpHScrollBar->GetSizePixel().Height();
if ( mpVScrollBar )
aSz.Width() += mpVScrollBar->GetSizePixel().Width();
return aSz;
}
void ImpVclMEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
{
static const sal_Unicode sampleChar = { 'x' };
Size aOutSz = mpTextWindow->GetOutputSizePixel();
Size aCharSz( mpTextWindow->GetTextWidth( OUString(sampleChar) ), mpTextWindow->GetTextHeight() );
rnCols = (sal_uInt16) (aOutSz.Width()/aCharSz.Width());
rnLines = (sal_uInt16) (aOutSz.Height()/aCharSz.Height());
}
void ImpVclMEdit::Enable( bool bEnable )
{
mpTextWindow->Enable( bEnable );
if ( mpHScrollBar )
mpHScrollBar->Enable( bEnable );
if ( mpVScrollBar )
mpVScrollBar->Enable( bEnable );
}
bool ImpVclMEdit::HandleCommand( const CommandEvent& rCEvt )
{
bool bDone = false;
if ( ( rCEvt.GetCommand() == CommandEventId::Wheel ) ||
( rCEvt.GetCommand() == CommandEventId::StartAutoScroll ) ||
( rCEvt.GetCommand() == CommandEventId::AutoScroll ) )
{
mpTextWindow->HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
bDone = true;
}
return bDone;
}
TextWindow::TextWindow( vcl::Window* pParent ) : Window( pParent )
{
mbInMBDown = false;
mbFocusSelectionHide = false;
mbIgnoreTab = false;
mbActivePopup = false;
mbSelectOnTab = true;
mbTextSelectable = true;
SetPointer( Pointer( PointerStyle::Text ) );
mpExtTextEngine = new ExtTextEngine;
mpExtTextEngine->SetMaxTextLen(EDIT_NOLIMIT);
if( pParent->GetStyle() & WB_BORDER )
mpExtTextEngine->SetLeftMargin( 2 );
mpExtTextEngine->SetLocale( GetSettings().GetLanguageTag().getLocale() );
mpExtTextView = new ExtTextView( mpExtTextEngine, this );
mpExtTextEngine->InsertView( mpExtTextView );
mpExtTextEngine->EnableUndo( true );
mpExtTextView->ShowCursor();
Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor();
SetBackground( aBackgroundColor );
pParent->SetBackground( aBackgroundColor );
}
TextWindow::~TextWindow()
{
disposeOnce();
}
void TextWindow::dispose()
{
delete mpExtTextView;
mpExtTextView = NULL;
delete mpExtTextEngine;
mpExtTextEngine = NULL;
Window::dispose();
}
void TextWindow::MouseMove( const MouseEvent& rMEvt )
{
mpExtTextView->MouseMove( rMEvt );
Window::MouseMove( rMEvt );
}
void TextWindow::MouseButtonDown( const MouseEvent& rMEvt )
{
if ( !mbTextSelectable )
return;
mbInMBDown = true; // so that GetFocus does not select everything
mpExtTextView->MouseButtonDown( rMEvt );
GrabFocus();
mbInMBDown = false;
}
void TextWindow::MouseButtonUp( const MouseEvent& rMEvt )
{
mpExtTextView->MouseButtonUp( rMEvt );
}
void TextWindow::KeyInput( const KeyEvent& rKEvent )
{
bool bDone = false;
sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
if ( nCode == com::sun::star::awt::Key::SELECT_ALL ||
( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() )
)
{
mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) );
bDone = true;
}
else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() )
{
if ( Edit::GetGetSpecialCharsFunction() )
{
// to maintain the selection
mbActivePopup = true;
OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() );
if (!aChars.isEmpty())
{
mpExtTextView->InsertText( aChars );
mpExtTextView->GetTextEngine()->SetModified( true );
}
mbActivePopup = false;
bDone = true;
}
}
else if ( nCode == KEY_TAB )
{
if ( !mbIgnoreTab || rKEvent.GetKeyCode().IsMod1() )
bDone = mpExtTextView->KeyInput( rKEvent );
}
else
{
bDone = mpExtTextView->KeyInput( rKEvent );
}
if ( !bDone )
Window::KeyInput( rKEvent );
}
void TextWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
{
mpExtTextView->Paint(rRenderContext, rRect);
}
void TextWindow::Resize()
{
}
void TextWindow::Command( const CommandEvent& rCEvt )
{
if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
{
PopupMenu* pPopup = Edit::CreatePopupMenu();
if ( !mpExtTextView->HasSelection() )
{
pPopup->EnableItem( SV_MENU_EDIT_CUT, false );
pPopup->EnableItem( SV_MENU_EDIT_COPY, false );
pPopup->EnableItem( SV_MENU_EDIT_DELETE, false );
}
if ( mpExtTextView->IsReadOnly() )
{
pPopup->EnableItem( SV_MENU_EDIT_CUT, false );
pPopup->EnableItem( SV_MENU_EDIT_PASTE, false );
pPopup->EnableItem( SV_MENU_EDIT_DELETE, false );
pPopup->EnableItem( SV_MENU_EDIT_INSERTSYMBOL, false );
}
if ( !mpExtTextView->GetTextEngine()->HasUndoManager() || !mpExtTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() )
{
pPopup->EnableItem( SV_MENU_EDIT_UNDO, false );
}
// if ( ( maSelection.Min() == 0 ) && ( maSelection.Max() == maText.Len() ) )
// {
// pPopup->EnableItem( SV_MENU_EDIT_SELECTALL, false );
// }
if ( !Edit::GetGetSpecialCharsFunction() )
{
sal_uInt16 nPos = pPopup->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL );
pPopup->RemoveItem( nPos );
pPopup->RemoveItem( nPos-1 );
}
mbActivePopup = true;
Point aPos = rCEvt.GetMousePosPixel();
if ( !rCEvt.IsMouseEvent() )
{
// Sometime do show Menu centered in the selection !!!
Size aSize = GetOutputSizePixel();
aPos = Point( aSize.Width()/2, aSize.Height()/2 );
}
// pPopup->RemoveDisabledEntries();
sal_uInt16 n = pPopup->Execute( this, aPos );
Edit::DeletePopupMenu( pPopup );
switch ( n )
{
case SV_MENU_EDIT_UNDO: mpExtTextView->Undo();
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
break;
case SV_MENU_EDIT_CUT: mpExtTextView->Cut();
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
break;
case SV_MENU_EDIT_COPY: mpExtTextView->Copy();
break;
case SV_MENU_EDIT_PASTE: mpExtTextView->Paste();
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
break;
case SV_MENU_EDIT_DELETE: mpExtTextView->DeleteSelected();
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
break;
case SV_MENU_EDIT_SELECTALL: mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFFFFFF, 0xFFFF ) ) );
break;
case SV_MENU_EDIT_INSERTSYMBOL:
{
OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() );
if (!aChars.isEmpty())
{
mpExtTextView->InsertText( aChars );
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
}
}
break;
}
mbActivePopup = false;
}
else
{
mpExtTextView->Command( rCEvt );
}
Window::Command( rCEvt );
}
void TextWindow::GetFocus()
{
Window::GetFocus();
if ( !mbActivePopup )
{
bool bGotoCursor = !mpExtTextView->IsReadOnly();
if ( mbFocusSelectionHide && IsReallyVisible() && !mpExtTextView->IsReadOnly()
&& ( mbSelectOnTab &&
(!mbInMBDown || ( GetSettings().GetStyleSettings().GetSelectionOptions() & SelectionOptions::Focus ) )) )
{
// select everything, but do not scroll
bool bAutoScroll = mpExtTextView->IsAutoScroll();
mpExtTextView->SetAutoScroll( false );
mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) );
mpExtTextView->SetAutoScroll( bAutoScroll );
bGotoCursor = false;
}
mpExtTextView->SetPaintSelection( true );
mpExtTextView->ShowCursor( bGotoCursor );
}
}
void TextWindow::LoseFocus()
{
Window::LoseFocus();
if ( mbFocusSelectionHide && !mbActivePopup && mpExtTextView )
mpExtTextView->SetPaintSelection( false );
}
VclMultiLineEdit::VclMultiLineEdit( vcl::Window* pParent, WinBits nWinStyle )
: Edit( pParent, nWinStyle )
{
SetType( WINDOW_MULTILINEEDIT );
pImpVclMEdit = new ImpVclMEdit( this, nWinStyle );
ImplInitSettings( true, true, true );
pUpdateDataTimer = 0;
SetCompoundControl( true );
SetStyle( ImplInitStyle( nWinStyle ) );
}
VclMultiLineEdit::~VclMultiLineEdit()
{
disposeOnce();
}
void VclMultiLineEdit::dispose()
{
{
std::unique_ptr< ImpVclMEdit > xDelete(pImpVclMEdit);
pImpVclMEdit = NULL;
}
delete pUpdateDataTimer;
pUpdateDataTimer = NULL;
Edit::dispose();
}
WinBits VclMultiLineEdit::ImplInitStyle( WinBits nStyle )
{
if ( !(nStyle & WB_NOTABSTOP) )
nStyle |= WB_TABSTOP;
if ( !(nStyle & WB_NOGROUP) )
nStyle |= WB_GROUP;
if ( !(nStyle & WB_IGNORETAB ))
nStyle |= WB_NODIALOGCONTROL;
return nStyle;
}
void VclMultiLineEdit::ApplySettings(vcl::RenderContext& rRenderContext)
{
const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
// The Font has to be adjusted, as the TextEngine does not take care of
// TextColor/Background
Color aTextColor = rStyleSettings.GetFieldTextColor();
if (IsControlForeground())
aTextColor = GetControlForeground();
if (!IsEnabled())
aTextColor = rStyleSettings.GetDisableColor();
vcl::Font aFont = rStyleSettings.GetFieldFont();
aFont.SetTransparent(IsPaintTransparent());
ApplyControlFont(rRenderContext, aFont);
vcl::Font theFont = rRenderContext.GetFont();
theFont.SetColor(aTextColor);
if (IsPaintTransparent())
theFont.SetFillColor(Color(COL_TRANSPARENT));
else
theFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
pImpVclMEdit->GetTextWindow()->SetFont(theFont);
// FIXME: next call causes infinite invalidation loop, rethink how to properly fix this situation
// pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(theFont);
pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
if (IsPaintTransparent())
{
pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
pImpVclMEdit->GetTextWindow()->SetBackground();
pImpVclMEdit->GetTextWindow()->SetControlBackground();
rRenderContext.SetBackground();
SetControlBackground();
}
else
{
if (IsControlBackground())
pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
else
pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
// also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
rRenderContext.SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
}
}
void VclMultiLineEdit::ImplInitSettings(bool /*bFont*/, bool /*bForeground*/, bool bBackground)
{
const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
// The Font has to be adjusted, as the TextEngine does not take care of
// TextColor/Background
Color aTextColor = rStyleSettings.GetFieldTextColor();
if (IsControlForeground())
aTextColor = GetControlForeground();
if (!IsEnabled())
aTextColor = rStyleSettings.GetDisableColor();
vcl::Font aFont = rStyleSettings.GetFieldFont();
aFont.SetTransparent(IsPaintTransparent());
ApplyControlFont(*this, aFont);
vcl::Font TheFont = GetFont();
TheFont.SetColor(aTextColor);
if (IsPaintTransparent())
TheFont.SetFillColor(Color(COL_TRANSPARENT));
else
TheFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
pImpVclMEdit->GetTextWindow()->SetFont(TheFont);
pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(TheFont);
pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
if (bBackground)
{
if (IsPaintTransparent())
{
pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
pImpVclMEdit->GetTextWindow()->SetBackground();
pImpVclMEdit->GetTextWindow()->SetControlBackground();
SetBackground();
SetControlBackground();
}
else
{
if (IsControlBackground())
pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
else
pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
// also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
}
}
}
void VclMultiLineEdit::Modify()
{
aModifyHdlLink.Call( this );
CallEventListeners( VCLEVENT_EDIT_MODIFY );
if ( pUpdateDataTimer )
pUpdateDataTimer->Start();
}
void VclMultiLineEdit::SelectionChanged()
{
CallEventListeners(VCLEVENT_EDIT_SELECTIONCHANGED);
}
void VclMultiLineEdit::CaretChanged()
{
CallEventListeners(VCLEVENT_EDIT_CARETCHANGED);
}
IMPL_LINK_NOARG_TYPED(VclMultiLineEdit, ImpUpdateDataHdl, Timer *, void)
{
UpdateData();
}
void VclMultiLineEdit::UpdateData()
{
aUpdateDataHdlLink.Call( this );
}
void VclMultiLineEdit::SetModifyFlag()
{
pImpVclMEdit->SetModified( true );
}
void VclMultiLineEdit::ClearModifyFlag()
{
pImpVclMEdit->SetModified( false );
}
bool VclMultiLineEdit::IsModified() const
{
return pImpVclMEdit->IsModified();
}
void VclMultiLineEdit::EnableUpdateData( sal_uLong nTimeout )
{
if ( !nTimeout )
DisableUpdateData();
else
{
if ( !pUpdateDataTimer )
{
pUpdateDataTimer = new Timer;
pUpdateDataTimer->SetTimeoutHdl( LINK( this, VclMultiLineEdit, ImpUpdateDataHdl ) );
}
pUpdateDataTimer->SetTimeout( nTimeout );
}
}
void VclMultiLineEdit::SetReadOnly( bool bReadOnly )
{
pImpVclMEdit->SetReadOnly( bReadOnly );
Edit::SetReadOnly( bReadOnly );
// #94921# ReadOnly can be overwritten in InitFromStyle() when WB not set.
WinBits nStyle = GetStyle();
if ( bReadOnly )
nStyle |= WB_READONLY;
else
nStyle &= ~WB_READONLY;
SetStyle( nStyle );
}
bool VclMultiLineEdit::IsReadOnly() const
{
return pImpVclMEdit->IsReadOnly();
}
void VclMultiLineEdit::SetMaxTextLen(sal_Int32 nMaxLen)
{
pImpVclMEdit->SetMaxTextLen(nMaxLen);
}
void VclMultiLineEdit::SetMaxTextWidth( sal_uLong nMaxWidth )
{
pImpVclMEdit->SetMaxTextWidth(nMaxWidth );
}
sal_Int32 VclMultiLineEdit::GetMaxTextLen() const
{
return pImpVclMEdit->GetMaxTextLen();
}
void VclMultiLineEdit::ReplaceSelected( const OUString& rStr )
{
pImpVclMEdit->InsertText( rStr );
}
void VclMultiLineEdit::DeleteSelected()
{
pImpVclMEdit->InsertText( OUString() );
}
OUString VclMultiLineEdit::GetSelected() const
{
return pImpVclMEdit->GetSelected();
}
OUString VclMultiLineEdit::GetSelected( LineEnd aSeparator ) const
{
return pImpVclMEdit->GetSelected( aSeparator );
}
void VclMultiLineEdit::Cut()
{
pImpVclMEdit->Cut();
}
void VclMultiLineEdit::Copy()
{
pImpVclMEdit->Copy();
}
void VclMultiLineEdit::Paste()
{
pImpVclMEdit->Paste();
}
void VclMultiLineEdit::SetText( const OUString& rStr )
{
pImpVclMEdit->SetText( rStr );
}
OUString VclMultiLineEdit::GetText() const
{
return pImpVclMEdit ? pImpVclMEdit->GetText() : OUString("");
}
OUString VclMultiLineEdit::GetText( LineEnd aSeparator ) const
{
return pImpVclMEdit ? pImpVclMEdit->GetText( aSeparator ) : OUString("");
}
OUString VclMultiLineEdit::GetTextLines( LineEnd aSeparator ) const
{
return pImpVclMEdit ? pImpVclMEdit->GetTextLines( aSeparator ) : OUString("");
}
void VclMultiLineEdit::Resize()
{
pImpVclMEdit->Resize();
}
void VclMultiLineEdit::GetFocus()
{
if ( !pImpVclMEdit ) // might be called from within the dtor, when pImpVclMEdit == NULL is a valid state
return;
pImpVclMEdit->GetFocus();
}
void VclMultiLineEdit::SetSelection( const Selection& rSelection )
{
pImpVclMEdit->SetSelection( rSelection );
}
const Selection& VclMultiLineEdit::GetSelection() const
{
return pImpVclMEdit->GetSelection();
}
Size VclMultiLineEdit::CalcMinimumSize() const
{
Size aSz = pImpVclMEdit->CalcMinimumSize();
sal_Int32 nLeft, nTop, nRight, nBottom;
static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
aSz.Width() += nLeft+nRight;
aSz.Height() += nTop+nBottom;
return aSz;
}
Size VclMultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const
{
Size aSz = rPrefSize;
sal_Int32 nLeft, nTop, nRight, nBottom;
static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
// center vertically for whole lines
long nHeight = aSz.Height() - nTop - nBottom;
long nLineHeight = pImpVclMEdit->CalcBlockSize( 1, 1 ).Height();
long nLines = nHeight / nLineHeight;
if ( nLines < 1 )
nLines = 1;
aSz.Height() = nLines * nLineHeight;
aSz.Height() += nTop+nBottom;
return aSz;
}
Size VclMultiLineEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
{
Size aSz = pImpVclMEdit->CalcBlockSize( nColumns, nLines );
sal_Int32 nLeft, nTop, nRight, nBottom;
static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
aSz.Width() += nLeft+nRight;
aSz.Height() += nTop+nBottom;
return aSz;
}
void VclMultiLineEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
{
pImpVclMEdit->GetMaxVisColumnsAndLines( rnCols, rnLines );
}
void VclMultiLineEdit::StateChanged( StateChangedType nType )
{
if( nType == StateChangedType::Enable )
{
pImpVclMEdit->Enable( IsEnabled() );
ImplInitSettings( true, false, false );
}
else if( nType == StateChangedType::ReadOnly )
{
pImpVclMEdit->SetReadOnly( IsReadOnly() );
}
else if ( nType == StateChangedType::Zoom )
{
pImpVclMEdit->GetTextWindow()->SetZoom( GetZoom() );
ImplInitSettings( true, false, false );
Resize();
}
else if ( nType == StateChangedType::ControlFont )
{
ImplInitSettings( true, false, false );
Resize();
Invalidate();
}
else if ( nType == StateChangedType::ControlForeground )
{
ImplInitSettings( false, true, false );
Invalidate();
}
else if ( nType == StateChangedType::ControlBackground )
{
ImplInitSettings( false, false, true );
Invalidate();
}
else if ( nType == StateChangedType::Style )
{
pImpVclMEdit->InitFromStyle( GetStyle() );
SetStyle( ImplInitStyle( GetStyle() ) );
}
else if ( nType == StateChangedType::InitShow )
{
if( IsPaintTransparent() )
{
pImpVclMEdit->GetTextWindow()->SetPaintTransparent( true );
pImpVclMEdit->GetTextWindow()->SetBackground();
pImpVclMEdit->GetTextWindow()->SetControlBackground();
SetBackground();
SetControlBackground();
}
}
Control::StateChanged( nType );
}
void VclMultiLineEdit::DataChanged( const DataChangedEvent& rDCEvt )
{
if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
(rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
{
ImplInitSettings( true, true, true );
Resize();
Invalidate();
}
else
Control::DataChanged( rDCEvt );
}
void VclMultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, DrawFlags nFlags )
{
ImplInitSettings( true, true, true );
Point aPos = pDev->LogicToPixel( rPos );
Size aSize = pDev->LogicToPixel( rSize );
vcl::Font aFont = pImpVclMEdit->GetTextWindow()->GetDrawPixelFont( pDev );
aFont.SetTransparent( true );
OutDevType eOutDevType = pDev->GetOutDevType();
pDev->Push();
pDev->SetMapMode();
pDev->SetFont( aFont );
pDev->SetTextFillColor();
// Border/Background
pDev->SetLineColor();
pDev->SetFillColor();
bool bBorder = !(nFlags & DrawFlags::NoBorder ) && (GetStyle() & WB_BORDER);
bool bBackground = !(nFlags & DrawFlags::NoBackground) && IsControlBackground();
if ( bBorder || bBackground )
{
Rectangle aRect( aPos, aSize );
if ( bBorder )
{
DecorationView aDecoView( pDev );
aRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleIn );
}
if ( bBackground )
{
pDev->SetFillColor( GetControlBackground() );
pDev->DrawRect( aRect );
}
}
// contents
if ( ( nFlags & DrawFlags::Mono ) || ( eOutDevType == OUTDEV_PRINTER ) )
pDev->SetTextColor( Color( COL_BLACK ) );
else
{
if ( !(nFlags & DrawFlags::NoDisable ) && !IsEnabled() )
{
const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
pDev->SetTextColor( rStyleSettings.GetDisableColor() );
}
else
{
pDev->SetTextColor( GetTextColor() );
}
}
OUString aText = GetText();
Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() );
sal_uLong nLines = (sal_uLong) (aSize.Height() / aTextSz.Height());
if ( !nLines )
nLines = 1;
aTextSz.Height() = nLines*aTextSz.Height();
long nOnePixel = GetDrawPixel( pDev, 1 );
long nOffX = 3*nOnePixel;
long nOffY = 2*nOnePixel;
// Clipping?
if ( ( nOffY < 0 ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) )
{
Rectangle aClip( aPos, aSize );
if ( aTextSz.Height() > aSize.Height() )
aClip.Bottom() += aTextSz.Height() - aSize.Height() + 1; // so that HP-printer does not 'optimize-away'
pDev->IntersectClipRegion( aClip );
}
ExtTextEngine aTE;
aTE.SetText( GetText() );
aTE.SetMaxTextWidth( aSize.Width() );
aTE.SetFont( aFont );
aTE.SetTextAlign( pImpVclMEdit->GetTextWindow()->GetTextEngine()->GetTextAlign() );
aTE.Draw( pDev, Point( aPos.X() + nOffX, aPos.Y() + nOffY ) );
pDev->Pop();
}
bool VclMultiLineEdit::Notify( NotifyEvent& rNEvt )
{
bool nDone = false;
if( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
{
nDone = pImpVclMEdit->HandleCommand( *rNEvt.GetCommandEvent() );
}
return nDone || Edit::Notify( rNEvt );
}
bool VclMultiLineEdit::PreNotify( NotifyEvent& rNEvt )
{
bool nDone = false;
if( ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) )
{
const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) )
{
nDone = true;
TextSelection aSel = pImpVclMEdit->GetTextWindow()->GetTextView()->GetSelection();
if ( aSel.HasRange() )
{
aSel.GetStart() = aSel.GetEnd();
pImpVclMEdit->GetTextWindow()->GetTextView()->SetSelection( aSel );
}
else
{
switch ( rKEvent.GetKeyCode().GetCode() )
{
case KEY_UP:
{
if ( pImpVclMEdit->GetVScrollBar() )
pImpVclMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEUP );
}
break;
case KEY_DOWN:
{
if ( pImpVclMEdit->GetVScrollBar() )
pImpVclMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEDOWN );
}
break;
case KEY_PAGEUP :
{
if ( pImpVclMEdit->GetVScrollBar() )
pImpVclMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEUP );
}
break;
case KEY_PAGEDOWN:
{
if ( pImpVclMEdit->GetVScrollBar() )
pImpVclMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEDOWN );
}
break;
case KEY_LEFT:
{
if ( pImpVclMEdit->GetHScrollBar() )
pImpVclMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEUP );
}
break;
case KEY_RIGHT:
{
if ( pImpVclMEdit->GetHScrollBar() )
pImpVclMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEDOWN );
}
break;
case KEY_HOME:
{
if ( rKEvent.GetKeyCode().IsMod1() )
pImpVclMEdit->GetTextWindow()->GetTextView()->
SetSelection( TextSelection( TextPaM( 0, 0 ) ) );
}
break;
case KEY_END:
{
if ( rKEvent.GetKeyCode().IsMod1() )
pImpVclMEdit->GetTextWindow()->GetTextView()->
SetSelection( TextSelection( TextPaM( 0xFFFF, 0xFFFF ) ) );
}
break;
default:
{
nDone = false;
}
}
}
}
}
return nDone || Edit::PreNotify( rNEvt );
}
// Internals for derived classes, e.g. TextComponent
ExtTextEngine* VclMultiLineEdit::GetTextEngine() const
{
return pImpVclMEdit->GetTextWindow()->GetTextEngine();
}
ExtTextView* VclMultiLineEdit::GetTextView() const
{
return pImpVclMEdit->GetTextWindow()->GetTextView();
}
ScrollBar* VclMultiLineEdit::GetVScrollBar() const
{
return pImpVclMEdit->GetVScrollBar();
}
void VclMultiLineEdit::EnableFocusSelectionHide( bool bHide )
{
pImpVclMEdit->GetTextWindow()->SetAutoFocusHide( bHide );
}
void VclMultiLineEdit::SetLeftMargin( sal_uInt16 n )
{
if ( GetTextEngine() )
GetTextEngine()->SetLeftMargin( n );
}
void VclMultiLineEdit::SetRightToLeft( bool bRightToLeft )
{
if ( GetTextEngine() )
{
GetTextEngine()->SetRightToLeft( bRightToLeft );
GetTextView()->ShowCursor();
}
}
void VclMultiLineEdit::DisableSelectionOnFocus()
{
pImpVclMEdit->GetTextWindow()->DisableSelectionOnFocus();
}
void VclMultiLineEdit::EnableCursor( bool bEnable )
{
GetTextView()->EnableCursor( bEnable );
}
bool VclMultiLineEdit::set_property(const OString &rKey, const OString &rValue)
{
if (rKey == "cursor-visible")
EnableCursor(toBool(rValue));
else if (rKey == "accepts-tab")
pImpVclMEdit->GetTextWindow()->SetIgnoreTab(!toBool(rValue));
else
return Edit::set_property(rKey, rValue);
return true;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */