bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / edit / vclmedit.cxx
blobe21d5c4c8f5736b7d94451757aae7d9c18de038e
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/timer.hxx>
27 #include <vcl/vclmedit.hxx>
28 #include <vcl/xtextedt.hxx>
29 #include <vcl/textview.hxx>
30 #include <vcl/ptrstyle.hxx>
32 #include <svl/undo.hxx>
33 #include <svl/lstner.hxx>
34 #include <vcl/uitest/uiobject.hxx>
36 #include <vcl/scrbar.hxx>
37 #include <vcl/settings.hxx>
38 #include <vcl/weld.hxx>
39 #include <osl/diagnose.h>
41 class ImpVclMEdit : public SfxListener
43 private:
44 VclPtr<VclMultiLineEdit> pVclMultiLineEdit;
46 VclPtr<TextWindow> mpTextWindow;
47 VclPtr<ScrollBar> mpHScrollBar;
48 VclPtr<ScrollBar> mpVScrollBar;
49 VclPtr<ScrollBarBox> mpScrollBox;
51 long mnTextWidth;
52 mutable Selection maSelection;
54 protected:
55 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
56 void ImpUpdateSrollBarVis( WinBits nWinStyle );
57 void ImpInitScrollBars();
58 void ImpSetScrollBarRanges();
59 void ImpSetHScrollBarThumbPos();
60 DECL_LINK( ScrollHdl, ScrollBar*, void );
62 public:
63 ImpVclMEdit( VclMultiLineEdit* pVclMultiLineEdit, WinBits nWinStyle );
64 virtual ~ImpVclMEdit() override;
66 void SetModified( bool bMod );
67 bool IsModified() const;
69 void SetReadOnly( bool bRdOnly );
70 bool IsReadOnly() const;
72 void SetMaxTextLen(sal_Int32 nLen);
73 sal_Int32 GetMaxTextLen() const;
75 void SetMaxTextWidth(long nMaxWidth);
77 void InsertText( const OUString& rStr );
78 OUString GetSelected() const;
79 OUString GetSelected( LineEnd aSeparator ) const;
81 void SetSelection( const Selection& rSelection );
82 const Selection& GetSelection() const;
84 void Cut();
85 void Copy();
86 void Paste();
88 void SetText( const OUString& rStr );
89 OUString GetText() const;
90 OUString GetText( LineEnd aSeparator ) const;
91 OUString GetTextLines( LineEnd aSeparator ) const;
93 void Resize();
94 void GetFocus();
96 bool HandleCommand( const CommandEvent& rCEvt );
98 void Enable( bool bEnable );
100 Size CalcMinimumSize() const;
101 Size CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const;
102 void GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const;
104 void SetAlign( WinBits nWinStyle );
106 void InitFromStyle( WinBits nWinStyle );
108 TextWindow* GetTextWindow() { return mpTextWindow; }
109 ScrollBar& GetHScrollBar() { return *mpHScrollBar; }
110 ScrollBar& GetVScrollBar() { return *mpVScrollBar; }
113 ImpVclMEdit::ImpVclMEdit( VclMultiLineEdit* pEdt, WinBits nWinStyle )
114 : pVclMultiLineEdit(pEdt)
115 , mpTextWindow(VclPtr<TextWindow>::Create(pEdt))
116 , mpHScrollBar(VclPtr<ScrollBar>::Create(pVclMultiLineEdit, WB_HSCROLL|WB_DRAG))
117 , mpVScrollBar(VclPtr<ScrollBar>::Create(pVclMultiLineEdit, WB_VSCROLL|WB_DRAG))
118 , mpScrollBox(VclPtr<ScrollBarBox>::Create(pVclMultiLineEdit, WB_SIZEABLE))
119 , mnTextWidth(0)
121 mpVScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
122 mpHScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
123 mpTextWindow->Show();
124 InitFromStyle( nWinStyle );
125 StartListening( *mpTextWindow->GetTextEngine() );
128 void ImpVclMEdit::ImpUpdateSrollBarVis( WinBits nWinStyle )
130 const bool bHaveVScroll = mpVScrollBar->IsVisible();
131 const bool bHaveHScroll = mpHScrollBar->IsVisible();
132 const bool bHaveScrollBox = mpScrollBox->IsVisible();
134 bool bNeedVScroll = ( nWinStyle & WB_VSCROLL ) == WB_VSCROLL;
135 const bool bNeedHScroll = ( nWinStyle & WB_HSCROLL ) == WB_HSCROLL;
137 const bool bAutoVScroll = ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL;
138 if ( !bNeedVScroll && bAutoVScroll )
140 TextEngine& rEngine( *mpTextWindow->GetTextEngine() );
141 long nOverallTextHeight(0);
142 for ( sal_uInt32 i=0; i<rEngine.GetParagraphCount(); ++i )
143 nOverallTextHeight += rEngine.GetTextHeight( i );
144 if ( nOverallTextHeight > mpTextWindow->GetOutputSizePixel().Height() )
145 bNeedVScroll = true;
148 const bool bNeedScrollBox = bNeedVScroll && bNeedHScroll;
150 bool bScrollbarsChanged = false;
151 if ( bHaveVScroll != bNeedVScroll )
153 mpVScrollBar->Show(bNeedVScroll);
154 bScrollbarsChanged = true;
157 if ( bHaveHScroll != bNeedHScroll )
159 mpHScrollBar->Show(bNeedHScroll);
160 bScrollbarsChanged = true;
163 if ( bHaveScrollBox != bNeedScrollBox )
165 mpScrollBox->Show(bNeedScrollBox);
168 if ( bScrollbarsChanged )
170 ImpInitScrollBars();
171 Resize();
175 void ImpVclMEdit::InitFromStyle( WinBits nWinStyle )
177 ImpUpdateSrollBarVis( nWinStyle );
178 SetAlign( nWinStyle );
180 if ( nWinStyle & WB_NOHIDESELECTION )
181 mpTextWindow->SetAutoFocusHide( false );
182 else
183 mpTextWindow->SetAutoFocusHide( true );
185 if ( nWinStyle & WB_READONLY )
186 mpTextWindow->GetTextView()->SetReadOnly( true );
187 else
188 mpTextWindow->GetTextView()->SetReadOnly( false );
190 if ( nWinStyle & WB_IGNORETAB )
192 mpTextWindow->SetIgnoreTab( true );
194 else
196 mpTextWindow->SetIgnoreTab( false );
197 // #103667# VclMultiLineEdit has the flag, but focusable window also needs this flag
198 WinBits nStyle = mpTextWindow->GetStyle();
199 nStyle |= WB_NODIALOGCONTROL;
200 mpTextWindow->SetStyle( nStyle );
204 ImpVclMEdit::~ImpVclMEdit()
206 EndListening( *mpTextWindow->GetTextEngine() );
207 mpTextWindow.disposeAndClear();
208 mpHScrollBar.disposeAndClear();
209 mpVScrollBar.disposeAndClear();
210 mpScrollBox.disposeAndClear();
211 pVclMultiLineEdit.disposeAndClear();
214 void ImpVclMEdit::ImpSetScrollBarRanges()
216 const long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
217 mpVScrollBar->SetRange( Range( 0, nTextHeight-1 ) );
219 mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
222 void ImpVclMEdit::ImpInitScrollBars()
224 static const sal_Unicode sampleChar = { 'x' };
226 ImpSetScrollBarRanges();
228 Size aCharBox;
229 aCharBox.setWidth( mpTextWindow->GetTextWidth( OUString(sampleChar) ) );
230 aCharBox.setHeight( mpTextWindow->GetTextHeight() );
231 Size aOutSz = mpTextWindow->GetOutputSizePixel();
233 mpHScrollBar->SetVisibleSize( aOutSz.Width() );
234 mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 );
235 mpHScrollBar->SetLineSize( aCharBox.Width()*10 );
236 ImpSetHScrollBarThumbPos();
238 mpVScrollBar->SetVisibleSize( aOutSz.Height() );
239 mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 );
240 mpVScrollBar->SetLineSize( aCharBox.Height() );
241 mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
244 void ImpVclMEdit::ImpSetHScrollBarThumbPos()
246 long nX = mpTextWindow->GetTextView()->GetStartDocPos().X();
247 if ( !mpTextWindow->GetTextEngine()->IsRightToLeft() )
248 mpHScrollBar->SetThumbPos( nX );
249 else
250 mpHScrollBar->SetThumbPos( mnTextWidth - mpHScrollBar->GetVisibleSize() - nX );
254 IMPL_LINK( ImpVclMEdit, ScrollHdl, ScrollBar*, pCurScrollBar, void )
256 long nDiffX = 0, nDiffY = 0;
258 if ( pCurScrollBar == mpVScrollBar )
259 nDiffY = mpTextWindow->GetTextView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
260 else if ( pCurScrollBar == mpHScrollBar )
261 nDiffX = mpTextWindow->GetTextView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
263 mpTextWindow->GetTextView()->Scroll( nDiffX, nDiffY );
264 // mpTextWindow->GetTextView()->ShowCursor( false, true );
267 void ImpVclMEdit::SetAlign( WinBits nWinStyle )
269 bool bRTL = AllSettings::GetLayoutRTL();
270 mpTextWindow->GetTextEngine()->SetRightToLeft( bRTL );
272 if ( nWinStyle & WB_CENTER )
273 mpTextWindow->GetTextEngine()->SetTextAlign( TxtAlign::Center );
274 else if ( nWinStyle & WB_RIGHT )
275 mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TxtAlign::Right : TxtAlign::Left );
276 else if ( nWinStyle & WB_LEFT )
277 mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TxtAlign::Left : TxtAlign::Right );
280 void ImpVclMEdit::SetModified( bool bMod )
282 mpTextWindow->GetTextEngine()->SetModified( bMod );
285 bool ImpVclMEdit::IsModified() const
287 return mpTextWindow->GetTextEngine()->IsModified();
290 void ImpVclMEdit::SetReadOnly( bool bRdOnly )
292 mpTextWindow->GetTextView()->SetReadOnly( bRdOnly );
293 // TODO: Adjust color?
296 bool ImpVclMEdit::IsReadOnly() const
298 return mpTextWindow->GetTextView()->IsReadOnly();
301 void ImpVclMEdit::SetMaxTextLen(sal_Int32 nLen)
303 mpTextWindow->GetTextEngine()->SetMaxTextLen(nLen);
306 sal_Int32 ImpVclMEdit::GetMaxTextLen() const
308 return mpTextWindow->GetTextEngine()->GetMaxTextLen();
311 void ImpVclMEdit::InsertText( const OUString& rStr )
313 mpTextWindow->GetTextView()->InsertText( rStr );
316 OUString ImpVclMEdit::GetSelected() const
318 return mpTextWindow->GetTextView()->GetSelected();
321 OUString ImpVclMEdit::GetSelected( LineEnd aSeparator ) const
323 return mpTextWindow->GetTextView()->GetSelected( aSeparator );
326 void ImpVclMEdit::SetMaxTextWidth(long nMaxWidth)
328 mpTextWindow->GetTextEngine()->SetMaxTextWidth(nMaxWidth);
331 void ImpVclMEdit::Resize()
333 int nIteration = 1;
336 WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
337 if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
338 ImpUpdateSrollBarVis( nWinStyle );
340 Size aSz = pVclMultiLineEdit->GetOutputSizePixel();
341 Size aEditSize = aSz;
342 long nSBWidth = pVclMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize();
343 nSBWidth = pVclMultiLineEdit->CalcZoom( nSBWidth );
345 if (mpHScrollBar->IsVisible())
346 aSz.AdjustHeight( -(nSBWidth+1) );
347 if (mpVScrollBar->IsVisible())
348 aSz.AdjustWidth( -(nSBWidth+1) );
350 if (!mpHScrollBar->IsVisible())
351 mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() );
352 else
353 mpHScrollBar->setPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth );
355 Point aTextWindowPos;
356 if (mpVScrollBar->IsVisible())
358 if( AllSettings::GetLayoutRTL() )
360 mpVScrollBar->setPosSizePixel( 0, 0, nSBWidth, aSz.Height() );
361 aTextWindowPos.AdjustX(nSBWidth );
363 else
364 mpVScrollBar->setPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() );
367 if (mpScrollBox->IsVisible())
368 mpScrollBox->setPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth );
370 Size aTextWindowSize( aSz );
371 if ( aTextWindowSize.Width() < 0 )
372 aTextWindowSize.setWidth( 0 );
373 if ( aTextWindowSize.Height() < 0 )
374 aTextWindowSize.setHeight( 0 );
376 Size aOldTextWindowSize( mpTextWindow->GetSizePixel() );
377 mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize );
378 if ( aOldTextWindowSize == aTextWindowSize )
379 break;
381 // Changing the text window size might effectively have changed the need for
382 // scrollbars, so do another iteration.
383 ++nIteration;
384 OSL_ENSURE( nIteration < 3, "ImpVclMEdit::Resize: isn't this expected to terminate with the second iteration?" );
386 } while ( nIteration <= 3 ); // artificial break after four iterations
388 ImpInitScrollBars();
391 void ImpVclMEdit::GetFocus()
393 mpTextWindow->GrabFocus();
396 void ImpVclMEdit::Cut()
398 if ( !mpTextWindow->GetTextView()->IsReadOnly() )
399 mpTextWindow->GetTextView()->Cut();
402 void ImpVclMEdit::Copy()
404 mpTextWindow->GetTextView()->Copy();
407 void ImpVclMEdit::Paste()
409 if ( !mpTextWindow->GetTextView()->IsReadOnly() )
410 mpTextWindow->GetTextView()->Paste();
413 void ImpVclMEdit::SetText( const OUString& rStr )
415 bool bWasModified = mpTextWindow->GetTextEngine()->IsModified();
416 mpTextWindow->GetTextEngine()->SetText( rStr );
417 if ( !bWasModified )
418 mpTextWindow->GetTextEngine()->SetModified( false );
420 mpTextWindow->GetTextView()->SetSelection( TextSelection() );
422 WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
423 if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
424 ImpUpdateSrollBarVis( nWinStyle );
427 OUString ImpVclMEdit::GetText() const
429 return mpTextWindow->GetTextEngine()->GetText();
432 OUString ImpVclMEdit::GetText( LineEnd aSeparator ) const
434 return mpTextWindow->GetTextEngine()->GetText( aSeparator );
437 OUString ImpVclMEdit::GetTextLines( LineEnd aSeparator ) const
439 return mpTextWindow->GetTextEngine()->GetTextLines( aSeparator );
442 void ImpVclMEdit::Notify( SfxBroadcaster&, const SfxHint& rHint )
444 const TextHint* pTextHint = dynamic_cast<const TextHint*>(&rHint);
445 if ( !pTextHint )
446 return;
448 switch (pTextHint->GetId())
450 case SfxHintId::TextViewScrolled:
451 if (mpHScrollBar->IsVisible())
452 ImpSetHScrollBarThumbPos();
453 if (mpVScrollBar->IsVisible())
454 mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
455 break;
457 case SfxHintId::TextHeightChanged:
458 if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() )
460 long nOutHeight = mpTextWindow->GetOutputSizePixel().Height();
461 long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
462 if ( nTextHeight < nOutHeight )
463 mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() );
465 ImpSetScrollBarRanges();
466 break;
468 case SfxHintId::TextFormatted:
469 if (mpHScrollBar->IsVisible())
471 const long nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
472 if ( nWidth != mnTextWidth )
474 mnTextWidth = nWidth;
475 mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
476 ImpSetHScrollBarThumbPos();
479 break;
481 case SfxHintId::TextModified:
482 ImpUpdateSrollBarVis(pVclMultiLineEdit->GetStyle());
483 pVclMultiLineEdit->Modify();
484 break;
486 case SfxHintId::TextViewSelectionChanged:
487 pVclMultiLineEdit->SelectionChanged();
488 break;
490 case SfxHintId::TextViewCaretChanged:
491 pVclMultiLineEdit->CaretChanged();
492 break;
494 default: break;
498 void ImpVclMEdit::SetSelection( const Selection& rSelection )
500 OUString aText = mpTextWindow->GetTextEngine()->GetText();
502 Selection aNewSelection( rSelection );
503 if ( aNewSelection.Min() < 0 )
504 aNewSelection.Min() = 0;
505 else if ( aNewSelection.Min() > aText.getLength() )
506 aNewSelection.Min() = aText.getLength();
507 if ( aNewSelection.Max() < 0 )
508 aNewSelection.Max() = 0;
509 else if ( aNewSelection.Max() > aText.getLength() )
510 aNewSelection.Max() = aText.getLength();
512 long nEnd = std::max( aNewSelection.Min(), aNewSelection.Max() );
513 TextSelection aTextSel;
514 sal_uInt32 nPara = 0;
515 sal_Int32 nChar = 0;
516 long x = 0;
517 while ( x <= nEnd )
519 if ( x == aNewSelection.Min() )
520 aTextSel.GetStart() = TextPaM( nPara, nChar );
521 if ( x == aNewSelection.Max() )
522 aTextSel.GetEnd() = TextPaM( nPara, nChar );
524 if ( ( x < aText.getLength() ) && ( aText[ x ] == '\n' ) )
526 nPara++;
527 nChar = 0;
529 else
530 nChar++;
531 x++;
533 mpTextWindow->GetTextView()->SetSelection( aTextSel );
536 const Selection& ImpVclMEdit::GetSelection() const
538 maSelection = Selection();
539 TextSelection aTextSel( mpTextWindow->GetTextView()->GetSelection() );
540 aTextSel.Justify();
541 // flatten selection => every line-break a character
543 ExtTextEngine* pExtTextEngine = mpTextWindow->GetTextEngine();
544 // paragraphs before
545 for ( sal_uInt32 n = 0; n < aTextSel.GetStart().GetPara(); ++n )
547 maSelection.Min() += pExtTextEngine->GetTextLen( n );
548 maSelection.Min()++;
551 // first paragraph with selection
552 maSelection.Max() = maSelection.Min();
553 maSelection.Min() += aTextSel.GetStart().GetIndex();
555 for ( sal_uInt32 n = aTextSel.GetStart().GetPara(); n < aTextSel.GetEnd().GetPara(); ++n )
557 maSelection.Max() += pExtTextEngine->GetTextLen( n );
558 maSelection.Max()++;
561 maSelection.Max() += aTextSel.GetEnd().GetIndex();
563 return maSelection;
566 Size ImpVclMEdit::CalcMinimumSize() const
568 Size aSz( mpTextWindow->GetTextEngine()->CalcTextWidth(),
569 mpTextWindow->GetTextEngine()->GetTextHeight() );
571 if (mpHScrollBar->IsVisible())
572 aSz.AdjustHeight(mpHScrollBar->GetSizePixel().Height() );
573 if (mpVScrollBar->IsVisible())
574 aSz.AdjustWidth(mpVScrollBar->GetSizePixel().Width() );
576 return aSz;
579 Size ImpVclMEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
581 static const sal_Unicode sampleChar = 'X';
583 Size aSz;
584 Size aCharSz;
585 aCharSz.setWidth( mpTextWindow->GetTextWidth( OUString(sampleChar) ) );
586 aCharSz.setHeight( mpTextWindow->GetTextHeight() );
588 if ( nLines )
589 aSz.setHeight( nLines*aCharSz.Height() );
590 else
591 aSz.setHeight( mpTextWindow->GetTextEngine()->GetTextHeight() );
593 if ( nColumns )
594 aSz.setWidth( nColumns*aCharSz.Width() );
595 else
596 aSz.setWidth( mpTextWindow->GetTextEngine()->CalcTextWidth() );
598 if (mpHScrollBar->IsVisible())
599 aSz.AdjustHeight(mpHScrollBar->GetSizePixel().Height() );
600 if (mpVScrollBar->IsVisible())
601 aSz.AdjustWidth(mpVScrollBar->GetSizePixel().Width() );
603 return aSz;
606 void ImpVclMEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
608 static const sal_Unicode sampleChar = { 'x' };
609 Size aOutSz = mpTextWindow->GetOutputSizePixel();
610 Size aCharSz( mpTextWindow->GetTextWidth( OUString(sampleChar) ), mpTextWindow->GetTextHeight() );
611 rnCols = static_cast<sal_uInt16>(aOutSz.Width()/aCharSz.Width());
612 rnLines = static_cast<sal_uInt16>(aOutSz.Height()/aCharSz.Height());
615 void ImpVclMEdit::Enable( bool bEnable )
617 mpTextWindow->Enable( bEnable );
618 if (mpHScrollBar->IsVisible())
619 mpHScrollBar->Enable( bEnable );
620 if (mpVScrollBar->IsVisible())
621 mpVScrollBar->Enable( bEnable );
624 bool ImpVclMEdit::HandleCommand( const CommandEvent& rCEvt )
626 bool bDone = false;
627 CommandEventId nCommand = rCEvt.GetCommand();
628 if (nCommand == CommandEventId::Wheel ||
629 nCommand == CommandEventId::StartAutoScroll ||
630 nCommand == CommandEventId::AutoScroll ||
631 nCommand == CommandEventId::Gesture)
633 ScrollBar* pHScrollBar = mpHScrollBar->IsVisible() ? mpHScrollBar.get() : nullptr;
634 ScrollBar* pVScrollBar = mpVScrollBar->IsVisible() ? mpVScrollBar.get() : nullptr;
635 mpTextWindow->HandleScrollCommand(rCEvt, pHScrollBar, pVScrollBar);
636 bDone = true;
638 return bDone;
641 TextWindow::TextWindow(Edit* pParent)
642 : Window(pParent)
643 , mxParent(pParent)
645 mbInMBDown = false;
646 mbFocusSelectionHide = false;
647 mbIgnoreTab = false;
648 mbActivePopup = false;
649 mbSelectOnTab = true;
651 SetPointer( PointerStyle::Text );
653 mpExtTextEngine.reset(new ExtTextEngine);
654 mpExtTextEngine->SetMaxTextLen(EDIT_NOLIMIT);
655 if( pParent->GetStyle() & WB_BORDER )
656 mpExtTextEngine->SetLeftMargin( 2 );
657 mpExtTextEngine->SetLocale( GetSettings().GetLanguageTag().getLocale() );
658 mpExtTextView.reset(new TextView( mpExtTextEngine.get(), this ));
659 mpExtTextEngine->InsertView( mpExtTextView.get() );
660 mpExtTextEngine->EnableUndo( true );
661 mpExtTextView->ShowCursor();
663 Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor();
664 SetBackground( aBackgroundColor );
665 pParent->SetBackground( aBackgroundColor );
668 TextWindow::~TextWindow()
670 disposeOnce();
673 void TextWindow::dispose()
675 mxParent.clear();
676 mpExtTextView.reset();
677 mpExtTextEngine.reset();
678 Window::dispose();
681 void TextWindow::MouseMove( const MouseEvent& rMEvt )
683 mpExtTextView->MouseMove( rMEvt );
684 Window::MouseMove( rMEvt );
687 void TextWindow::MouseButtonDown( const MouseEvent& rMEvt )
689 mbInMBDown = true; // so that GetFocus does not select everything
690 mpExtTextView->MouseButtonDown( rMEvt );
691 GrabFocus();
692 mbInMBDown = false;
695 void TextWindow::MouseButtonUp( const MouseEvent& rMEvt )
697 mpExtTextView->MouseButtonUp( rMEvt );
700 void TextWindow::KeyInput( const KeyEvent& rKEvent )
702 bool bDone = false;
703 sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
704 if ( nCode == css::awt::Key::SELECT_ALL ||
705 ( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() )
708 mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
709 bDone = true;
711 else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() )
713 if ( Edit::GetGetSpecialCharsFunction() )
715 // to maintain the selection
716 mbActivePopup = true;
717 OUString aChars = Edit::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont());
718 if (!aChars.isEmpty())
720 mpExtTextView->InsertText( aChars );
721 mpExtTextView->GetTextEngine()->SetModified( true );
723 mbActivePopup = false;
724 bDone = true;
727 else if ( nCode == KEY_TAB )
729 if ( !mbIgnoreTab || rKEvent.GetKeyCode().IsMod1() )
730 bDone = mpExtTextView->KeyInput( rKEvent );
732 else
734 bDone = mpExtTextView->KeyInput( rKEvent );
737 if ( !bDone )
738 Window::KeyInput( rKEvent );
741 void TextWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
743 mpExtTextView->Paint(rRenderContext, rRect);
746 void TextWindow::Resize()
750 void TextWindow::Command( const CommandEvent& rCEvt )
752 if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
754 VclPtr<PopupMenu> pPopup = mxParent->CreatePopupMenu();
755 bool bEnableCut = true;
756 bool bEnableCopy = true;
757 bool bEnableDelete = true;
758 bool bEnablePaste = true;
759 bool bEnableSpecialChar = true;
760 bool bEnableUndo = true;
762 if ( !mpExtTextView->HasSelection() )
764 bEnableCut = false;
765 bEnableCopy = false;
766 bEnableDelete = false;
768 if ( mpExtTextView->IsReadOnly() )
770 bEnableCut = false;
771 bEnablePaste = false;
772 bEnableDelete = false;
773 bEnableSpecialChar = false;
775 if ( !mpExtTextView->GetTextEngine()->HasUndoManager() || !mpExtTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() )
777 bEnableUndo = false;
779 pPopup->EnableItem(pPopup->GetItemId("cut"), bEnableCut);
780 pPopup->EnableItem(pPopup->GetItemId("copy"), bEnableCopy);
781 pPopup->EnableItem(pPopup->GetItemId("delete"), bEnableDelete);
782 pPopup->EnableItem(pPopup->GetItemId("paste"), bEnablePaste);
783 pPopup->EnableItem(pPopup->GetItemId("specialchar"), bEnableSpecialChar);
784 pPopup->EnableItem(pPopup->GetItemId("undo"), bEnableUndo);
785 pPopup->ShowItem(pPopup->GetItemId("specialchar"), !Edit::GetGetSpecialCharsFunction());
787 mbActivePopup = true;
788 Point aPos = rCEvt.GetMousePosPixel();
789 if ( !rCEvt.IsMouseEvent() )
791 // Sometime do show Menu centered in the selection !!!
792 Size aSize = GetOutputSizePixel();
793 aPos = Point( aSize.Width()/2, aSize.Height()/2 );
795 sal_uInt16 n = pPopup->Execute( this, aPos );
796 OString sCommand = pPopup->GetItemIdent(n);
797 if (sCommand == "undo")
799 mpExtTextView->Undo();
800 mpExtTextEngine->SetModified( true );
801 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
803 else if (sCommand == "cut")
805 mpExtTextView->Cut();
806 mpExtTextEngine->SetModified( true );
807 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
809 else if (sCommand == "copy")
811 mpExtTextView->Copy();
813 else if (sCommand == "paste")
815 mpExtTextView->Paste();
816 mpExtTextEngine->SetModified( true );
817 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
819 else if (sCommand == "delete")
821 mpExtTextView->DeleteSelected();
822 mpExtTextEngine->SetModified( true );
823 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
825 else if (sCommand == "selectall")
827 mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
829 else if (sCommand == "specialchar")
831 OUString aChars = Edit::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont());
832 if (!aChars.isEmpty())
834 mpExtTextView->InsertText( aChars );
835 mpExtTextEngine->SetModified( true );
836 mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
839 pPopup.clear();
840 mbActivePopup = false;
842 else
844 mpExtTextView->Command( rCEvt );
846 Window::Command( rCEvt );
849 void TextWindow::GetFocus()
851 Window::GetFocus();
852 if ( !mbActivePopup )
854 bool bGotoCursor = !mpExtTextView->IsReadOnly();
855 if ( mbFocusSelectionHide && IsReallyVisible()
856 && ( mbSelectOnTab &&
857 (!mbInMBDown || ( GetSettings().GetStyleSettings().GetSelectionOptions() & SelectionOptions::Focus ) )) )
859 // select everything, but do not scroll
860 bool bAutoScroll = mpExtTextView->IsAutoScroll();
861 mpExtTextView->SetAutoScroll( false );
862 mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
863 mpExtTextView->SetAutoScroll( bAutoScroll );
864 bGotoCursor = false;
866 mpExtTextView->SetPaintSelection( true );
867 mpExtTextView->ShowCursor( bGotoCursor );
871 void TextWindow::LoseFocus()
873 Window::LoseFocus();
875 if ( mbFocusSelectionHide && !mbActivePopup && mpExtTextView )
876 mpExtTextView->SetPaintSelection( false );
879 VclMultiLineEdit::VclMultiLineEdit( vcl::Window* pParent, WinBits nWinStyle )
880 : Edit( pParent, nWinStyle )
882 SetType( WindowType::MULTILINEEDIT );
883 pImpVclMEdit.reset(new ImpVclMEdit( this, nWinStyle ));
884 ImplInitSettings( true );
885 pUpdateDataTimer = nullptr;
887 SetCompoundControl( true );
888 SetStyle( ImplInitStyle( nWinStyle ) );
891 VclMultiLineEdit::~VclMultiLineEdit()
893 disposeOnce();
896 void VclMultiLineEdit::dispose()
898 pImpVclMEdit.reset();
899 pUpdateDataTimer.reset();
900 Edit::dispose();
903 WinBits VclMultiLineEdit::ImplInitStyle( WinBits nStyle )
905 if ( !(nStyle & WB_NOTABSTOP) )
906 nStyle |= WB_TABSTOP;
908 if ( !(nStyle & WB_NOGROUP) )
909 nStyle |= WB_GROUP;
911 if ( !(nStyle & WB_IGNORETAB ))
912 nStyle |= WB_NODIALOGCONTROL;
914 return nStyle;
917 void VclMultiLineEdit::ApplySettings(vcl::RenderContext& rRenderContext)
919 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
921 // The Font has to be adjusted, as the TextEngine does not take care of
922 // TextColor/Background
924 Color aTextColor = rStyleSettings.GetFieldTextColor();
925 if (IsControlForeground())
926 aTextColor = GetControlForeground();
928 if (!IsEnabled())
929 aTextColor = rStyleSettings.GetDisableColor();
931 vcl::Font aFont = rStyleSettings.GetFieldFont();
932 aFont.SetTransparent(IsPaintTransparent());
933 ApplyControlFont(rRenderContext, aFont);
935 vcl::Font theFont = rRenderContext.GetFont();
936 theFont.SetColor(aTextColor);
937 if (IsPaintTransparent())
938 theFont.SetFillColor(COL_TRANSPARENT);
939 else
940 theFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
942 pImpVclMEdit->GetTextWindow()->SetFont(theFont);
943 // FIXME: next call causes infinite invalidation loop, rethink how to properly fix this situation
944 // pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(theFont);
945 pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
947 if (IsPaintTransparent())
949 pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
950 pImpVclMEdit->GetTextWindow()->SetBackground();
951 pImpVclMEdit->GetTextWindow()->SetControlBackground();
952 rRenderContext.SetBackground();
953 SetControlBackground();
955 else
957 if (IsControlBackground())
958 pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
959 else
960 pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
961 // also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
962 rRenderContext.SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
966 void VclMultiLineEdit::ImplInitSettings(bool bBackground)
968 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
970 // The Font has to be adjusted, as the TextEngine does not take care of
971 // TextColor/Background
973 Color aTextColor = rStyleSettings.GetFieldTextColor();
974 if (IsControlForeground())
975 aTextColor = GetControlForeground();
976 if (!IsEnabled())
977 aTextColor = rStyleSettings.GetDisableColor();
979 vcl::Font aFont = rStyleSettings.GetFieldFont();
980 aFont.SetTransparent(IsPaintTransparent());
981 ApplyControlFont(*this, aFont);
983 vcl::Font TheFont = GetFont();
984 TheFont.SetColor(aTextColor);
985 if (IsPaintTransparent())
986 TheFont.SetFillColor(COL_TRANSPARENT);
987 else
988 TheFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
989 pImpVclMEdit->GetTextWindow()->SetFont(TheFont);
990 pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(TheFont);
991 pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
993 if (bBackground)
995 if (IsPaintTransparent())
997 pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
998 pImpVclMEdit->GetTextWindow()->SetBackground();
999 pImpVclMEdit->GetTextWindow()->SetControlBackground();
1000 SetBackground();
1001 SetControlBackground();
1003 else
1005 if (IsControlBackground())
1006 pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
1007 else
1008 pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
1009 // also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
1010 SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
1015 void VclMultiLineEdit::Modify()
1017 aModifyHdlLink.Call( *this );
1019 CallEventListeners( VclEventId::EditModify );
1021 if ( pUpdateDataTimer )
1022 pUpdateDataTimer->Start();
1025 void VclMultiLineEdit::SelectionChanged()
1027 CallEventListeners(VclEventId::EditSelectionChanged);
1030 void VclMultiLineEdit::CaretChanged()
1032 CallEventListeners(VclEventId::EditCaretChanged);
1035 IMPL_LINK_NOARG(VclMultiLineEdit, ImpUpdateDataHdl, Timer *, void)
1037 UpdateData();
1040 void VclMultiLineEdit::UpdateData()
1044 void VclMultiLineEdit::SetModifyFlag()
1046 pImpVclMEdit->SetModified( true );
1049 void VclMultiLineEdit::ClearModifyFlag()
1051 pImpVclMEdit->SetModified( false );
1054 bool VclMultiLineEdit::IsModified() const
1056 return pImpVclMEdit->IsModified();
1059 void VclMultiLineEdit::EnableUpdateData( sal_uLong nTimeout )
1061 if ( !nTimeout )
1062 DisableUpdateData();
1063 else
1065 if ( !pUpdateDataTimer )
1067 pUpdateDataTimer.reset(new Timer("MultiLineEditTimer"));
1068 pUpdateDataTimer->SetInvokeHandler( LINK( this, VclMultiLineEdit, ImpUpdateDataHdl ) );
1070 pUpdateDataTimer->SetTimeout( nTimeout );
1074 void VclMultiLineEdit::SetReadOnly( bool bReadOnly )
1076 pImpVclMEdit->SetReadOnly( bReadOnly );
1077 Edit::SetReadOnly( bReadOnly );
1079 // #94921# ReadOnly can be overwritten in InitFromStyle() when WB not set.
1080 WinBits nStyle = GetStyle();
1081 if ( bReadOnly )
1082 nStyle |= WB_READONLY;
1083 else
1084 nStyle &= ~WB_READONLY;
1085 SetStyle( nStyle );
1088 bool VclMultiLineEdit::IsReadOnly() const
1090 return pImpVclMEdit->IsReadOnly();
1093 void VclMultiLineEdit::SetMaxTextLen(sal_Int32 nMaxLen)
1095 pImpVclMEdit->SetMaxTextLen(nMaxLen);
1098 void VclMultiLineEdit::SetMaxTextWidth(long nMaxWidth)
1100 pImpVclMEdit->SetMaxTextWidth(nMaxWidth );
1103 sal_Int32 VclMultiLineEdit::GetMaxTextLen() const
1105 return pImpVclMEdit->GetMaxTextLen();
1108 void VclMultiLineEdit::ReplaceSelected( const OUString& rStr )
1110 pImpVclMEdit->InsertText( rStr );
1113 void VclMultiLineEdit::DeleteSelected()
1115 pImpVclMEdit->InsertText( OUString() );
1118 OUString VclMultiLineEdit::GetSelected() const
1120 return pImpVclMEdit->GetSelected();
1123 OUString VclMultiLineEdit::GetSelected( LineEnd aSeparator ) const
1125 return pImpVclMEdit->GetSelected( aSeparator );
1128 void VclMultiLineEdit::Cut()
1130 pImpVclMEdit->Cut();
1133 void VclMultiLineEdit::Copy()
1135 pImpVclMEdit->Copy();
1138 void VclMultiLineEdit::Paste()
1140 pImpVclMEdit->Paste();
1143 void VclMultiLineEdit::SetText( const OUString& rStr )
1145 pImpVclMEdit->SetText( rStr );
1148 OUString VclMultiLineEdit::GetText() const
1150 return pImpVclMEdit ? pImpVclMEdit->GetText() : OUString();
1153 OUString VclMultiLineEdit::GetText( LineEnd aSeparator ) const
1155 return pImpVclMEdit ? pImpVclMEdit->GetText( aSeparator ) : OUString();
1158 OUString VclMultiLineEdit::GetTextLines( LineEnd aSeparator ) const
1160 return pImpVclMEdit ? pImpVclMEdit->GetTextLines( aSeparator ) : OUString();
1163 void VclMultiLineEdit::Resize()
1165 pImpVclMEdit->Resize();
1168 void VclMultiLineEdit::GetFocus()
1170 if ( !pImpVclMEdit ) // might be called from within the dtor, when pImpVclMEdit == NULL is a valid state
1171 return;
1173 pImpVclMEdit->GetFocus();
1176 void VclMultiLineEdit::SetSelection( const Selection& rSelection )
1178 pImpVclMEdit->SetSelection( rSelection );
1181 const Selection& VclMultiLineEdit::GetSelection() const
1183 return pImpVclMEdit->GetSelection();
1186 Size VclMultiLineEdit::CalcMinimumSize() const
1188 Size aSz = pImpVclMEdit->CalcMinimumSize();
1190 sal_Int32 nLeft, nTop, nRight, nBottom;
1191 static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1192 aSz.AdjustWidth(nLeft+nRight );
1193 aSz.AdjustHeight(nTop+nBottom );
1195 return aSz;
1198 Size VclMultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const
1200 Size aSz = rPrefSize;
1201 sal_Int32 nLeft, nTop, nRight, nBottom;
1202 static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1204 // center vertically for whole lines
1206 long nHeight = aSz.Height() - nTop - nBottom;
1207 long nLineHeight = pImpVclMEdit->CalcBlockSize( 1, 1 ).Height();
1208 long nLines = nHeight / nLineHeight;
1209 if ( nLines < 1 )
1210 nLines = 1;
1212 aSz.setHeight( nLines * nLineHeight );
1213 aSz.AdjustHeight(nTop+nBottom );
1215 return aSz;
1218 Size VclMultiLineEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1220 Size aSz = pImpVclMEdit->CalcBlockSize( nColumns, nLines );
1222 sal_Int32 nLeft, nTop, nRight, nBottom;
1223 static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1224 aSz.AdjustWidth(nLeft+nRight );
1225 aSz.AdjustHeight(nTop+nBottom );
1226 return aSz;
1229 void VclMultiLineEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1231 pImpVclMEdit->GetMaxVisColumnsAndLines( rnCols, rnLines );
1234 void VclMultiLineEdit::StateChanged( StateChangedType nType )
1236 if( nType == StateChangedType::Enable )
1238 pImpVclMEdit->Enable( IsEnabled() );
1239 ImplInitSettings( false );
1241 else if( nType == StateChangedType::ReadOnly )
1243 pImpVclMEdit->SetReadOnly( IsReadOnly() );
1245 else if ( nType == StateChangedType::Zoom )
1247 pImpVclMEdit->GetTextWindow()->SetZoom( GetZoom() );
1248 ImplInitSettings( false );
1249 Resize();
1251 else if ( nType == StateChangedType::ControlFont )
1253 ImplInitSettings( false );
1254 Resize();
1255 Invalidate();
1257 else if ( nType == StateChangedType::ControlForeground )
1259 ImplInitSettings( false );
1260 Invalidate();
1262 else if ( nType == StateChangedType::ControlBackground )
1264 ImplInitSettings( true );
1265 Invalidate();
1267 else if ( nType == StateChangedType::Style )
1269 pImpVclMEdit->InitFromStyle( GetStyle() );
1270 SetStyle( ImplInitStyle( GetStyle() ) );
1272 else if ( nType == StateChangedType::InitShow )
1274 if( IsPaintTransparent() )
1276 pImpVclMEdit->GetTextWindow()->SetPaintTransparent( true );
1277 pImpVclMEdit->GetTextWindow()->SetBackground();
1278 pImpVclMEdit->GetTextWindow()->SetControlBackground();
1279 SetBackground();
1280 SetControlBackground();
1284 Control::StateChanged( nType );
1287 void VclMultiLineEdit::DataChanged( const DataChangedEvent& rDCEvt )
1289 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1290 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1292 ImplInitSettings( true );
1293 Resize();
1294 Invalidate();
1296 else
1297 Control::DataChanged( rDCEvt );
1300 void VclMultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, DrawFlags nFlags )
1302 ImplInitSettings(true);
1304 Point aPos = pDev->LogicToPixel( rPos );
1305 Size aSize = pDev->LogicToPixel( rSize );
1307 vcl::Font aFont = pImpVclMEdit->GetTextWindow()->GetDrawPixelFont(pDev);
1308 aFont.SetTransparent( true );
1309 OutDevType eOutDevType = pDev->GetOutDevType();
1311 pDev->Push();
1312 pDev->SetMapMode();
1313 pDev->SetFont( aFont );
1314 pDev->SetTextFillColor();
1316 // Border/Background
1317 pDev->SetLineColor();
1318 pDev->SetFillColor();
1319 bool bBorder = (GetStyle() & WB_BORDER);
1320 bool bBackground = IsControlBackground();
1321 if ( bBorder || bBackground )
1323 tools::Rectangle aRect( aPos, aSize );
1324 if ( bBorder )
1326 DecorationView aDecoView( pDev );
1327 aRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleIn );
1329 if ( bBackground )
1331 pDev->SetFillColor( GetControlBackground() );
1332 pDev->DrawRect( aRect );
1336 // contents
1337 if ( ( nFlags & DrawFlags::Mono ) || ( eOutDevType == OUTDEV_PRINTER ) )
1338 pDev->SetTextColor( COL_BLACK );
1339 else
1341 if ( !IsEnabled() )
1343 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1344 pDev->SetTextColor( rStyleSettings.GetDisableColor() );
1346 else
1348 pDev->SetTextColor( GetTextColor() );
1352 OUString aText = GetText();
1353 Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() );
1354 sal_uLong nLines = static_cast<sal_uLong>(aSize.Height() / aTextSz.Height());
1355 if ( !nLines )
1356 nLines = 1;
1357 aTextSz.setHeight( nLines*aTextSz.Height() );
1358 long nOnePixel = GetDrawPixel( pDev, 1 );
1359 long nOffX = 3*nOnePixel;
1360 long nOffY = 2*nOnePixel;
1362 // Clipping?
1363 if ( ( nOffY < 0 ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) )
1365 tools::Rectangle aClip( aPos, aSize );
1366 if ( aTextSz.Height() > aSize.Height() )
1367 aClip.AdjustBottom(aTextSz.Height() - aSize.Height() + 1 ); // so that HP-printer does not 'optimize-away'
1368 pDev->IntersectClipRegion( aClip );
1371 ExtTextEngine aTE;
1372 aTE.SetText( GetText() );
1373 aTE.SetMaxTextWidth( aSize.Width() );
1374 aTE.SetFont( aFont );
1375 aTE.SetTextAlign( pImpVclMEdit->GetTextWindow()->GetTextEngine()->GetTextAlign() );
1376 aTE.Draw( pDev, Point( aPos.X() + nOffX, aPos.Y() + nOffY ) );
1378 pDev->Pop();
1381 bool VclMultiLineEdit::EventNotify( NotifyEvent& rNEvt )
1383 bool bDone = false;
1384 if( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
1386 bDone = pImpVclMEdit->HandleCommand( *rNEvt.GetCommandEvent() );
1388 return bDone || Edit::EventNotify( rNEvt );
1391 bool VclMultiLineEdit::PreNotify( NotifyEvent& rNEvt )
1393 bool bDone = false;
1395 if( ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) )
1397 const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
1398 if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) )
1400 bDone = true;
1401 TextSelection aSel = pImpVclMEdit->GetTextWindow()->GetTextView()->GetSelection();
1402 if ( aSel.HasRange() )
1404 aSel.GetStart() = aSel.GetEnd();
1405 pImpVclMEdit->GetTextWindow()->GetTextView()->SetSelection( aSel );
1407 else
1409 switch ( rKEvent.GetKeyCode().GetCode() )
1411 case KEY_UP:
1413 if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1414 pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::LineUp );
1416 break;
1417 case KEY_DOWN:
1419 if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1420 pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::LineDown );
1422 break;
1423 case KEY_PAGEUP :
1425 if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1426 pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::PageUp );
1428 break;
1429 case KEY_PAGEDOWN:
1431 if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1432 pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::PageDown );
1434 break;
1435 case KEY_LEFT:
1437 if ( pImpVclMEdit->GetHScrollBar().IsVisible() )
1438 pImpVclMEdit->GetHScrollBar().DoScrollAction( ScrollType::LineUp );
1440 break;
1441 case KEY_RIGHT:
1443 if ( pImpVclMEdit->GetHScrollBar().IsVisible() )
1444 pImpVclMEdit->GetHScrollBar().DoScrollAction( ScrollType::LineDown );
1446 break;
1447 case KEY_HOME:
1449 if ( rKEvent.GetKeyCode().IsMod1() )
1450 pImpVclMEdit->GetTextWindow()->GetTextView()->
1451 SetSelection( TextSelection( TextPaM( 0, 0 ) ) );
1453 break;
1454 case KEY_END:
1456 if ( rKEvent.GetKeyCode().IsMod1() )
1457 pImpVclMEdit->GetTextWindow()->GetTextView()->
1458 SetSelection( TextSelection( TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
1460 break;
1461 default:
1463 bDone = false;
1470 return bDone || Edit::PreNotify( rNEvt );
1473 // Internals for derived classes, e.g. TextComponent
1475 ExtTextEngine* VclMultiLineEdit::GetTextEngine() const
1477 return pImpVclMEdit->GetTextWindow()->GetTextEngine();
1480 TextView* VclMultiLineEdit::GetTextView() const
1482 return pImpVclMEdit->GetTextWindow()->GetTextView();
1485 ScrollBar& VclMultiLineEdit::GetVScrollBar() const
1487 return pImpVclMEdit->GetVScrollBar();
1490 void VclMultiLineEdit::EnableFocusSelectionHide( bool bHide )
1492 pImpVclMEdit->GetTextWindow()->SetAutoFocusHide( bHide );
1495 void VclMultiLineEdit::SetRightToLeft( bool bRightToLeft )
1497 if ( GetTextEngine() )
1499 GetTextEngine()->SetRightToLeft( bRightToLeft );
1500 GetTextView()->ShowCursor();
1504 void VclMultiLineEdit::DisableSelectionOnFocus()
1506 pImpVclMEdit->GetTextWindow()->DisableSelectionOnFocus();
1509 void VclMultiLineEdit::EnableCursor( bool bEnable )
1511 GetTextView()->EnableCursor( bEnable );
1514 TextWindow* VclMultiLineEdit::GetTextWindow()
1516 return pImpVclMEdit->GetTextWindow();
1519 FactoryFunction VclMultiLineEdit::GetUITestFactory() const
1521 return MultiLineEditUIObject::create;
1524 bool VclMultiLineEdit::set_property(const OString &rKey, const OUString &rValue)
1526 if (rKey == "cursor-visible")
1527 EnableCursor(toBool(rValue));
1528 else if (rKey == "accepts-tab")
1529 pImpVclMEdit->GetTextWindow()->SetIgnoreTab(!toBool(rValue));
1530 else
1531 return Edit::set_property(rKey, rValue);
1532 return true;
1535 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */