bump product version to 7.6.3.2-android
[LibreOffice.git] / vcl / source / edit / vclmedit.cxx
blob541d6bfc20c804d6b01422652778f422c97c1e6c
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 .
20 #include <memory>
21 #include <i18nlangtag/languagetag.hxx>
22 #include <vcl/commandevent.hxx>
23 #include <vcl/builder.hxx>
24 #include <vcl/decoview.hxx>
25 #include <vcl/event.hxx>
26 #include <vcl/menu.hxx>
27 #include <vcl/specialchars.hxx>
28 #include <vcl/timer.hxx>
29 #include <vcl/vclevent.hxx>
30 #include <vcl/xtextedt.hxx>
31 #include <vcl/textview.hxx>
32 #include <vcl/ptrstyle.hxx>
34 #include <svl/undo.hxx>
35 #include <svl/lstner.hxx>
36 #include <vcl/uitest/uiobject.hxx>
38 #include <vcl/settings.hxx>
39 #include <vcl/toolkit/scrbar.hxx>
40 #include <vcl/toolkit/vclmedit.hxx>
41 #include <vcl/weld.hxx>
42 #include <osl/diagnose.h>
43 #include <tools/json_writer.hxx>
45 class ImpVclMEdit : public SfxListener
47 private:
48 VclPtr<VclMultiLineEdit> pVclMultiLineEdit;
50 VclPtr<TextWindow> mpTextWindow;
51 VclPtr<ScrollBar> mpHScrollBar;
52 VclPtr<ScrollBar> mpVScrollBar;
53 VclPtr<ScrollBarBox> mpScrollBox;
55 tools::Long mnTextWidth;
56 mutable Selection maSelection;
58 protected:
59 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
60 void ImpUpdateScrollBarVis( WinBits nWinStyle );
61 void ImpInitScrollBars();
62 void ImpSetScrollBarRanges();
63 void ImpSetHScrollBarThumbPos();
64 DECL_LINK( ScrollHdl, ScrollBar*, void );
66 public:
67 ImpVclMEdit( VclMultiLineEdit* pVclMultiLineEdit, WinBits nWinStyle );
68 virtual ~ImpVclMEdit() override;
70 void SetModified( bool bMod );
72 void SetReadOnly( bool bRdOnly );
73 bool IsReadOnly() const;
75 void SetMaxTextLen(sal_Int32 nLen);
76 sal_Int32 GetMaxTextLen() const;
78 void SetMaxTextWidth(tools::Long nMaxWidth);
80 void InsertText( const OUString& rStr );
81 OUString GetSelected() const;
82 OUString GetSelected( LineEnd aSeparator ) const;
84 void SetSelection( const Selection& rSelection );
85 const Selection& GetSelection() const;
87 void Cut();
88 void Copy();
89 void Paste();
91 void SetText( const OUString& rStr );
92 OUString GetText() const;
93 OUString GetText( LineEnd aSeparator ) const;
94 OUString GetTextLines( LineEnd aSeparator ) const;
96 void Resize();
97 void GetFocus();
99 bool HandleCommand( const CommandEvent& rCEvt );
101 void Enable( bool bEnable );
103 Size CalcMinimumSize() const;
104 Size CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const;
105 void GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const;
107 void SetAlign( WinBits nWinStyle );
109 void InitFromStyle( WinBits nWinStyle );
111 TextWindow* GetTextWindow() { return mpTextWindow; }
112 ScrollBar& GetHScrollBar() { return *mpHScrollBar; }
113 ScrollBar& GetVScrollBar() { return *mpVScrollBar; }
116 ImpVclMEdit::ImpVclMEdit( VclMultiLineEdit* pEdt, WinBits nWinStyle )
117 : pVclMultiLineEdit(pEdt)
118 , mpTextWindow(VclPtr<TextWindow>::Create(pEdt))
119 , mpHScrollBar(VclPtr<ScrollBar>::Create(pVclMultiLineEdit, WB_HSCROLL|WB_DRAG))
120 , mpVScrollBar(VclPtr<ScrollBar>::Create(pVclMultiLineEdit, WB_VSCROLL|WB_DRAG))
121 , mpScrollBox(VclPtr<ScrollBarBox>::Create(pVclMultiLineEdit, WB_SIZEABLE))
122 , mnTextWidth(0)
124 mpVScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
125 mpHScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
126 mpTextWindow->Show();
127 InitFromStyle( nWinStyle );
128 StartListening( *mpTextWindow->GetTextEngine() );
131 void ImpVclMEdit::ImpUpdateScrollBarVis( WinBits nWinStyle )
133 const bool bHaveVScroll = mpVScrollBar->IsVisible();
134 const bool bHaveHScroll = mpHScrollBar->IsVisible();
135 const bool bHaveScrollBox = mpScrollBox->IsVisible();
137 bool bNeedVScroll = ( nWinStyle & WB_VSCROLL ) == WB_VSCROLL;
138 const bool bNeedHScroll = ( nWinStyle & WB_HSCROLL ) == WB_HSCROLL;
140 const bool bAutoVScroll = ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL;
141 if ( !bNeedVScroll && bAutoVScroll )
143 TextEngine& rEngine( *mpTextWindow->GetTextEngine() );
144 tools::Long nOverallTextHeight(0);
145 for ( sal_uInt32 i=0; i<rEngine.GetParagraphCount(); ++i )
146 nOverallTextHeight += rEngine.GetTextHeight( i );
147 if ( nOverallTextHeight > mpTextWindow->GetOutputSizePixel().Height() )
148 bNeedVScroll = true;
151 const bool bNeedScrollBox = bNeedVScroll && bNeedHScroll;
153 bool bScrollbarsChanged = false;
154 if ( bHaveVScroll != bNeedVScroll )
156 mpVScrollBar->Show(bNeedVScroll);
157 bScrollbarsChanged = true;
160 if ( bHaveHScroll != bNeedHScroll )
162 mpHScrollBar->Show(bNeedHScroll);
163 bScrollbarsChanged = true;
166 if ( bHaveScrollBox != bNeedScrollBox )
168 mpScrollBox->Show(bNeedScrollBox);
171 if ( bScrollbarsChanged )
173 ImpInitScrollBars();
174 Resize();
178 void ImpVclMEdit::InitFromStyle( WinBits nWinStyle )
180 ImpUpdateScrollBarVis( nWinStyle );
181 SetAlign( nWinStyle );
183 if ( nWinStyle & WB_NOHIDESELECTION )
184 mpTextWindow->SetAutoFocusHide( false );
185 else
186 mpTextWindow->SetAutoFocusHide( true );
188 if ( nWinStyle & WB_READONLY )
189 mpTextWindow->GetTextView()->SetReadOnly( true );
190 else
191 mpTextWindow->GetTextView()->SetReadOnly( false );
193 if ( nWinStyle & WB_IGNORETAB )
195 mpTextWindow->SetIgnoreTab( true );
197 else
199 mpTextWindow->SetIgnoreTab( false );
200 // #103667# VclMultiLineEdit has the flag, but focusable window also needs this flag
201 WinBits nStyle = mpTextWindow->GetStyle();
202 nStyle |= WB_NODIALOGCONTROL;
203 mpTextWindow->SetStyle( nStyle );
207 ImpVclMEdit::~ImpVclMEdit()
209 EndListening( *mpTextWindow->GetTextEngine() );
210 mpTextWindow.disposeAndClear();
211 mpHScrollBar.disposeAndClear();
212 mpVScrollBar.disposeAndClear();
213 mpScrollBox.disposeAndClear();
214 pVclMultiLineEdit.disposeAndClear();
217 void ImpVclMEdit::ImpSetScrollBarRanges()
219 const tools::Long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
220 mpVScrollBar->SetRange( Range( 0, nTextHeight-1 ) );
222 mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
225 void ImpVclMEdit::ImpInitScrollBars()
227 static const sal_Unicode sampleChar = { 'x' };
229 ImpSetScrollBarRanges();
231 Size aCharBox;
232 aCharBox.setWidth( mpTextWindow->GetTextWidth( OUString(sampleChar) ) );
233 aCharBox.setHeight( mpTextWindow->GetTextHeight() );
234 Size aOutSz = mpTextWindow->GetOutputSizePixel();
236 mpHScrollBar->SetVisibleSize( aOutSz.Width() );
237 mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 );
238 mpHScrollBar->SetLineSize( aCharBox.Width()*10 );
239 ImpSetHScrollBarThumbPos();
241 mpVScrollBar->SetVisibleSize( aOutSz.Height() );
242 mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 );
243 mpVScrollBar->SetLineSize( aCharBox.Height() );
244 mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
247 void ImpVclMEdit::ImpSetHScrollBarThumbPos()
249 tools::Long nX = mpTextWindow->GetTextView()->GetStartDocPos().X();
250 if ( !mpTextWindow->GetTextEngine()->IsRightToLeft() )
251 mpHScrollBar->SetThumbPos( nX );
252 else
253 mpHScrollBar->SetThumbPos( mnTextWidth - mpHScrollBar->GetVisibleSize() - nX );
257 IMPL_LINK( ImpVclMEdit, ScrollHdl, ScrollBar*, pCurScrollBar, void )
259 tools::Long nDiffX = 0, nDiffY = 0;
261 if ( pCurScrollBar == mpVScrollBar )
262 nDiffY = mpTextWindow->GetTextView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
263 else if ( pCurScrollBar == mpHScrollBar )
264 nDiffX = mpTextWindow->GetTextView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
266 mpTextWindow->GetTextView()->Scroll( nDiffX, nDiffY );
267 // mpTextWindow->GetTextView()->ShowCursor( false, true );
270 void ImpVclMEdit::SetAlign( WinBits nWinStyle )
272 bool bRTL = AllSettings::GetLayoutRTL();
273 mpTextWindow->GetTextEngine()->SetRightToLeft( bRTL );
275 if ( nWinStyle & WB_CENTER )
276 mpTextWindow->GetTextEngine()->SetTextAlign( TxtAlign::Center );
277 else if ( nWinStyle & WB_RIGHT )
278 mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TxtAlign::Right : TxtAlign::Left );
279 else if ( nWinStyle & WB_LEFT )
280 mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TxtAlign::Left : TxtAlign::Right );
283 void ImpVclMEdit::SetModified( bool bMod )
285 mpTextWindow->GetTextEngine()->SetModified( bMod );
288 void ImpVclMEdit::SetReadOnly( bool bRdOnly )
290 mpTextWindow->GetTextView()->SetReadOnly( bRdOnly );
291 // TODO: Adjust color?
294 bool ImpVclMEdit::IsReadOnly() const
296 return mpTextWindow->GetTextView()->IsReadOnly();
299 void ImpVclMEdit::SetMaxTextLen(sal_Int32 nLen)
301 mpTextWindow->GetTextEngine()->SetMaxTextLen(nLen);
304 sal_Int32 ImpVclMEdit::GetMaxTextLen() const
306 return mpTextWindow->GetTextEngine()->GetMaxTextLen();
309 void ImpVclMEdit::InsertText( const OUString& rStr )
311 mpTextWindow->GetTextView()->InsertText( rStr );
314 OUString ImpVclMEdit::GetSelected() const
316 return mpTextWindow->GetTextView()->GetSelected();
319 OUString ImpVclMEdit::GetSelected( LineEnd aSeparator ) const
321 return mpTextWindow->GetTextView()->GetSelected( aSeparator );
324 void ImpVclMEdit::SetMaxTextWidth(tools::Long nMaxWidth)
326 mpTextWindow->GetTextEngine()->SetMaxTextWidth(nMaxWidth);
329 void ImpVclMEdit::Resize()
331 int nIteration = 1;
334 WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
335 if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
336 ImpUpdateScrollBarVis( nWinStyle );
338 Size aSz = pVclMultiLineEdit->GetOutputSizePixel();
339 Size aEditSize = aSz;
340 tools::Long nSBWidth = pVclMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize();
341 nSBWidth = pVclMultiLineEdit->CalcZoom( nSBWidth );
343 if (mpHScrollBar->IsVisible())
344 aSz.AdjustHeight( -(nSBWidth+1) );
345 if (mpVScrollBar->IsVisible())
346 aSz.AdjustWidth( -(nSBWidth+1) );
348 if (!mpHScrollBar->IsVisible())
349 mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() );
350 else
351 mpHScrollBar->setPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth );
353 Point aTextWindowPos;
354 if (mpVScrollBar->IsVisible())
356 if( AllSettings::GetLayoutRTL() )
358 mpVScrollBar->setPosSizePixel( 0, 0, nSBWidth, aSz.Height() );
359 aTextWindowPos.AdjustX(nSBWidth );
361 else
362 mpVScrollBar->setPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() );
365 if (mpScrollBox->IsVisible())
366 mpScrollBox->setPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth );
368 Size aTextWindowSize( aSz );
369 if ( aTextWindowSize.Width() < 0 )
370 aTextWindowSize.setWidth( 0 );
371 if ( aTextWindowSize.Height() < 0 )
372 aTextWindowSize.setHeight( 0 );
374 Size aOldTextWindowSize( mpTextWindow->GetSizePixel() );
375 mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize );
376 if ( aOldTextWindowSize == aTextWindowSize )
377 break;
379 // Changing the text window size might effectively have changed the need for
380 // scrollbars, so do another iteration.
381 ++nIteration;
382 OSL_ENSURE( nIteration < 3, "ImpVclMEdit::Resize: isn't this expected to terminate with the second iteration?" );
384 } while ( nIteration <= 3 ); // artificial break after four iterations
386 ImpInitScrollBars();
389 void ImpVclMEdit::GetFocus()
391 mpTextWindow->GrabFocus();
394 void ImpVclMEdit::Cut()
396 if ( !mpTextWindow->GetTextView()->IsReadOnly() )
397 mpTextWindow->GetTextView()->Cut();
400 void ImpVclMEdit::Copy()
402 mpTextWindow->GetTextView()->Copy();
405 void ImpVclMEdit::Paste()
407 if ( !mpTextWindow->GetTextView()->IsReadOnly() )
408 mpTextWindow->GetTextView()->Paste();
411 void ImpVclMEdit::SetText( const OUString& rStr )
413 bool bWasModified = mpTextWindow->GetTextEngine()->IsModified();
414 mpTextWindow->GetTextEngine()->SetText( rStr );
415 if ( !bWasModified )
416 mpTextWindow->GetTextEngine()->SetModified( false );
418 mpTextWindow->GetTextView()->SetSelection( TextSelection() );
420 WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
421 if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
422 ImpUpdateScrollBarVis( nWinStyle );
425 OUString ImpVclMEdit::GetText() const
427 return mpTextWindow->GetTextEngine()->GetText();
430 OUString ImpVclMEdit::GetText( LineEnd aSeparator ) const
432 return mpTextWindow->GetTextEngine()->GetText( aSeparator );
435 OUString ImpVclMEdit::GetTextLines( LineEnd aSeparator ) const
437 return mpTextWindow->GetTextEngine()->GetTextLines( aSeparator );
440 void ImpVclMEdit::Notify( SfxBroadcaster&, const SfxHint& rHint )
442 const TextHint* pTextHint = dynamic_cast<const TextHint*>(&rHint);
443 if ( !pTextHint )
444 return;
446 switch (pTextHint->GetId())
448 case SfxHintId::TextViewScrolled:
449 if (mpHScrollBar->IsVisible())
450 ImpSetHScrollBarThumbPos();
451 if (mpVScrollBar->IsVisible())
452 mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
453 break;
455 case SfxHintId::TextHeightChanged:
456 if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() )
458 tools::Long nOutHeight = mpTextWindow->GetOutputSizePixel().Height();
459 tools::Long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
460 if ( nTextHeight < nOutHeight )
461 mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() );
463 ImpSetScrollBarRanges();
464 break;
466 case SfxHintId::TextFormatted:
467 if (mpHScrollBar->IsVisible())
469 const tools::Long nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
470 if ( nWidth != mnTextWidth )
472 mnTextWidth = nWidth;
473 mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
474 ImpSetHScrollBarThumbPos();
477 break;
479 case SfxHintId::TextModified:
480 ImpUpdateScrollBarVis(pVclMultiLineEdit->GetStyle());
481 pVclMultiLineEdit->Modify();
482 break;
484 case SfxHintId::TextViewSelectionChanged:
485 pVclMultiLineEdit->SelectionChanged();
486 break;
488 case SfxHintId::TextViewCaretChanged:
489 pVclMultiLineEdit->CaretChanged();
490 break;
492 default: break;
496 void ImpVclMEdit::SetSelection( const Selection& rSelection )
498 OUString aText = mpTextWindow->GetTextEngine()->GetText();
500 Selection aNewSelection( rSelection );
501 if ( aNewSelection.Min() < 0 )
502 aNewSelection.Min() = 0;
503 else if ( aNewSelection.Min() > aText.getLength() )
504 aNewSelection.Min() = aText.getLength();
505 if ( aNewSelection.Max() < 0 )
506 aNewSelection.Max() = 0;
507 else if ( aNewSelection.Max() > aText.getLength() )
508 aNewSelection.Max() = aText.getLength();
510 tools::Long nEnd = std::max( aNewSelection.Min(), aNewSelection.Max() );
511 TextSelection aTextSel;
512 sal_uInt32 nPara = 0;
513 sal_Int32 nChar = 0;
514 tools::Long x = 0;
515 while ( x <= nEnd )
517 if ( x == aNewSelection.Min() )
518 aTextSel.GetStart() = TextPaM( nPara, nChar );
519 if ( x == aNewSelection.Max() )
520 aTextSel.GetEnd() = TextPaM( nPara, nChar );
522 if ( ( x < aText.getLength() ) && ( aText[ x ] == '\n' ) )
524 nPara++;
525 nChar = 0;
527 else
528 nChar++;
529 x++;
531 mpTextWindow->GetTextView()->SetSelection( aTextSel );
534 const Selection& ImpVclMEdit::GetSelection() const
536 maSelection = Selection();
537 TextSelection aTextSel( mpTextWindow->GetTextView()->GetSelection() );
538 aTextSel.Justify();
539 // flatten selection => every line-break a character
541 ExtTextEngine* pExtTextEngine = mpTextWindow->GetTextEngine();
542 // paragraphs before
543 for ( sal_uInt32 n = 0; n < aTextSel.GetStart().GetPara(); ++n )
545 maSelection.Min() += pExtTextEngine->GetTextLen( n );
546 maSelection.Min()++;
549 // first paragraph with selection
550 maSelection.Max() = maSelection.Min();
551 maSelection.Min() += aTextSel.GetStart().GetIndex();
553 for ( sal_uInt32 n = aTextSel.GetStart().GetPara(); n < aTextSel.GetEnd().GetPara(); ++n )
555 maSelection.Max() += pExtTextEngine->GetTextLen( n );
556 maSelection.Max()++;
559 maSelection.Max() += aTextSel.GetEnd().GetIndex();
561 return maSelection;
564 Size ImpVclMEdit::CalcMinimumSize() const
566 Size aSz( mpTextWindow->GetTextEngine()->CalcTextWidth(),
567 mpTextWindow->GetTextEngine()->GetTextHeight() );
569 if (mpHScrollBar->IsVisible())
570 aSz.AdjustHeight(mpHScrollBar->GetSizePixel().Height() );
571 if (mpVScrollBar->IsVisible())
572 aSz.AdjustWidth(mpVScrollBar->GetSizePixel().Width() );
574 return aSz;
577 Size ImpVclMEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
579 static const sal_Unicode sampleChar = 'X';
581 Size aSz;
582 Size aCharSz;
583 aCharSz.setWidth( mpTextWindow->GetTextWidth( OUString(sampleChar) ) );
584 aCharSz.setHeight( mpTextWindow->GetTextHeight() );
586 if ( nLines )
587 aSz.setHeight( nLines*aCharSz.Height() );
588 else
589 aSz.setHeight( mpTextWindow->GetTextEngine()->GetTextHeight() );
591 if ( nColumns )
592 aSz.setWidth( nColumns*aCharSz.Width() );
593 else
594 aSz.setWidth( mpTextWindow->GetTextEngine()->CalcTextWidth() );
596 if (mpHScrollBar->IsVisible())
597 aSz.AdjustHeight(mpHScrollBar->GetSizePixel().Height() );
598 if (mpVScrollBar->IsVisible())
599 aSz.AdjustWidth(mpVScrollBar->GetSizePixel().Width() );
601 return aSz;
604 void ImpVclMEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
606 static const sal_Unicode sampleChar = { 'x' };
607 Size aOutSz = mpTextWindow->GetOutputSizePixel();
608 Size aCharSz( mpTextWindow->GetTextWidth( OUString(sampleChar) ), mpTextWindow->GetTextHeight() );
609 rnCols = static_cast<sal_uInt16>(aOutSz.Width()/aCharSz.Width());
610 rnLines = static_cast<sal_uInt16>(aOutSz.Height()/aCharSz.Height());
613 void ImpVclMEdit::Enable( bool bEnable )
615 mpTextWindow->Enable( bEnable );
616 if (mpHScrollBar->IsVisible())
617 mpHScrollBar->Enable( bEnable );
618 if (mpVScrollBar->IsVisible())
619 mpVScrollBar->Enable( bEnable );
622 bool ImpVclMEdit::HandleCommand( const CommandEvent& rCEvt )
624 bool bDone = false;
625 CommandEventId nCommand = rCEvt.GetCommand();
626 if (nCommand == CommandEventId::Wheel ||
627 nCommand == CommandEventId::StartAutoScroll ||
628 nCommand == CommandEventId::AutoScroll ||
629 nCommand == CommandEventId::GesturePan)
631 ScrollBar* pHScrollBar = mpHScrollBar->IsVisible() ? mpHScrollBar.get() : nullptr;
632 ScrollBar* pVScrollBar = mpVScrollBar->IsVisible() ? mpVScrollBar.get() : nullptr;
633 mpTextWindow->HandleScrollCommand(rCEvt, pHScrollBar, pVScrollBar);
634 bDone = true;
636 return bDone;
639 TextWindow::TextWindow(Edit* pParent)
640 : Window(pParent)
641 , mxParent(pParent)
643 mbInMBDown = false;
644 mbFocusSelectionHide = false;
645 mbIgnoreTab = false;
646 mbActivePopup = false;
647 mbSelectOnTab = true;
649 SetPointer( PointerStyle::Text );
651 mpExtTextEngine.reset(new ExtTextEngine);
652 mpExtTextEngine->SetMaxTextLen(EDIT_NOLIMIT);
653 if( pParent->GetStyle() & WB_BORDER )
654 mpExtTextEngine->SetLeftMargin( 2 );
655 mpExtTextEngine->SetLocale( GetSettings().GetLanguageTag().getLocale() );
656 mpExtTextView.reset(new TextView( mpExtTextEngine.get(), this ));
657 mpExtTextEngine->InsertView( mpExtTextView.get() );
658 mpExtTextEngine->EnableUndo( true );
659 mpExtTextView->ShowCursor();
661 Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor();
662 SetBackground( aBackgroundColor );
663 pParent->SetBackground( aBackgroundColor );
666 TextWindow::~TextWindow()
668 disposeOnce();
671 void TextWindow::dispose()
673 mxParent.clear();
674 mpExtTextView.reset();
675 mpExtTextEngine.reset();
676 Window::dispose();
679 void TextWindow::MouseMove( const MouseEvent& rMEvt )
681 mpExtTextView->MouseMove( rMEvt );
682 Window::MouseMove( rMEvt );
685 void TextWindow::MouseButtonDown( const MouseEvent& rMEvt )
687 mbInMBDown = true; // so that GetFocus does not select everything
688 mpExtTextView->MouseButtonDown( rMEvt );
689 GrabFocus();
690 mbInMBDown = false;
693 void TextWindow::MouseButtonUp( const MouseEvent& rMEvt )
695 mpExtTextView->MouseButtonUp( rMEvt );
698 void TextWindow::KeyInput( const KeyEvent& rKEvent )
700 bool bDone = false;
701 sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
702 if ( nCode == css::awt::Key::SELECT_ALL ||
703 ( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() )
706 mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
707 bDone = true;
709 else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() )
711 if ( vcl::GetGetSpecialCharsFunction() )
713 // to maintain the selection
714 mbActivePopup = true;
715 OUString aChars = vcl::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont());
716 if (!aChars.isEmpty())
718 mpExtTextView->InsertText( aChars );
719 mpExtTextView->GetTextEngine()->SetModified( true );
721 mbActivePopup = false;
722 bDone = true;
725 else if ( nCode == KEY_TAB )
727 if (!mbIgnoreTab)
729 if (!rKEvent.GetKeyCode().IsMod1())
730 bDone = mpExtTextView->KeyInput(rKEvent);
731 else
733 // tdf#107625 make ctrl+tab act like tab when MultiLine Edit normally accepts tab as an input char
734 vcl::KeyCode aKeyCode(rKEvent.GetKeyCode().GetCode(), rKEvent.GetKeyCode().GetModifier() & ~KEY_MOD1);
735 KeyEvent aKEventWithoutMod1(rKEvent.GetCharCode(), aKeyCode, rKEvent.GetRepeat());
736 Window::KeyInput(aKEventWithoutMod1);
737 bDone = true;
741 else
743 bDone = mpExtTextView->KeyInput( rKEvent );
746 if ( !bDone )
747 Window::KeyInput( rKEvent );
750 void TextWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
752 mpExtTextView->Paint(rRenderContext, rRect);
755 void TextWindow::Resize()
759 void TextWindow::Command( const CommandEvent& rCEvt )
761 if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
763 VclPtr<PopupMenu> pPopup = mxParent->CreatePopupMenu();
764 bool bEnableCut = true;
765 bool bEnableCopy = true;
766 bool bEnableDelete = true;
767 bool bEnablePaste = true;
768 bool bEnableSpecialChar = true;
769 bool bEnableUndo = true;
771 if ( !mpExtTextView->HasSelection() )
773 bEnableCut = false;
774 bEnableCopy = false;
775 bEnableDelete = false;
777 if ( mpExtTextView->IsReadOnly() )
779 bEnableCut = false;
780 bEnablePaste = false;
781 bEnableDelete = false;
782 bEnableSpecialChar = false;
784 if ( !mpExtTextView->GetTextEngine()->HasUndoManager() || !mpExtTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() )
786 bEnableUndo = false;
788 pPopup->EnableItem(pPopup->GetItemId(u"cut"), bEnableCut);
789 pPopup->EnableItem(pPopup->GetItemId(u"copy"), bEnableCopy);
790 pPopup->EnableItem(pPopup->GetItemId(u"delete"), bEnableDelete);
791 pPopup->EnableItem(pPopup->GetItemId(u"paste"), bEnablePaste);
792 pPopup->EnableItem(pPopup->GetItemId(u"specialchar"), bEnableSpecialChar);
793 pPopup->EnableItem(pPopup->GetItemId(u"undo"), bEnableUndo);
794 pPopup->ShowItem(pPopup->GetItemId(u"specialchar"), !vcl::GetGetSpecialCharsFunction());
796 mbActivePopup = true;
797 Point aPos = rCEvt.GetMousePosPixel();
798 if ( !rCEvt.IsMouseEvent() )
800 // Sometime do show Menu centered in the selection !!!
801 Size aSize = GetOutputSizePixel();
802 aPos = Point( aSize.Width()/2, aSize.Height()/2 );
804 sal_uInt16 n = pPopup->Execute( this, aPos );
805 OUString sCommand = pPopup->GetItemIdent(n);
806 if (sCommand == "undo")
808 mpExtTextView->Undo();
809 mpExtTextEngine->SetModified( true );
810 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
812 else if (sCommand == "cut")
814 mpExtTextView->Cut();
815 mpExtTextEngine->SetModified( true );
816 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
818 else if (sCommand == "copy")
820 mpExtTextView->Copy();
822 else if (sCommand == "paste")
824 mpExtTextView->Paste();
825 mpExtTextEngine->SetModified( true );
826 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
828 else if (sCommand == "delete")
830 mpExtTextView->DeleteSelected();
831 mpExtTextEngine->SetModified( true );
832 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
834 else if (sCommand == "selectall")
836 mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
838 else if (sCommand == "specialchar")
840 OUString aChars = vcl::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont());
841 if (!aChars.isEmpty())
843 mpExtTextView->InsertText( aChars );
844 mpExtTextEngine->SetModified( true );
845 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
848 pPopup.clear();
849 mbActivePopup = false;
851 else
853 mpExtTextView->Command( rCEvt );
855 Window::Command( rCEvt );
858 void TextWindow::GetFocus()
860 Window::GetFocus();
861 if ( mbActivePopup )
862 return;
864 bool bGotoCursor = !mpExtTextView->IsReadOnly();
865 if ( mbFocusSelectionHide && IsReallyVisible() && mbSelectOnTab && !mbInMBDown )
867 // select everything, but do not scroll
868 bool bAutoScroll = mpExtTextView->IsAutoScroll();
869 mpExtTextView->SetAutoScroll( false );
870 mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
871 mpExtTextView->SetAutoScroll( bAutoScroll );
872 bGotoCursor = false;
874 mpExtTextView->SetPaintSelection( true );
875 mpExtTextView->ShowCursor( bGotoCursor );
878 void TextWindow::LoseFocus()
880 Window::LoseFocus();
882 if ( mbFocusSelectionHide && !mbActivePopup && mpExtTextView )
883 mpExtTextView->SetPaintSelection( false );
886 VclMultiLineEdit::VclMultiLineEdit( vcl::Window* pParent, WinBits nWinStyle )
887 : Edit( pParent, nWinStyle )
889 SetType( WindowType::MULTILINEEDIT );
890 pImpVclMEdit.reset(new ImpVclMEdit( this, nWinStyle ));
891 ImplInitSettings( true );
893 SetCompoundControl( true );
894 SetStyle( ImplInitStyle( nWinStyle ) );
897 VclMultiLineEdit::~VclMultiLineEdit()
899 disposeOnce();
902 void VclMultiLineEdit::dispose()
904 pImpVclMEdit.reset();
905 Edit::dispose();
908 WinBits VclMultiLineEdit::ImplInitStyle( WinBits nStyle )
910 if ( !(nStyle & WB_NOTABSTOP) )
911 nStyle |= WB_TABSTOP;
913 if ( !(nStyle & WB_NOGROUP) )
914 nStyle |= WB_GROUP;
916 if ( !(nStyle & WB_IGNORETAB ))
917 nStyle |= WB_NODIALOGCONTROL;
919 return nStyle;
922 void VclMultiLineEdit::ApplySettings(vcl::RenderContext& rRenderContext)
924 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
926 // The Font has to be adjusted, as the TextEngine does not take care of
927 // TextColor/Background
929 Color aTextColor = rStyleSettings.GetFieldTextColor();
930 if (IsControlForeground())
931 aTextColor = GetControlForeground();
933 if (!IsEnabled())
934 aTextColor = rStyleSettings.GetDisableColor();
936 vcl::Font aFont = rStyleSettings.GetFieldFont();
937 aFont.SetTransparent(IsPaintTransparent());
938 ApplyControlFont(rRenderContext, aFont);
940 vcl::Font theFont = rRenderContext.GetFont();
941 theFont.SetColor(aTextColor);
942 if (IsPaintTransparent())
943 theFont.SetFillColor(COL_TRANSPARENT);
944 else
945 theFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
947 pImpVclMEdit->GetTextWindow()->SetFont(theFont);
948 // FIXME: next call causes infinite invalidation loop, rethink how to properly fix this situation
949 // pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(theFont);
950 pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
952 if (IsPaintTransparent())
954 pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
955 pImpVclMEdit->GetTextWindow()->SetBackground();
956 pImpVclMEdit->GetTextWindow()->SetControlBackground();
957 rRenderContext.SetBackground();
958 SetControlBackground();
960 else
962 if (IsControlBackground())
963 pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
964 else
965 pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
966 // also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
967 rRenderContext.SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
971 void VclMultiLineEdit::ImplInitSettings(bool bBackground)
973 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
975 // The Font has to be adjusted, as the TextEngine does not take care of
976 // TextColor/Background
978 Color aTextColor = rStyleSettings.GetFieldTextColor();
979 if (IsControlForeground())
980 aTextColor = GetControlForeground();
981 if (!IsEnabled())
982 aTextColor = rStyleSettings.GetDisableColor();
984 vcl::Font aFont = rStyleSettings.GetFieldFont();
985 aFont.SetTransparent(IsPaintTransparent());
986 ApplyControlFont(*GetOutDev(), aFont);
988 vcl::Font TheFont = GetFont();
989 TheFont.SetColor(aTextColor);
990 if (IsPaintTransparent())
991 TheFont.SetFillColor(COL_TRANSPARENT);
992 else
993 TheFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
994 pImpVclMEdit->GetTextWindow()->SetFont(TheFont);
995 pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(TheFont);
996 pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
998 if (!bBackground)
999 return;
1001 if (IsPaintTransparent())
1003 pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
1004 pImpVclMEdit->GetTextWindow()->SetBackground();
1005 pImpVclMEdit->GetTextWindow()->SetControlBackground();
1006 SetBackground();
1007 SetControlBackground();
1009 else
1011 if (IsControlBackground())
1012 pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
1013 else
1014 pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
1015 // also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
1016 SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
1020 void VclMultiLineEdit::Modify()
1022 aModifyHdlLink.Call( *this );
1024 CallEventListeners( VclEventId::EditModify );
1027 void VclMultiLineEdit::SelectionChanged()
1029 CallEventListeners(VclEventId::EditSelectionChanged);
1032 void VclMultiLineEdit::CaretChanged()
1034 CallEventListeners(VclEventId::EditCaretChanged);
1037 void VclMultiLineEdit::SetModifyFlag()
1039 pImpVclMEdit->SetModified( true );
1042 void VclMultiLineEdit::SetReadOnly( bool bReadOnly )
1044 pImpVclMEdit->SetReadOnly( bReadOnly );
1045 Edit::SetReadOnly( bReadOnly );
1047 // #94921# ReadOnly can be overwritten in InitFromStyle() when WB not set.
1048 WinBits nStyle = GetStyle();
1049 if ( bReadOnly )
1050 nStyle |= WB_READONLY;
1051 else
1052 nStyle &= ~WB_READONLY;
1053 SetStyle( nStyle );
1056 bool VclMultiLineEdit::IsReadOnly() const
1058 if (!pImpVclMEdit) // might be called from within the dtor, when pImpVclMEdit == NULL is a valid state
1059 return true;
1061 return pImpVclMEdit->IsReadOnly();
1064 void VclMultiLineEdit::SetMaxTextLen(sal_Int32 nMaxLen)
1066 pImpVclMEdit->SetMaxTextLen(nMaxLen);
1069 void VclMultiLineEdit::SetMaxTextWidth(tools::Long nMaxWidth)
1071 pImpVclMEdit->SetMaxTextWidth(nMaxWidth );
1074 sal_Int32 VclMultiLineEdit::GetMaxTextLen() const
1076 return pImpVclMEdit->GetMaxTextLen();
1079 void VclMultiLineEdit::ReplaceSelected( const OUString& rStr )
1081 pImpVclMEdit->InsertText( rStr );
1084 void VclMultiLineEdit::DeleteSelected()
1086 pImpVclMEdit->InsertText( OUString() );
1089 OUString VclMultiLineEdit::GetSelected() const
1091 return pImpVclMEdit->GetSelected();
1094 OUString VclMultiLineEdit::GetSelected( LineEnd aSeparator ) const
1096 return pImpVclMEdit->GetSelected( aSeparator );
1099 void VclMultiLineEdit::Cut()
1101 pImpVclMEdit->Cut();
1104 void VclMultiLineEdit::Copy()
1106 pImpVclMEdit->Copy();
1109 void VclMultiLineEdit::Paste()
1111 pImpVclMEdit->Paste();
1114 void VclMultiLineEdit::SetText( const OUString& rStr )
1116 pImpVclMEdit->SetText( rStr );
1119 OUString VclMultiLineEdit::GetText() const
1121 return pImpVclMEdit ? pImpVclMEdit->GetText() : OUString();
1124 OUString VclMultiLineEdit::GetText( LineEnd aSeparator ) const
1126 return pImpVclMEdit ? pImpVclMEdit->GetText( aSeparator ) : OUString();
1129 OUString VclMultiLineEdit::GetTextLines( LineEnd aSeparator ) const
1131 return pImpVclMEdit ? pImpVclMEdit->GetTextLines( aSeparator ) : OUString();
1134 void VclMultiLineEdit::Resize()
1136 pImpVclMEdit->Resize();
1139 void VclMultiLineEdit::GetFocus()
1141 if ( !pImpVclMEdit ) // might be called from within the dtor, when pImpVclMEdit == NULL is a valid state
1142 return;
1144 pImpVclMEdit->GetFocus();
1147 void VclMultiLineEdit::SetSelection( const Selection& rSelection )
1149 pImpVclMEdit->SetSelection( rSelection );
1152 const Selection& VclMultiLineEdit::GetSelection() const
1154 return pImpVclMEdit->GetSelection();
1157 Size VclMultiLineEdit::CalcMinimumSize() const
1159 Size aSz = pImpVclMEdit->CalcMinimumSize();
1161 sal_Int32 nLeft, nTop, nRight, nBottom;
1162 static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1163 aSz.AdjustWidth(nLeft+nRight );
1164 aSz.AdjustHeight(nTop+nBottom );
1166 return aSz;
1169 Size VclMultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const
1171 Size aSz = rPrefSize;
1172 sal_Int32 nLeft, nTop, nRight, nBottom;
1173 static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1175 // center vertically for whole lines
1177 tools::Long nHeight = aSz.Height() - nTop - nBottom;
1178 tools::Long nLineHeight = pImpVclMEdit->CalcBlockSize( 1, 1 ).Height();
1179 tools::Long nLines = nHeight / nLineHeight;
1180 if ( nLines < 1 )
1181 nLines = 1;
1183 aSz.setHeight( nLines * nLineHeight );
1184 aSz.AdjustHeight(nTop+nBottom );
1186 return aSz;
1189 Size VclMultiLineEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1191 Size aSz = pImpVclMEdit->CalcBlockSize( nColumns, nLines );
1193 sal_Int32 nLeft, nTop, nRight, nBottom;
1194 static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1195 aSz.AdjustWidth(nLeft+nRight );
1196 aSz.AdjustHeight(nTop+nBottom );
1197 return aSz;
1200 void VclMultiLineEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1202 pImpVclMEdit->GetMaxVisColumnsAndLines( rnCols, rnLines );
1205 void VclMultiLineEdit::StateChanged( StateChangedType nType )
1207 if( nType == StateChangedType::Enable )
1209 pImpVclMEdit->Enable( IsEnabled() );
1210 ImplInitSettings( false );
1212 else if( nType == StateChangedType::ReadOnly )
1214 pImpVclMEdit->SetReadOnly( IsReadOnly() );
1216 else if ( nType == StateChangedType::Zoom )
1218 pImpVclMEdit->GetTextWindow()->SetZoom( GetZoom() );
1219 ImplInitSettings( false );
1220 Resize();
1222 else if ( nType == StateChangedType::ControlFont )
1224 ImplInitSettings( false );
1225 Resize();
1226 Invalidate();
1228 else if ( nType == StateChangedType::ControlForeground )
1230 ImplInitSettings( false );
1231 Invalidate();
1233 else if ( nType == StateChangedType::ControlBackground )
1235 ImplInitSettings( true );
1236 Invalidate();
1238 else if ( nType == StateChangedType::Style )
1240 pImpVclMEdit->InitFromStyle( GetStyle() );
1241 SetStyle( ImplInitStyle( GetStyle() ) );
1243 else if ( nType == StateChangedType::InitShow )
1245 if( IsPaintTransparent() )
1247 pImpVclMEdit->GetTextWindow()->SetPaintTransparent( true );
1248 pImpVclMEdit->GetTextWindow()->SetBackground();
1249 pImpVclMEdit->GetTextWindow()->SetControlBackground();
1250 SetBackground();
1251 SetControlBackground();
1255 Control::StateChanged( nType );
1258 void VclMultiLineEdit::DataChanged( const DataChangedEvent& rDCEvt )
1260 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1261 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1263 ImplInitSettings( true );
1264 Resize();
1265 Invalidate();
1267 else
1268 Control::DataChanged( rDCEvt );
1271 void VclMultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags )
1273 ImplInitSettings(true);
1275 Point aPos = pDev->LogicToPixel( rPos );
1276 Size aSize = GetSizePixel();
1278 vcl::Font aFont = pImpVclMEdit->GetTextWindow()->GetDrawPixelFont(pDev);
1279 aFont.SetTransparent( true );
1281 pDev->Push();
1282 pDev->SetMapMode();
1283 pDev->SetFont( aFont );
1284 pDev->SetTextFillColor();
1286 // Border/Background
1287 pDev->SetLineColor();
1288 pDev->SetFillColor();
1289 bool bBorder = (GetStyle() & WB_BORDER);
1290 bool bBackground = IsControlBackground();
1291 if ( bBorder || bBackground )
1293 tools::Rectangle aRect( aPos, aSize );
1294 if ( bBorder )
1296 DecorationView aDecoView( pDev );
1297 aRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleIn );
1299 if ( bBackground )
1301 pDev->SetFillColor( GetControlBackground() );
1302 pDev->DrawRect( aRect );
1306 pDev->SetSystemTextColor(nFlags, IsEnabled());
1308 OUString aText = GetText();
1309 Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() );
1310 sal_uLong nLines = static_cast<sal_uLong>(aSize.Height() / aTextSz.Height());
1311 if ( !nLines )
1312 nLines = 1;
1313 aTextSz.setHeight( nLines*aTextSz.Height() );
1314 tools::Long nOnePixel = GetDrawPixel( pDev, 1 );
1315 tools::Long nOffX = 3*nOnePixel;
1316 tools::Long nOffY = 2*nOnePixel;
1318 // Clipping?
1319 if ( ( nOffY < 0 ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) )
1321 tools::Rectangle aClip( aPos, aSize );
1322 if ( aTextSz.Height() > aSize.Height() )
1323 aClip.AdjustBottom(aTextSz.Height() - aSize.Height() + 1 ); // so that HP-printer does not 'optimize-away'
1324 pDev->IntersectClipRegion( aClip );
1327 ExtTextEngine aTE;
1328 aTE.SetText( GetText() );
1329 aTE.SetMaxTextWidth( aSize.Width() );
1330 aTE.SetFont( aFont );
1331 aTE.SetTextAlign( pImpVclMEdit->GetTextWindow()->GetTextEngine()->GetTextAlign() );
1332 aTE.Draw( pDev, Point( aPos.X() + nOffX, aPos.Y() + nOffY ) );
1334 pDev->Pop();
1337 bool VclMultiLineEdit::EventNotify( NotifyEvent& rNEvt )
1339 bool bDone = false;
1340 if( rNEvt.GetType() == NotifyEventType::COMMAND )
1342 bDone = pImpVclMEdit->HandleCommand( *rNEvt.GetCommandEvent() );
1344 return bDone || Edit::EventNotify( rNEvt );
1347 bool VclMultiLineEdit::PreNotify( NotifyEvent& rNEvt )
1349 bool bDone = false;
1351 if( ( rNEvt.GetType() == NotifyEventType::KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) )
1353 const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
1354 if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) )
1356 bDone = true;
1357 TextSelection aSel = pImpVclMEdit->GetTextWindow()->GetTextView()->GetSelection();
1358 if ( aSel.HasRange() )
1360 aSel.GetStart() = aSel.GetEnd();
1361 pImpVclMEdit->GetTextWindow()->GetTextView()->SetSelection( aSel );
1363 else
1365 switch ( rKEvent.GetKeyCode().GetCode() )
1367 case KEY_UP:
1369 if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1370 pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::LineUp );
1372 break;
1373 case KEY_DOWN:
1375 if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1376 pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::LineDown );
1378 break;
1379 case KEY_PAGEUP :
1381 if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1382 pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::PageUp );
1384 break;
1385 case KEY_PAGEDOWN:
1387 if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1388 pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::PageDown );
1390 break;
1391 case KEY_LEFT:
1393 if ( pImpVclMEdit->GetHScrollBar().IsVisible() )
1394 pImpVclMEdit->GetHScrollBar().DoScrollAction( ScrollType::LineUp );
1396 break;
1397 case KEY_RIGHT:
1399 if ( pImpVclMEdit->GetHScrollBar().IsVisible() )
1400 pImpVclMEdit->GetHScrollBar().DoScrollAction( ScrollType::LineDown );
1402 break;
1403 case KEY_HOME:
1405 if ( rKEvent.GetKeyCode().IsMod1() )
1406 pImpVclMEdit->GetTextWindow()->GetTextView()->
1407 SetSelection( TextSelection( TextPaM( 0, 0 ) ) );
1409 break;
1410 case KEY_END:
1412 if ( rKEvent.GetKeyCode().IsMod1() )
1413 pImpVclMEdit->GetTextWindow()->GetTextView()->
1414 SetSelection( TextSelection( TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
1416 break;
1417 default:
1419 bDone = false;
1426 return bDone || Edit::PreNotify( rNEvt );
1429 // Internals for derived classes, e.g. TextComponent
1431 ExtTextEngine* VclMultiLineEdit::GetTextEngine() const
1433 return pImpVclMEdit->GetTextWindow()->GetTextEngine();
1436 TextView* VclMultiLineEdit::GetTextView() const
1438 return pImpVclMEdit->GetTextWindow()->GetTextView();
1441 ScrollBar& VclMultiLineEdit::GetVScrollBar() const
1443 return pImpVclMEdit->GetVScrollBar();
1446 void VclMultiLineEdit::EnableFocusSelectionHide( bool bHide )
1448 pImpVclMEdit->GetTextWindow()->SetAutoFocusHide( bHide );
1451 void VclMultiLineEdit::DisableSelectionOnFocus()
1453 pImpVclMEdit->GetTextWindow()->DisableSelectionOnFocus();
1456 void VclMultiLineEdit::EnableCursor( bool bEnable )
1458 GetTextView()->EnableCursor( bEnable );
1461 bool VclMultiLineEdit::CanUp() const
1463 TextView* pTextView = GetTextView();
1464 const TextSelection& rTextSelection = pTextView->GetSelection();
1465 TextPaM aPaM(rTextSelection.GetEnd());
1466 return aPaM != pTextView->CursorUp(aPaM);
1469 bool VclMultiLineEdit::CanDown() const
1471 TextView* pTextView = GetTextView();
1472 const TextSelection& rTextSelection = pTextView->GetSelection();
1473 TextPaM aPaM(rTextSelection.GetEnd());
1474 return aPaM != pTextView->CursorDown(aPaM);
1477 TextWindow* VclMultiLineEdit::GetTextWindow()
1479 return pImpVclMEdit->GetTextWindow();
1482 FactoryFunction VclMultiLineEdit::GetUITestFactory() const
1484 return MultiLineEditUIObject::create;
1487 bool VclMultiLineEdit::set_property(const OUString &rKey, const OUString &rValue)
1489 if (rKey == "cursor-visible")
1490 EnableCursor(toBool(rValue));
1491 else if (rKey == "accepts-tab")
1492 pImpVclMEdit->GetTextWindow()->SetIgnoreTab(!toBool(rValue));
1493 else
1494 return Edit::set_property(rKey, rValue);
1495 return true;
1498 void VclMultiLineEdit::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
1500 Edit::DumpAsPropertyTree(rJsonWriter);
1502 rJsonWriter.put("cursor", pImpVclMEdit->GetTextWindow()->GetTextView()->IsCursorEnabled());
1505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */