1
0
Fork 0
libreoffice/vcl/source/edit/vclmedit.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

1505 lines
46 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 <memory>
#include <i18nlangtag/languagetag.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/builder.hxx>
#include <vcl/decoview.hxx>
#include <vcl/event.hxx>
#include <vcl/menu.hxx>
#include <vcl/specialchars.hxx>
#include <vcl/timer.hxx>
#include <vcl/vclevent.hxx>
#include <vcl/xtextedt.hxx>
#include <vcl/textview.hxx>
#include <vcl/ptrstyle.hxx>
#include <svl/undo.hxx>
#include <svl/lstner.hxx>
#include <vcl/uitest/uiobject.hxx>
#include <vcl/settings.hxx>
#include <vcl/toolkit/scrbar.hxx>
#include <vcl/toolkit/vclmedit.hxx>
#include <vcl/weld.hxx>
#include <osl/diagnose.h>
#include <tools/json_writer.hxx>
#include <strings.hrc>
#include <svdata.hxx>
class ImpVclMEdit : public SfxListener
{
private:
VclPtr<VclMultiLineEdit> pVclMultiLineEdit;
VclPtr<TextWindow> mpTextWindow;
VclPtr<ScrollBar> mpHScrollBar;
VclPtr<ScrollBar> mpVScrollBar;
VclPtr<ScrollBarBox> mpScrollBox;
tools::Long mnTextWidth;
mutable Selection maSelection;
protected:
virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
void ImpUpdateScrollBarVis( WinBits nWinStyle );
void ImpInitScrollBars();
void ImpSetScrollBarRanges();
void ImpSetHScrollBarThumbPos();
DECL_LINK( ScrollHdl, ScrollBar*, void );
public:
ImpVclMEdit( VclMultiLineEdit* pVclMultiLineEdit, WinBits nWinStyle );
virtual ~ImpVclMEdit() override;
void SetModified( bool bMod );
void SetReadOnly( bool bRdOnly );
bool IsReadOnly() const;
void SetMaxTextLen(sal_Int32 nLen);
sal_Int32 GetMaxTextLen() const;
void SetMaxTextWidth(tools::Long 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 )
: pVclMultiLineEdit(pEdt)
, mpTextWindow(VclPtr<TextWindow>::Create(pEdt))
, mpHScrollBar(VclPtr<ScrollBar>::Create(pVclMultiLineEdit, WB_HSCROLL|WB_DRAG))
, mpVScrollBar(VclPtr<ScrollBar>::Create(pVclMultiLineEdit, WB_VSCROLL|WB_DRAG))
, mpScrollBox(VclPtr<ScrollBarBox>::Create(pVclMultiLineEdit, WB_SIZEABLE))
, mnTextWidth(0)
{
mpVScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
mpHScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
mpTextWindow->Show();
InitFromStyle( nWinStyle );
StartListening( *mpTextWindow->GetTextEngine() );
}
void ImpVclMEdit::ImpUpdateScrollBarVis( WinBits nWinStyle )
{
const bool bHaveVScroll = mpVScrollBar->IsVisible();
const bool bHaveHScroll = mpHScrollBar->IsVisible();
const bool bHaveScrollBox = mpScrollBox->IsVisible();
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() );
tools::Long nOverallTextHeight(0);
for ( sal_uInt32 i=0; i<rEngine.GetParagraphCount(); ++i )
nOverallTextHeight += rEngine.GetTextHeight( i );
if ( nOverallTextHeight > mpTextWindow->GetOutputSizePixel().Height() )
bNeedVScroll = true;
}
const bool bNeedScrollBox = bNeedVScroll && bNeedHScroll;
bool bScrollbarsChanged = false;
if ( bHaveVScroll != bNeedVScroll )
{
mpVScrollBar->Show(bNeedVScroll);
bScrollbarsChanged = true;
}
if ( bHaveHScroll != bNeedHScroll )
{
mpHScrollBar->Show(bNeedHScroll);
bScrollbarsChanged = true;
}
if ( bHaveScrollBox != bNeedScrollBox )
{
mpScrollBox->Show(bNeedScrollBox);
}
if ( bScrollbarsChanged )
{
ImpInitScrollBars();
Resize();
}
}
void ImpVclMEdit::InitFromStyle( WinBits nWinStyle )
{
ImpUpdateScrollBarVis( 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()
{
const tools::Long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
mpVScrollBar->SetRange( Range( 0, nTextHeight-1 ) );
mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
}
void ImpVclMEdit::ImpInitScrollBars()
{
static const sal_Unicode sampleChar = { 'x' };
ImpSetScrollBarRanges();
Size aCharBox;
aCharBox.setWidth( mpTextWindow->GetTextWidth( OUString(sampleChar) ) );
aCharBox.setHeight( mpTextWindow->GetTextHeight() );
Size aOutSz = mpTextWindow->GetOutputSizePixel();
mpHScrollBar->SetVisibleSize( aOutSz.Width() );
mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 );
mpHScrollBar->SetLineSize( aCharBox.Width()*10 );
ImpSetHScrollBarThumbPos();
mpVScrollBar->SetVisibleSize( aOutSz.Height() );
mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 );
mpVScrollBar->SetLineSize( aCharBox.Height() );
mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
}
void ImpVclMEdit::ImpSetHScrollBarThumbPos()
{
tools::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, void )
{
tools::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 );
}
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 );
}
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(tools::Long nMaxWidth)
{
mpTextWindow->GetTextEngine()->SetMaxTextWidth(nMaxWidth);
}
void ImpVclMEdit::Resize()
{
int nIteration = 1;
do
{
WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
ImpUpdateScrollBarVis( nWinStyle );
Size aSz = pVclMultiLineEdit->GetOutputSizePixel();
Size aEditSize = aSz;
tools::Long nSBWidth = pVclMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize();
nSBWidth = pVclMultiLineEdit->CalcZoom( nSBWidth );
if (mpHScrollBar->IsVisible())
aSz.AdjustHeight( -(nSBWidth+1) );
if (mpVScrollBar->IsVisible())
aSz.AdjustWidth( -(nSBWidth+1) );
if (!mpHScrollBar->IsVisible())
mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() );
else
mpHScrollBar->setPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth );
Point aTextWindowPos;
if (mpVScrollBar->IsVisible())
{
if( AllSettings::GetLayoutRTL() )
{
mpVScrollBar->setPosSizePixel( 0, 0, nSBWidth, aSz.Height() );
aTextWindowPos.AdjustX(nSBWidth );
}
else
mpVScrollBar->setPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() );
}
if (mpScrollBox->IsVisible())
mpScrollBox->setPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth );
Size aTextWindowSize( aSz );
if ( aTextWindowSize.Width() < 0 )
aTextWindowSize.setWidth( 0 );
if ( aTextWindowSize.Height() < 0 )
aTextWindowSize.setHeight( 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 )
ImpUpdateScrollBarVis( 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 )
{
switch (rHint.GetId())
{
case SfxHintId::TextViewScrolled:
if (mpHScrollBar->IsVisible())
ImpSetHScrollBarThumbPos();
if (mpVScrollBar->IsVisible())
mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
break;
case SfxHintId::TextHeightChanged:
if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() )
{
tools::Long nOutHeight = mpTextWindow->GetOutputSizePixel().Height();
tools::Long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
if ( nTextHeight < nOutHeight )
mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() );
}
ImpSetScrollBarRanges();
break;
case SfxHintId::TextFormatted:
if (mpHScrollBar->IsVisible())
{
const tools::Long nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
if ( nWidth != mnTextWidth )
{
mnTextWidth = nWidth;
mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
ImpSetHScrollBarThumbPos();
}
}
break;
case SfxHintId::TextModified:
ImpUpdateScrollBarVis(pVclMultiLineEdit->GetStyle());
pVclMultiLineEdit->Modify();
break;
case SfxHintId::TextViewSelectionChanged:
pVclMultiLineEdit->SelectionChanged();
break;
case SfxHintId::TextViewCaretChanged:
pVclMultiLineEdit->CaretChanged();
break;
default: break;
}
}
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();
tools::Long nEnd = std::max( aNewSelection.Min(), aNewSelection.Max() );
TextSelection aTextSel;
sal_uInt32 nPara = 0;
sal_Int32 nChar = 0;
tools::Long 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
for ( sal_uInt32 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 ( sal_uInt32 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->IsVisible())
aSz.AdjustHeight(mpHScrollBar->GetSizePixel().Height() );
if (mpVScrollBar->IsVisible())
aSz.AdjustWidth(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.setWidth( mpTextWindow->GetTextWidth( OUString(sampleChar) ) );
aCharSz.setHeight( mpTextWindow->GetTextHeight() );
if ( nLines )
aSz.setHeight( nLines*aCharSz.Height() );
else
aSz.setHeight( mpTextWindow->GetTextEngine()->GetTextHeight() );
if ( nColumns )
aSz.setWidth( nColumns*aCharSz.Width() );
else
aSz.setWidth( mpTextWindow->GetTextEngine()->CalcTextWidth() );
if (mpHScrollBar->IsVisible())
aSz.AdjustHeight(mpHScrollBar->GetSizePixel().Height() );
if (mpVScrollBar->IsVisible())
aSz.AdjustWidth(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 = static_cast<sal_uInt16>(aOutSz.Width()/aCharSz.Width());
rnLines = static_cast<sal_uInt16>(aOutSz.Height()/aCharSz.Height());
}
void ImpVclMEdit::Enable( bool bEnable )
{
mpTextWindow->Enable( bEnable );
if (mpHScrollBar->IsVisible())
mpHScrollBar->Enable( bEnable );
if (mpVScrollBar->IsVisible())
mpVScrollBar->Enable( bEnable );
}
bool ImpVclMEdit::HandleCommand( const CommandEvent& rCEvt )
{
bool bDone = false;
CommandEventId nCommand = rCEvt.GetCommand();
if (nCommand == CommandEventId::Wheel ||
nCommand == CommandEventId::StartAutoScroll ||
nCommand == CommandEventId::AutoScroll ||
nCommand == CommandEventId::GesturePan)
{
ScrollBar* pHScrollBar = mpHScrollBar->IsVisible() ? mpHScrollBar.get() : nullptr;
ScrollBar* pVScrollBar = mpVScrollBar->IsVisible() ? mpVScrollBar.get() : nullptr;
mpTextWindow->HandleScrollCommand(rCEvt, pHScrollBar, pVScrollBar);
bDone = true;
}
return bDone;
}
TextWindow::TextWindow(Edit* pParent)
: Window(pParent)
, mxParent(pParent)
{
mbInMBDown = false;
mbFocusSelectionHide = false;
mbIgnoreTab = false;
mbActivePopup = false;
mbSelectOnTab = true;
SetPointer( PointerStyle::Text );
mpExtTextEngine.reset(new ExtTextEngine);
mpExtTextEngine->SetMaxTextLen(EDIT_NOLIMIT);
if( pParent->GetStyle() & WB_BORDER )
mpExtTextEngine->SetLeftMargin( 2 );
mpExtTextEngine->SetLocale( GetSettings().GetLanguageTag().getLocale() );
mpExtTextView.reset(new TextView( mpExtTextEngine.get(), this ));
mpExtTextEngine->InsertView( mpExtTextView.get() );
mpExtTextEngine->EnableUndo( true );
mpExtTextView->ShowCursor();
Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor();
SetBackground( aBackgroundColor );
pParent->SetBackground( aBackgroundColor );
}
TextWindow::~TextWindow()
{
disposeOnce();
}
void TextWindow::dispose()
{
mxParent.clear();
mpExtTextView.reset();
mpExtTextEngine.reset();
Window::dispose();
}
void TextWindow::MouseMove( const MouseEvent& rMEvt )
{
mpExtTextView->MouseMove( rMEvt );
Window::MouseMove( rMEvt );
}
void TextWindow::MouseButtonDown( const MouseEvent& rMEvt )
{
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 == css::awt::Key::SELECT_ALL ||
( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() )
)
{
mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
bDone = true;
}
else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() )
{
if ( vcl::GetGetSpecialCharsFunction() )
{
// to maintain the selection
mbActivePopup = true;
OUString aChars = vcl::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont());
if (!aChars.isEmpty())
{
mpExtTextView->InsertText( aChars );
mpExtTextView->GetTextEngine()->SetModified( true );
}
mbActivePopup = false;
bDone = true;
}
}
else if ( nCode == KEY_TAB )
{
if (!mbIgnoreTab)
{
if (!rKEvent.GetKeyCode().IsMod1())
bDone = mpExtTextView->KeyInput(rKEvent);
else
{
// tdf#107625 make ctrl+tab act like tab when MultiLine Edit normally accepts tab as an input char
vcl::KeyCode aKeyCode(rKEvent.GetKeyCode().GetCode(), rKEvent.GetKeyCode().GetModifier() & ~KEY_MOD1);
KeyEvent aKEventWithoutMod1(rKEvent.GetCharCode(), aKeyCode, rKEvent.GetRepeat());
Window::KeyInput(aKEventWithoutMod1);
bDone = true;
}
}
}
else
{
bDone = mpExtTextView->KeyInput( rKEvent );
}
if ( !bDone )
Window::KeyInput( rKEvent );
}
void TextWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
{
mpExtTextView->Paint(rRenderContext, rRect);
}
void TextWindow::Resize()
{
}
void TextWindow::Command( const CommandEvent& rCEvt )
{
if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
{
VclPtr<PopupMenu> pPopup = mxParent->CreatePopupMenu();
bool bEnableCut = true;
bool bEnableCopy = true;
bool bEnableDelete = true;
bool bEnablePaste = true;
bool bEnableSpecialChar = true;
bool bEnableUndo = true;
if ( !mpExtTextView->HasSelection() )
{
bEnableCut = false;
bEnableCopy = false;
bEnableDelete = false;
}
if ( mpExtTextView->IsReadOnly() )
{
bEnableCut = false;
bEnablePaste = false;
bEnableDelete = false;
bEnableSpecialChar = false;
}
if ( !mpExtTextView->GetTextEngine()->HasUndoManager() || !mpExtTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() )
{
bEnableUndo = false;
}
pPopup->EnableItem(pPopup->GetItemId(u"cut"), bEnableCut);
pPopup->EnableItem(pPopup->GetItemId(u"copy"), bEnableCopy);
pPopup->EnableItem(pPopup->GetItemId(u"delete"), bEnableDelete);
pPopup->EnableItem(pPopup->GetItemId(u"paste"), bEnablePaste);
pPopup->SetItemText(pPopup->GetItemId(u"specialchar"),
BuilderUtils::convertMnemonicMarkup(VclResId(STR_SPECIAL_CHARACTER_MENU_ENTRY)));
pPopup->EnableItem(pPopup->GetItemId(u"specialchar"), bEnableSpecialChar);
pPopup->EnableItem(pPopup->GetItemId(u"undo"), bEnableUndo);
pPopup->ShowItem(pPopup->GetItemId(u"specialchar"), !vcl::GetGetSpecialCharsFunction());
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 );
}
sal_uInt16 n = pPopup->Execute( this, aPos );
OUString sCommand = pPopup->GetItemIdent(n);
if (sCommand == "undo")
{
mpExtTextView->Undo();
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
}
else if (sCommand == "cut")
{
mpExtTextView->Cut();
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
}
else if (sCommand == "copy")
{
mpExtTextView->Copy();
}
else if (sCommand == "paste")
{
mpExtTextView->Paste();
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
}
else if (sCommand == "delete")
{
mpExtTextView->DeleteSelected();
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
}
else if (sCommand == "selectall")
{
mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
}
else if (sCommand == "specialchar")
{
OUString aChars = vcl::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont());
if (!aChars.isEmpty())
{
mpExtTextView->InsertText( aChars );
mpExtTextEngine->SetModified( true );
mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
}
}
pPopup.clear();
mbActivePopup = false;
}
else
{
mpExtTextView->Command( rCEvt );
}
Window::Command( rCEvt );
}
void TextWindow::GetFocus()
{
Window::GetFocus();
if ( mbActivePopup )
return;
bool bGotoCursor = !mpExtTextView->IsReadOnly();
if ( mbFocusSelectionHide && IsReallyVisible() && mbSelectOnTab && !mbInMBDown )
{
// select everything, but do not scroll
bool bAutoScroll = mpExtTextView->IsAutoScroll();
mpExtTextView->SetAutoScroll( false );
mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
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( WindowType::MULTILINEEDIT );
pImpVclMEdit.reset(new ImpVclMEdit( this, nWinStyle ));
ImplInitSettings( true );
SetCompoundControl( true );
SetStyle( ImplInitStyle( nWinStyle ) );
}
VclMultiLineEdit::~VclMultiLineEdit()
{
disposeOnce();
}
void VclMultiLineEdit::dispose()
{
pImpVclMEdit.reset();
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(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 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(*GetOutDev(), aFont);
vcl::Font TheFont = GetFont();
TheFont.SetColor(aTextColor);
if (IsPaintTransparent())
TheFont.SetFillColor(COL_TRANSPARENT);
else
TheFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
pImpVclMEdit->GetTextWindow()->SetFont(TheFont);
pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(TheFont);
pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
if (!bBackground)
return;
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( VclEventId::EditModify );
}
void VclMultiLineEdit::SelectionChanged()
{
CallEventListeners(VclEventId::EditSelectionChanged);
}
void VclMultiLineEdit::CaretChanged()
{
CallEventListeners(VclEventId::EditCaretChanged);
}
void VclMultiLineEdit::SetModifyFlag()
{
pImpVclMEdit->SetModified( true );
}
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
{
if (!pImpVclMEdit) // might be called from within the dtor, when pImpVclMEdit == NULL is a valid state
return true;
return pImpVclMEdit->IsReadOnly();
}
void VclMultiLineEdit::SetMaxTextLen(sal_Int32 nMaxLen)
{
pImpVclMEdit->SetMaxTextLen(nMaxLen);
}
void VclMultiLineEdit::SetMaxTextWidth(tools::Long 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;
GetBorder(nLeft, nTop, nRight, nBottom);
aSz.AdjustWidth(nLeft+nRight );
aSz.AdjustHeight(nTop+nBottom );
return aSz;
}
Size VclMultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const
{
Size aSz = rPrefSize;
sal_Int32 nLeft, nTop, nRight, nBottom;
GetBorder(nLeft, nTop, nRight, nBottom);
// center vertically for whole lines
tools::Long nHeight = aSz.Height() - nTop - nBottom;
tools::Long nLineHeight = pImpVclMEdit->CalcBlockSize( 1, 1 ).Height();
tools::Long nLines = nHeight / nLineHeight;
if ( nLines < 1 )
nLines = 1;
aSz.setHeight( nLines * nLineHeight );
aSz.AdjustHeight(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;
GetBorder(nLeft, nTop, nRight, nBottom);
aSz.AdjustWidth(nLeft+nRight );
aSz.AdjustHeight(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( false );
}
else if( nType == StateChangedType::ReadOnly )
{
pImpVclMEdit->SetReadOnly( IsReadOnly() );
}
else if ( nType == StateChangedType::Zoom )
{
pImpVclMEdit->GetTextWindow()->SetZoom( GetZoom() );
ImplInitSettings( false );
Resize();
}
else if ( nType == StateChangedType::ControlFont )
{
ImplInitSettings( false );
Resize();
Invalidate();
}
else if ( nType == StateChangedType::ControlForeground )
{
ImplInitSettings( false );
Invalidate();
}
else if ( nType == StateChangedType::ControlBackground )
{
ImplInitSettings( 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 );
Resize();
Invalidate();
}
else
Control::DataChanged( rDCEvt );
}
void VclMultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags )
{
ImplInitSettings(true);
Point aPos = pDev->LogicToPixel( rPos );
Size aSize = GetSizePixel();
vcl::Font aFont = pImpVclMEdit->GetTextWindow()->GetDrawPixelFont(pDev);
aFont.SetTransparent( true );
pDev->Push();
pDev->SetMapMode();
pDev->SetFont( aFont );
pDev->SetTextFillColor();
// Border/Background
pDev->SetLineColor();
pDev->SetFillColor();
bool bBorder = (GetStyle() & WB_BORDER);
bool bBackground = IsControlBackground();
if ( bBorder || bBackground )
{
tools::Rectangle aRect( aPos, aSize );
if ( bBorder )
{
DecorationView aDecoView( pDev );
aRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleIn );
}
if ( bBackground )
{
pDev->SetFillColor( GetControlBackground() );
pDev->DrawRect( aRect );
}
}
pDev->SetSystemTextColor(nFlags, IsEnabled());
OUString aText = GetText();
Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() );
sal_uLong nLines = static_cast<sal_uLong>(aSize.Height() / aTextSz.Height());
if ( !nLines )
nLines = 1;
aTextSz.setHeight( nLines*aTextSz.Height() );
tools::Long nOnePixel = GetDrawPixel( pDev, 1 );
tools::Long nOffX = 3*nOnePixel;
tools::Long nOffY = 2*nOnePixel;
// Clipping?
if ( ( nOffY < 0 ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) )
{
tools::Rectangle aClip( aPos, aSize );
if ( aTextSz.Height() > aSize.Height() )
aClip.AdjustBottom(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::EventNotify( NotifyEvent& rNEvt )
{
bool bDone = false;
if( rNEvt.GetType() == NotifyEventType::COMMAND )
{
bDone = pImpVclMEdit->HandleCommand( *rNEvt.GetCommandEvent() );
}
return bDone || Edit::EventNotify( rNEvt );
}
bool VclMultiLineEdit::PreNotify( NotifyEvent& rNEvt )
{
bool bDone = false;
if( ( rNEvt.GetType() == NotifyEventType::KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) )
{
const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) )
{
bDone = 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().IsVisible() )
pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::LineUp );
}
break;
case KEY_DOWN:
{
if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::LineDown );
}
break;
case KEY_PAGEUP :
{
if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::PageUp );
}
break;
case KEY_PAGEDOWN:
{
if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::PageDown );
}
break;
case KEY_LEFT:
{
if ( pImpVclMEdit->GetHScrollBar().IsVisible() )
pImpVclMEdit->GetHScrollBar().DoScrollAction( ScrollType::LineUp );
}
break;
case KEY_RIGHT:
{
if ( pImpVclMEdit->GetHScrollBar().IsVisible() )
pImpVclMEdit->GetHScrollBar().DoScrollAction( ScrollType::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( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
}
break;
default:
{
bDone = false;
}
}
}
}
}
return bDone || Edit::PreNotify( rNEvt );
}
// Internals for derived classes, e.g. TextComponent
ExtTextEngine* VclMultiLineEdit::GetTextEngine() const
{
return pImpVclMEdit->GetTextWindow()->GetTextEngine();
}
TextView* 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::DisableSelectionOnFocus()
{
pImpVclMEdit->GetTextWindow()->DisableSelectionOnFocus();
}
void VclMultiLineEdit::EnableCursor( bool bEnable )
{
GetTextView()->EnableCursor( bEnable );
}
bool VclMultiLineEdit::CanUp() const
{
TextView* pTextView = GetTextView();
const TextSelection& rTextSelection = pTextView->GetSelection();
TextPaM aPaM(rTextSelection.GetEnd());
return aPaM != pTextView->CursorUp(aPaM);
}
bool VclMultiLineEdit::CanDown() const
{
TextView* pTextView = GetTextView();
const TextSelection& rTextSelection = pTextView->GetSelection();
TextPaM aPaM(rTextSelection.GetEnd());
return aPaM != pTextView->CursorDown(aPaM);
}
TextWindow* VclMultiLineEdit::GetTextWindow()
{
return pImpVclMEdit->GetTextWindow();
}
FactoryFunction VclMultiLineEdit::GetUITestFactory() const
{
return MultiLineEditUIObject::create;
}
bool VclMultiLineEdit::set_property(const OUString &rKey, const OUString &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;
}
void VclMultiLineEdit::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
Edit::DumpAsPropertyTree(rJsonWriter);
rJsonWriter.put("cursor", pImpVclMEdit->GetTextWindow()->GetTextView()->IsCursorEnabled());
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */