Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <tools/rc.h>
21 : #include <vcl/builder.hxx>
22 : #include <vcl/decoview.hxx>
23 : #include <vcl/svapp.hxx>
24 :
25 : #include <vcl/vclmedit.hxx>
26 : #include <vcl/xtextedt.hxx>
27 : #include <svl/undo.hxx>
28 : #include <svl/lstner.hxx>
29 : #include <svl/smplhint.hxx>
30 :
31 : #include <svids.hrc>
32 : #include <vcl/scrbar.hxx>
33 : #include <vcl/settings.hxx>
34 :
35 : class TextWindow : public vcl::Window
36 : {
37 : private:
38 : ExtTextEngine* mpExtTextEngine;
39 : ExtTextView* mpExtTextView;
40 :
41 : bool mbInMBDown;
42 : bool mbFocusSelectionHide;
43 : bool mbIgnoreTab;
44 : bool mbActivePopup;
45 : bool mbSelectOnTab;
46 : bool mbTextSelectable;
47 :
48 : public:
49 : explicit TextWindow( vcl::Window* pParent );
50 : virtual ~TextWindow();
51 : virtual void dispose() SAL_OVERRIDE;
52 :
53 1438 : ExtTextEngine* GetTextEngine() const { return mpExtTextEngine; }
54 677 : ExtTextView* GetTextView() const { return mpExtTextView; }
55 :
56 : virtual void MouseMove( const MouseEvent& rMEvt ) SAL_OVERRIDE;
57 : virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
58 : virtual void MouseButtonUp( const MouseEvent& rMEvt ) SAL_OVERRIDE;
59 : virtual void KeyInput( const KeyEvent& rKEvent ) SAL_OVERRIDE;
60 :
61 : virtual void Command( const CommandEvent& rCEvt ) SAL_OVERRIDE;
62 :
63 : virtual void Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect) SAL_OVERRIDE;
64 : virtual void Resize() SAL_OVERRIDE;
65 :
66 : virtual void GetFocus() SAL_OVERRIDE;
67 : virtual void LoseFocus() SAL_OVERRIDE;
68 :
69 163 : void SetAutoFocusHide( bool bAutoHide ) { mbFocusSelectionHide = bAutoHide; }
70 :
71 150 : void SetIgnoreTab( bool bIgnore ) { mbIgnoreTab = bIgnore; }
72 :
73 11 : void DisableSelectionOnFocus() { mbSelectOnTab = false; }
74 : };
75 :
76 : class ImpVclMEdit : public SfxListener
77 : {
78 : private:
79 : VclPtr<VclMultiLineEdit> pVclMultiLineEdit;
80 :
81 : VclPtr<TextWindow> mpTextWindow;
82 : VclPtr<ScrollBar> mpHScrollBar;
83 : VclPtr<ScrollBar> mpVScrollBar;
84 : VclPtr<ScrollBarBox> mpScrollBox;
85 :
86 : Point maTextWindowOffset;
87 : sal_Int32 mnTextWidth;
88 : mutable Selection maSelection;
89 :
90 : protected:
91 : virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE;
92 : void ImpUpdateSrollBarVis( WinBits nWinStyle );
93 : void ImpInitScrollBars();
94 : void ImpSetScrollBarRanges();
95 : void ImpSetHScrollBarThumbPos();
96 : DECL_LINK( ScrollHdl, ScrollBar* );
97 :
98 : public:
99 : ImpVclMEdit( VclMultiLineEdit* pVclMultiLineEdit, WinBits nWinStyle );
100 : virtual ~ImpVclMEdit();
101 :
102 : void SetModified( bool bMod );
103 : bool IsModified() const;
104 :
105 : void SetReadOnly( bool bRdOnly );
106 : bool IsReadOnly() const;
107 :
108 : void SetMaxTextLen(sal_Int32 nLen);
109 : sal_Int32 GetMaxTextLen() const;
110 :
111 : void SetMaxTextWidth( sal_uLong nMaxWidth );
112 :
113 : void InsertText( const OUString& rStr );
114 : OUString GetSelected() const;
115 : OUString GetSelected( LineEnd aSeparator ) const;
116 :
117 : void SetSelection( const Selection& rSelection );
118 : const Selection& GetSelection() const;
119 :
120 : void Cut();
121 : void Copy();
122 : void Paste();
123 :
124 : void SetText( const OUString& rStr );
125 : OUString GetText() const;
126 : OUString GetText( LineEnd aSeparator ) const;
127 : OUString GetTextLines( LineEnd aSeparator ) const;
128 :
129 : void Resize();
130 : void GetFocus();
131 :
132 : bool HandleCommand( const CommandEvent& rCEvt );
133 :
134 : void Enable( bool bEnable );
135 :
136 : Size CalcMinimumSize() const;
137 : Size CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const;
138 : void GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const;
139 :
140 : void SetAlign( WinBits nWinStyle );
141 :
142 : void InitFromStyle( WinBits nWinStyle );
143 :
144 1574 : TextWindow* GetTextWindow() { return mpTextWindow; }
145 0 : ScrollBar* GetHScrollBar() { return mpHScrollBar; }
146 0 : ScrollBar* GetVScrollBar() { return mpVScrollBar; }
147 : };
148 :
149 52 : ImpVclMEdit::ImpVclMEdit( VclMultiLineEdit* pEdt, WinBits nWinStyle )
150 : :mpHScrollBar(NULL)
151 : ,mpVScrollBar(NULL)
152 52 : ,mpScrollBox(NULL)
153 : {
154 52 : pVclMultiLineEdit = pEdt;
155 52 : mnTextWidth = 0;
156 52 : mpTextWindow = VclPtr<TextWindow>::Create( pEdt );
157 52 : mpTextWindow->Show();
158 52 : InitFromStyle( nWinStyle );
159 52 : StartListening( *mpTextWindow->GetTextEngine() );
160 52 : }
161 :
162 150 : void ImpVclMEdit::ImpUpdateSrollBarVis( WinBits nWinStyle )
163 : {
164 150 : const bool bHaveVScroll = (nullptr != mpVScrollBar);
165 150 : const bool bHaveHScroll = (nullptr != mpHScrollBar);
166 150 : const bool bHaveScrollBox = (nullptr != mpScrollBox);
167 :
168 150 : bool bNeedVScroll = ( nWinStyle & WB_VSCROLL ) == WB_VSCROLL;
169 150 : const bool bNeedHScroll = ( nWinStyle & WB_HSCROLL ) == WB_HSCROLL;
170 :
171 150 : const bool bAutoVScroll = ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL;
172 150 : if ( !bNeedVScroll && bAutoVScroll )
173 : {
174 0 : TextEngine& rEngine( *mpTextWindow->GetTextEngine() );
175 0 : sal_uLong nOverallTextHeight(0);
176 0 : for ( sal_uLong i=0; i<rEngine.GetParagraphCount(); ++i )
177 0 : nOverallTextHeight += rEngine.GetTextHeight( i );
178 0 : if ( nOverallTextHeight > (sal_uLong)mpTextWindow->GetOutputSizePixel().Height() )
179 0 : bNeedVScroll = true;
180 : }
181 :
182 150 : const bool bNeedScrollBox = bNeedVScroll && bNeedHScroll;
183 :
184 150 : bool bScrollbarsChanged = false;
185 150 : if ( bHaveVScroll != bNeedVScroll )
186 : {
187 14 : mpVScrollBar.disposeAndClear();
188 14 : mpVScrollBar = bNeedVScroll ? VclPtr<ScrollBar>::Create( pVclMultiLineEdit, WB_VSCROLL|WB_DRAG ) : nullptr;
189 :
190 14 : if ( bNeedVScroll )
191 : {
192 14 : mpVScrollBar->Show();
193 14 : mpVScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
194 : }
195 :
196 14 : bScrollbarsChanged = true;
197 : }
198 :
199 150 : if ( bHaveHScroll != bNeedHScroll )
200 : {
201 9 : mpHScrollBar.disposeAndClear();
202 9 : mpHScrollBar = bNeedHScroll ? VclPtr<ScrollBar>::Create( pVclMultiLineEdit, WB_HSCROLL|WB_DRAG ) : nullptr;
203 :
204 9 : if ( bNeedHScroll )
205 : {
206 9 : mpHScrollBar->Show();
207 9 : mpHScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
208 : }
209 :
210 9 : bScrollbarsChanged = true;
211 : }
212 :
213 150 : if ( bHaveScrollBox != bNeedScrollBox )
214 : {
215 5 : mpScrollBox.disposeAndClear();
216 5 : mpScrollBox = bNeedScrollBox ? VclPtr<ScrollBarBox>::Create( pVclMultiLineEdit, WB_SIZEABLE ) : nullptr;
217 :
218 5 : if ( bNeedScrollBox )
219 5 : mpScrollBox->Show();
220 : }
221 :
222 150 : if ( bScrollbarsChanged )
223 : {
224 18 : ImpInitScrollBars();
225 18 : Resize();
226 : }
227 150 : }
228 :
229 150 : void ImpVclMEdit::InitFromStyle( WinBits nWinStyle )
230 : {
231 150 : ImpUpdateSrollBarVis( nWinStyle );
232 150 : SetAlign( nWinStyle );
233 :
234 150 : if ( nWinStyle & WB_NOHIDESELECTION )
235 44 : mpTextWindow->SetAutoFocusHide( false );
236 : else
237 106 : mpTextWindow->SetAutoFocusHide( true );
238 :
239 150 : if ( nWinStyle & WB_READONLY )
240 45 : mpTextWindow->GetTextView()->SetReadOnly( true );
241 : else
242 105 : mpTextWindow->GetTextView()->SetReadOnly( false );
243 :
244 150 : if ( nWinStyle & WB_IGNORETAB )
245 : {
246 68 : mpTextWindow->SetIgnoreTab( true );
247 : }
248 : else
249 : {
250 82 : mpTextWindow->SetIgnoreTab( false );
251 : // #103667# VclMultiLineEdit has the flag, but focusable window also needs this flag
252 82 : WinBits nStyle = mpTextWindow->GetStyle();
253 82 : nStyle |= WB_NODIALOGCONTROL;
254 82 : mpTextWindow->SetStyle( nStyle );
255 : }
256 150 : }
257 :
258 150 : ImpVclMEdit::~ImpVclMEdit()
259 : {
260 50 : EndListening( *mpTextWindow->GetTextEngine() );
261 50 : mpTextWindow.disposeAndClear();
262 50 : mpHScrollBar.disposeAndClear();
263 50 : mpVScrollBar.disposeAndClear();
264 50 : mpScrollBox.disposeAndClear();
265 50 : pVclMultiLineEdit.disposeAndClear();
266 100 : }
267 :
268 266 : void ImpVclMEdit::ImpSetScrollBarRanges()
269 : {
270 266 : if ( mpVScrollBar )
271 : {
272 100 : sal_uLong nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
273 100 : mpVScrollBar->SetRange( Range( 0, (long)nTextHeight-1 ) );
274 : }
275 266 : if ( mpHScrollBar )
276 : {
277 : // sal_uLong nTextWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
278 : // Es gibt kein Notify bei Breiten-Aenderung...
279 : // sal_uLong nW = Max( (sal_uLong)mpTextWindow->GetOutputSizePixel().Width()*5, (sal_uLong)nTextWidth );
280 : // mpHScrollBar->SetRange( Range( 0, (long)nW ) );
281 99 : mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
282 : }
283 266 : }
284 :
285 125 : void ImpVclMEdit::ImpInitScrollBars()
286 : {
287 : static const sal_Unicode sampleChar = { 'x' };
288 125 : if ( mpHScrollBar || mpVScrollBar )
289 : {
290 105 : ImpSetScrollBarRanges();
291 105 : Size aCharBox;
292 105 : aCharBox.Width() = mpTextWindow->GetTextWidth( OUString(sampleChar) );
293 105 : aCharBox.Height() = mpTextWindow->GetTextHeight();
294 105 : Size aOutSz = mpTextWindow->GetOutputSizePixel();
295 105 : if ( mpHScrollBar )
296 : {
297 70 : mpHScrollBar->SetVisibleSize( aOutSz.Width() );
298 70 : mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 );
299 70 : mpHScrollBar->SetLineSize( aCharBox.Width()*10 );
300 70 : ImpSetHScrollBarThumbPos();
301 : }
302 105 : if ( mpVScrollBar )
303 : {
304 70 : mpVScrollBar->SetVisibleSize( aOutSz.Height() );
305 70 : mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 );
306 70 : mpVScrollBar->SetLineSize( aCharBox.Height() );
307 70 : mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
308 : }
309 : }
310 125 : }
311 :
312 91 : void ImpVclMEdit::ImpSetHScrollBarThumbPos()
313 : {
314 91 : long nX = mpTextWindow->GetTextView()->GetStartDocPos().X();
315 91 : if ( !mpTextWindow->GetTextEngine()->IsRightToLeft() )
316 91 : mpHScrollBar->SetThumbPos( nX );
317 : else
318 0 : mpHScrollBar->SetThumbPos( mnTextWidth - mpHScrollBar->GetVisibleSize() - nX );
319 :
320 91 : }
321 :
322 0 : IMPL_LINK( ImpVclMEdit, ScrollHdl, ScrollBar*, pCurScrollBar )
323 : {
324 0 : long nDiffX = 0, nDiffY = 0;
325 :
326 0 : if ( pCurScrollBar == mpVScrollBar )
327 0 : nDiffY = mpTextWindow->GetTextView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
328 0 : else if ( pCurScrollBar == mpHScrollBar )
329 0 : nDiffX = mpTextWindow->GetTextView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
330 :
331 0 : mpTextWindow->GetTextView()->Scroll( nDiffX, nDiffY );
332 : // mpTextWindow->GetTextView()->ShowCursor( false, true );
333 :
334 0 : return 0;
335 : }
336 :
337 150 : void ImpVclMEdit::SetAlign( WinBits nWinStyle )
338 : {
339 150 : bool bRTL = AllSettings::GetLayoutRTL();
340 150 : mpTextWindow->GetTextEngine()->SetRightToLeft( bRTL );
341 :
342 150 : if ( nWinStyle & WB_CENTER )
343 62 : mpTextWindow->GetTextEngine()->SetTextAlign( TXTALIGN_CENTER );
344 88 : else if ( nWinStyle & WB_RIGHT )
345 0 : mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_RIGHT : TXTALIGN_LEFT );
346 88 : else if ( nWinStyle & WB_LEFT )
347 88 : mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_LEFT : TXTALIGN_RIGHT );
348 150 : }
349 :
350 16 : void ImpVclMEdit::SetModified( bool bMod )
351 : {
352 16 : mpTextWindow->GetTextEngine()->SetModified( bMod );
353 16 : }
354 :
355 0 : bool ImpVclMEdit::IsModified() const
356 : {
357 0 : return mpTextWindow->GetTextEngine()->IsModified();
358 : }
359 :
360 41 : void ImpVclMEdit::SetReadOnly( bool bRdOnly )
361 : {
362 41 : mpTextWindow->GetTextView()->SetReadOnly( bRdOnly );
363 : // TODO: Adjust color?
364 41 : }
365 :
366 11 : bool ImpVclMEdit::IsReadOnly() const
367 : {
368 11 : return mpTextWindow->GetTextView()->IsReadOnly();
369 : }
370 :
371 47 : void ImpVclMEdit::SetMaxTextLen(sal_Int32 nLen)
372 : {
373 47 : mpTextWindow->GetTextEngine()->SetMaxTextLen(nLen);
374 47 : }
375 :
376 17 : sal_Int32 ImpVclMEdit::GetMaxTextLen() const
377 : {
378 17 : return mpTextWindow->GetTextEngine()->GetMaxTextLen();
379 : }
380 :
381 0 : void ImpVclMEdit::InsertText( const OUString& rStr )
382 : {
383 0 : mpTextWindow->GetTextView()->InsertText( rStr );
384 0 : }
385 :
386 0 : OUString ImpVclMEdit::GetSelected() const
387 : {
388 0 : return mpTextWindow->GetTextView()->GetSelected();
389 : }
390 :
391 0 : OUString ImpVclMEdit::GetSelected( LineEnd aSeparator ) const
392 : {
393 0 : return mpTextWindow->GetTextView()->GetSelected( aSeparator );
394 : }
395 :
396 0 : void ImpVclMEdit::SetMaxTextWidth( sal_uLong nMaxWidth )
397 : {
398 0 : mpTextWindow->GetTextEngine()->SetMaxTextWidth( nMaxWidth );
399 0 : }
400 :
401 107 : void ImpVclMEdit::Resize()
402 : {
403 107 : size_t nIteration = 1;
404 21 : do
405 : {
406 128 : WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
407 128 : if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
408 0 : ImpUpdateSrollBarVis( nWinStyle );
409 :
410 128 : Size aSz = pVclMultiLineEdit->GetOutputSizePixel();
411 128 : Size aEditSize = aSz;
412 128 : long nSBWidth = pVclMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize();
413 128 : nSBWidth = pVclMultiLineEdit->CalcZoom( nSBWidth );
414 :
415 128 : if ( mpHScrollBar )
416 76 : aSz.Height() -= nSBWidth+1;
417 128 : if ( mpVScrollBar )
418 67 : aSz.Width() -= nSBWidth+1;
419 :
420 128 : if ( !mpHScrollBar )
421 52 : mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() );
422 : else
423 76 : mpHScrollBar->setPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth );
424 :
425 128 : Point aTextWindowPos( maTextWindowOffset );
426 128 : if ( mpVScrollBar )
427 : {
428 67 : if( AllSettings::GetLayoutRTL() )
429 : {
430 0 : mpVScrollBar->setPosSizePixel( 0, 0, nSBWidth, aSz.Height() );
431 0 : aTextWindowPos.X() += nSBWidth;
432 : }
433 : else
434 67 : mpVScrollBar->setPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() );
435 : }
436 :
437 128 : if ( mpScrollBox )
438 38 : mpScrollBox->setPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth );
439 :
440 128 : Size aTextWindowSize( aSz );
441 128 : aTextWindowSize.Width() -= maTextWindowOffset.X();
442 128 : aTextWindowSize.Height() -= maTextWindowOffset.Y();
443 128 : if ( aTextWindowSize.Width() < 0 )
444 21 : aTextWindowSize.Width() = 0;
445 128 : if ( aTextWindowSize.Height() < 0 )
446 9 : aTextWindowSize.Height() = 0;
447 :
448 128 : Size aOldTextWindowSize( mpTextWindow->GetSizePixel() );
449 128 : mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize );
450 128 : if ( aOldTextWindowSize == aTextWindowSize )
451 107 : break;
452 :
453 : // Changing the text window size might effectively have changed the need for
454 : // scrollbars, so do another iteration.
455 21 : ++nIteration;
456 : OSL_ENSURE( nIteration < 3, "ImpVclMEdit::Resize: isn't this expected to terminate with the second iteration?" );
457 :
458 : } while ( nIteration <= 3 ); // artificial break after four iterations
459 :
460 107 : ImpInitScrollBars();
461 107 : }
462 :
463 0 : void ImpVclMEdit::GetFocus()
464 : {
465 0 : mpTextWindow->GrabFocus();
466 0 : }
467 :
468 0 : void ImpVclMEdit::Cut()
469 : {
470 0 : if ( !mpTextWindow->GetTextView()->IsReadOnly() )
471 0 : mpTextWindow->GetTextView()->Cut();
472 0 : }
473 :
474 0 : void ImpVclMEdit::Copy()
475 : {
476 0 : mpTextWindow->GetTextView()->Copy();
477 0 : }
478 :
479 0 : void ImpVclMEdit::Paste()
480 : {
481 0 : if ( !mpTextWindow->GetTextView()->IsReadOnly() )
482 0 : mpTextWindow->GetTextView()->Paste();
483 0 : }
484 :
485 129 : void ImpVclMEdit::SetText( const OUString& rStr )
486 : {
487 129 : bool bWasModified = mpTextWindow->GetTextEngine()->IsModified();
488 129 : mpTextWindow->GetTextEngine()->SetText( rStr );
489 129 : if ( !bWasModified )
490 124 : mpTextWindow->GetTextEngine()->SetModified( false );
491 :
492 129 : mpTextWindow->GetTextView()->SetSelection( TextSelection() );
493 :
494 129 : WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
495 129 : if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
496 0 : ImpUpdateSrollBarVis( nWinStyle );
497 129 : }
498 :
499 0 : OUString ImpVclMEdit::GetText() const
500 : {
501 0 : return mpTextWindow->GetTextEngine()->GetText();
502 : }
503 :
504 0 : OUString ImpVclMEdit::GetText( LineEnd aSeparator ) const
505 : {
506 0 : return mpTextWindow->GetTextEngine()->GetText( aSeparator );
507 : }
508 :
509 0 : OUString ImpVclMEdit::GetTextLines( LineEnd aSeparator ) const
510 : {
511 0 : return mpTextWindow->GetTextEngine()->GetTextLines( aSeparator );
512 : }
513 :
514 1209 : void ImpVclMEdit::Notify( SfxBroadcaster&, const SfxHint& rHint )
515 : {
516 1209 : const TextHint* pTextHint = dynamic_cast<const TextHint*>(&rHint);
517 1209 : if ( pTextHint )
518 : {
519 1209 : if( pTextHint->GetId() == TEXT_HINT_VIEWSCROLLED )
520 : {
521 0 : if ( mpHScrollBar )
522 0 : ImpSetHScrollBarThumbPos();
523 0 : if ( mpVScrollBar )
524 0 : mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
525 : }
526 1209 : else if( pTextHint->GetId() == TEXT_HINT_TEXTHEIGHTCHANGED )
527 : {
528 161 : if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() )
529 : {
530 0 : long nOutHeight = mpTextWindow->GetOutputSizePixel().Height();
531 0 : long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
532 0 : if ( nTextHeight < nOutHeight )
533 0 : mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() );
534 : }
535 :
536 161 : ImpSetScrollBarRanges();
537 : }
538 1048 : else if( pTextHint->GetId() == TEXT_HINT_TEXTFORMATTED )
539 : {
540 372 : if ( mpHScrollBar )
541 : {
542 77 : sal_Int32 nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
543 77 : if ( nWidth != mnTextWidth )
544 : {
545 21 : mnTextWidth = nWidth;
546 21 : mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
547 21 : ImpSetHScrollBarThumbPos();
548 : }
549 : }
550 : }
551 676 : else if( pTextHint->GetId() == TEXT_HINT_MODIFIED )
552 : {
553 0 : ImpUpdateSrollBarVis(pVclMultiLineEdit->GetStyle());
554 0 : pVclMultiLineEdit->Modify();
555 : }
556 676 : else if( pTextHint->GetId() == TEXT_HINT_VIEWSELECTIONCHANGED )
557 : {
558 4 : pVclMultiLineEdit->SelectionChanged();
559 : }
560 672 : else if( pTextHint->GetId() == TEXT_HINT_VIEWCARETCHANGED )
561 : {
562 0 : pVclMultiLineEdit->CaretChanged();
563 : }
564 : }
565 1209 : }
566 :
567 17 : void ImpVclMEdit::SetSelection( const Selection& rSelection )
568 : {
569 17 : OUString aText = mpTextWindow->GetTextEngine()->GetText();
570 :
571 17 : Selection aNewSelection( rSelection );
572 17 : if ( aNewSelection.Min() < 0 )
573 0 : aNewSelection.Min() = 0;
574 17 : else if ( aNewSelection.Min() > aText.getLength() )
575 17 : aNewSelection.Min() = aText.getLength();
576 17 : if ( aNewSelection.Max() < 0 )
577 17 : aNewSelection.Max() = 0;
578 0 : else if ( aNewSelection.Max() > aText.getLength() )
579 0 : aNewSelection.Max() = aText.getLength();
580 :
581 17 : long nEnd = std::max( aNewSelection.Min(), aNewSelection.Max() );
582 17 : TextSelection aTextSel;
583 17 : sal_uLong nPara = 0;
584 17 : sal_uInt16 nChar = 0;
585 17 : sal_uInt16 x = 0;
586 133 : while ( x <= nEnd )
587 : {
588 99 : if ( x == aNewSelection.Min() )
589 17 : aTextSel.GetStart() = TextPaM( nPara, nChar );
590 99 : if ( x == aNewSelection.Max() )
591 17 : aTextSel.GetEnd() = TextPaM( nPara, nChar );
592 :
593 99 : if ( ( x < aText.getLength() ) && ( aText[ x ] == '\n' ) )
594 : {
595 0 : nPara++;
596 0 : nChar = 0;
597 : }
598 : else
599 99 : nChar++;
600 99 : x++;
601 : }
602 17 : mpTextWindow->GetTextView()->SetSelection( aTextSel );
603 17 : }
604 :
605 0 : const Selection& ImpVclMEdit::GetSelection() const
606 : {
607 0 : maSelection = Selection();
608 0 : TextSelection aTextSel( mpTextWindow->GetTextView()->GetSelection() );
609 0 : aTextSel.Justify();
610 : // flatten selection => every line-break a character
611 :
612 0 : ExtTextEngine* pExtTextEngine = mpTextWindow->GetTextEngine();
613 : // paragraphs before
614 : sal_uLong n;
615 0 : for ( n = 0; n < aTextSel.GetStart().GetPara(); n++ )
616 : {
617 0 : maSelection.Min() += pExtTextEngine->GetTextLen( n );
618 0 : maSelection.Min()++;
619 : }
620 :
621 : // first paragraph with selection
622 0 : maSelection.Max() = maSelection.Min();
623 0 : maSelection.Min() += aTextSel.GetStart().GetIndex();
624 :
625 0 : for ( n = aTextSel.GetStart().GetPara(); n < aTextSel.GetEnd().GetPara(); n++ )
626 : {
627 0 : maSelection.Max() += pExtTextEngine->GetTextLen( n );
628 0 : maSelection.Max()++;
629 : }
630 :
631 0 : maSelection.Max() += aTextSel.GetEnd().GetIndex();
632 :
633 0 : return maSelection;
634 : }
635 :
636 0 : Size ImpVclMEdit::CalcMinimumSize() const
637 : {
638 0 : Size aSz( mpTextWindow->GetTextEngine()->CalcTextWidth(),
639 0 : mpTextWindow->GetTextEngine()->GetTextHeight() );
640 :
641 0 : if ( mpHScrollBar )
642 0 : aSz.Height() += mpHScrollBar->GetSizePixel().Height();
643 0 : if ( mpVScrollBar )
644 0 : aSz.Width() += mpVScrollBar->GetSizePixel().Width();
645 :
646 0 : return aSz;
647 : }
648 :
649 0 : Size ImpVclMEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
650 : {
651 : static const sal_Unicode sampleChar = 'X';
652 :
653 0 : Size aSz;
654 0 : Size aCharSz;
655 0 : aCharSz.Width() = mpTextWindow->GetTextWidth( OUString(sampleChar) );
656 0 : aCharSz.Height() = mpTextWindow->GetTextHeight();
657 :
658 0 : if ( nLines )
659 0 : aSz.Height() = nLines*aCharSz.Height();
660 : else
661 0 : aSz.Height() = mpTextWindow->GetTextEngine()->GetTextHeight();
662 :
663 0 : if ( nColumns )
664 0 : aSz.Width() = nColumns*aCharSz.Width();
665 : else
666 0 : aSz.Width() = mpTextWindow->GetTextEngine()->CalcTextWidth();
667 :
668 0 : if ( mpHScrollBar )
669 0 : aSz.Height() += mpHScrollBar->GetSizePixel().Height();
670 0 : if ( mpVScrollBar )
671 0 : aSz.Width() += mpVScrollBar->GetSizePixel().Width();
672 :
673 0 : return aSz;
674 : }
675 :
676 0 : void ImpVclMEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
677 : {
678 : static const sal_Unicode sampleChar = { 'x' };
679 0 : Size aOutSz = mpTextWindow->GetOutputSizePixel();
680 0 : Size aCharSz( mpTextWindow->GetTextWidth( OUString(sampleChar) ), mpTextWindow->GetTextHeight() );
681 0 : rnCols = (sal_uInt16) (aOutSz.Width()/aCharSz.Width());
682 0 : rnLines = (sal_uInt16) (aOutSz.Height()/aCharSz.Height());
683 0 : }
684 :
685 11 : void ImpVclMEdit::Enable( bool bEnable )
686 : {
687 11 : mpTextWindow->Enable( bEnable );
688 11 : if ( mpHScrollBar )
689 11 : mpHScrollBar->Enable( bEnable );
690 11 : if ( mpVScrollBar )
691 7 : mpVScrollBar->Enable( bEnable );
692 11 : }
693 :
694 0 : bool ImpVclMEdit::HandleCommand( const CommandEvent& rCEvt )
695 : {
696 0 : bool bDone = false;
697 0 : if ( ( rCEvt.GetCommand() == CommandEventId::Wheel ) ||
698 0 : ( rCEvt.GetCommand() == CommandEventId::StartAutoScroll ) ||
699 0 : ( rCEvt.GetCommand() == CommandEventId::AutoScroll ) )
700 : {
701 0 : mpTextWindow->HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
702 0 : bDone = true;
703 : }
704 0 : return bDone;
705 : }
706 :
707 52 : TextWindow::TextWindow( vcl::Window* pParent ) : Window( pParent )
708 : {
709 52 : mbInMBDown = false;
710 52 : mbFocusSelectionHide = false;
711 52 : mbIgnoreTab = false;
712 52 : mbActivePopup = false;
713 52 : mbSelectOnTab = true;
714 52 : mbTextSelectable = true;
715 :
716 52 : SetPointer( Pointer( PointerStyle::Text ) );
717 :
718 52 : mpExtTextEngine = new ExtTextEngine;
719 52 : mpExtTextEngine->SetMaxTextLen(EDIT_NOLIMIT);
720 52 : if( pParent->GetStyle() & WB_BORDER )
721 11 : mpExtTextEngine->SetLeftMargin( 2 );
722 52 : mpExtTextEngine->SetLocale( GetSettings().GetLanguageTag().getLocale() );
723 52 : mpExtTextView = new ExtTextView( mpExtTextEngine, this );
724 52 : mpExtTextEngine->InsertView( mpExtTextView );
725 52 : mpExtTextEngine->EnableUndo( true );
726 52 : mpExtTextView->ShowCursor();
727 :
728 52 : Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor();
729 52 : SetBackground( aBackgroundColor );
730 52 : pParent->SetBackground( aBackgroundColor );
731 52 : }
732 :
733 150 : TextWindow::~TextWindow()
734 : {
735 50 : disposeOnce();
736 100 : }
737 :
738 50 : void TextWindow::dispose()
739 : {
740 50 : delete mpExtTextView;
741 50 : mpExtTextView = NULL;
742 50 : delete mpExtTextEngine;
743 50 : mpExtTextEngine = NULL;
744 50 : Window::dispose();
745 50 : }
746 :
747 0 : void TextWindow::MouseMove( const MouseEvent& rMEvt )
748 : {
749 0 : mpExtTextView->MouseMove( rMEvt );
750 0 : Window::MouseMove( rMEvt );
751 0 : }
752 :
753 0 : void TextWindow::MouseButtonDown( const MouseEvent& rMEvt )
754 : {
755 0 : if ( !mbTextSelectable )
756 0 : return;
757 :
758 0 : mbInMBDown = true; // so that GetFocus does not select everything
759 0 : mpExtTextView->MouseButtonDown( rMEvt );
760 0 : GrabFocus();
761 0 : mbInMBDown = false;
762 : }
763 :
764 0 : void TextWindow::MouseButtonUp( const MouseEvent& rMEvt )
765 : {
766 0 : mpExtTextView->MouseButtonUp( rMEvt );
767 0 : }
768 :
769 0 : void TextWindow::KeyInput( const KeyEvent& rKEvent )
770 : {
771 0 : bool bDone = false;
772 0 : sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
773 0 : if ( nCode == com::sun::star::awt::Key::SELECT_ALL ||
774 0 : ( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() )
775 : )
776 : {
777 0 : mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) );
778 0 : bDone = true;
779 : }
780 0 : else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() )
781 : {
782 0 : if ( Edit::GetGetSpecialCharsFunction() )
783 : {
784 : // to maintain the selection
785 0 : mbActivePopup = true;
786 0 : OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() );
787 0 : if (!aChars.isEmpty())
788 : {
789 0 : mpExtTextView->InsertText( aChars );
790 0 : mpExtTextView->GetTextEngine()->SetModified( true );
791 : }
792 0 : mbActivePopup = false;
793 0 : bDone = true;
794 : }
795 : }
796 0 : else if ( nCode == KEY_TAB )
797 : {
798 0 : if ( !mbIgnoreTab || rKEvent.GetKeyCode().IsMod1() )
799 0 : bDone = mpExtTextView->KeyInput( rKEvent );
800 : }
801 : else
802 : {
803 0 : bDone = mpExtTextView->KeyInput( rKEvent );
804 : }
805 :
806 0 : if ( !bDone )
807 0 : Window::KeyInput( rKEvent );
808 0 : }
809 :
810 100 : void TextWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
811 : {
812 100 : mpExtTextView->Paint(rRenderContext, rRect);
813 100 : }
814 :
815 73 : void TextWindow::Resize()
816 : {
817 73 : }
818 :
819 0 : void TextWindow::Command( const CommandEvent& rCEvt )
820 : {
821 0 : if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
822 : {
823 0 : PopupMenu* pPopup = Edit::CreatePopupMenu();
824 0 : if ( !mpExtTextView->HasSelection() )
825 : {
826 0 : pPopup->EnableItem( SV_MENU_EDIT_CUT, false );
827 0 : pPopup->EnableItem( SV_MENU_EDIT_COPY, false );
828 0 : pPopup->EnableItem( SV_MENU_EDIT_DELETE, false );
829 : }
830 0 : if ( mpExtTextView->IsReadOnly() )
831 : {
832 0 : pPopup->EnableItem( SV_MENU_EDIT_CUT, false );
833 0 : pPopup->EnableItem( SV_MENU_EDIT_PASTE, false );
834 0 : pPopup->EnableItem( SV_MENU_EDIT_DELETE, false );
835 0 : pPopup->EnableItem( SV_MENU_EDIT_INSERTSYMBOL, false );
836 : }
837 0 : if ( !mpExtTextView->GetTextEngine()->HasUndoManager() || !mpExtTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() )
838 : {
839 0 : pPopup->EnableItem( SV_MENU_EDIT_UNDO, false );
840 : }
841 : // if ( ( maSelection.Min() == 0 ) && ( maSelection.Max() == maText.Len() ) )
842 : // {
843 : // pPopup->EnableItem( SV_MENU_EDIT_SELECTALL, false );
844 : // }
845 0 : if ( !Edit::GetGetSpecialCharsFunction() )
846 : {
847 0 : sal_uInt16 nPos = pPopup->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL );
848 0 : pPopup->RemoveItem( nPos );
849 0 : pPopup->RemoveItem( nPos-1 );
850 : }
851 :
852 0 : mbActivePopup = true;
853 0 : Point aPos = rCEvt.GetMousePosPixel();
854 0 : if ( !rCEvt.IsMouseEvent() )
855 : {
856 : // Sometime do show Menu centered in the selection !!!
857 0 : Size aSize = GetOutputSizePixel();
858 0 : aPos = Point( aSize.Width()/2, aSize.Height()/2 );
859 : }
860 : // pPopup->RemoveDisabledEntries();
861 0 : sal_uInt16 n = pPopup->Execute( this, aPos );
862 0 : Edit::DeletePopupMenu( pPopup );
863 0 : switch ( n )
864 : {
865 0 : case SV_MENU_EDIT_UNDO: mpExtTextView->Undo();
866 0 : mpExtTextEngine->SetModified( true );
867 0 : mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
868 0 : break;
869 0 : case SV_MENU_EDIT_CUT: mpExtTextView->Cut();
870 0 : mpExtTextEngine->SetModified( true );
871 0 : mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
872 0 : break;
873 0 : case SV_MENU_EDIT_COPY: mpExtTextView->Copy();
874 0 : break;
875 0 : case SV_MENU_EDIT_PASTE: mpExtTextView->Paste();
876 0 : mpExtTextEngine->SetModified( true );
877 0 : mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
878 0 : break;
879 0 : case SV_MENU_EDIT_DELETE: mpExtTextView->DeleteSelected();
880 0 : mpExtTextEngine->SetModified( true );
881 0 : mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
882 0 : break;
883 0 : case SV_MENU_EDIT_SELECTALL: mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFFFFFF, 0xFFFF ) ) );
884 0 : break;
885 : case SV_MENU_EDIT_INSERTSYMBOL:
886 : {
887 0 : OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() );
888 0 : if (!aChars.isEmpty())
889 : {
890 0 : mpExtTextView->InsertText( aChars );
891 0 : mpExtTextEngine->SetModified( true );
892 0 : mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
893 0 : }
894 : }
895 0 : break;
896 : }
897 0 : mbActivePopup = false;
898 : }
899 : else
900 : {
901 0 : mpExtTextView->Command( rCEvt );
902 : }
903 0 : Window::Command( rCEvt );
904 0 : }
905 :
906 0 : void TextWindow::GetFocus()
907 : {
908 0 : Window::GetFocus();
909 0 : if ( !mbActivePopup )
910 : {
911 0 : bool bGotoCursor = !mpExtTextView->IsReadOnly();
912 0 : if ( mbFocusSelectionHide && IsReallyVisible() && !mpExtTextView->IsReadOnly()
913 0 : && ( mbSelectOnTab &&
914 0 : (!mbInMBDown || ( GetSettings().GetStyleSettings().GetSelectionOptions() & SelectionOptions::Focus ) )) )
915 : {
916 : // select everything, but do not scroll
917 0 : bool bAutoScroll = mpExtTextView->IsAutoScroll();
918 0 : mpExtTextView->SetAutoScroll( false );
919 0 : mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) );
920 0 : mpExtTextView->SetAutoScroll( bAutoScroll );
921 0 : bGotoCursor = false;
922 : }
923 0 : mpExtTextView->SetPaintSelection( true );
924 0 : mpExtTextView->ShowCursor( bGotoCursor );
925 : }
926 0 : }
927 :
928 0 : void TextWindow::LoseFocus()
929 : {
930 0 : Window::LoseFocus();
931 :
932 0 : if ( mbFocusSelectionHide && !mbActivePopup && mpExtTextView )
933 0 : mpExtTextView->SetPaintSelection( false );
934 0 : }
935 :
936 52 : VclMultiLineEdit::VclMultiLineEdit( vcl::Window* pParent, WinBits nWinStyle )
937 52 : : Edit( pParent, nWinStyle )
938 : {
939 52 : SetType( WINDOW_MULTILINEEDIT );
940 52 : pImpVclMEdit = new ImpVclMEdit( this, nWinStyle );
941 52 : ImplInitSettings( true, true, true );
942 52 : pUpdateDataTimer = 0;
943 :
944 52 : SetCompoundControl( true );
945 52 : SetStyle( ImplInitStyle( nWinStyle ) );
946 52 : }
947 :
948 100 : VclMultiLineEdit::~VclMultiLineEdit()
949 : {
950 50 : disposeOnce();
951 50 : }
952 :
953 50 : void VclMultiLineEdit::dispose()
954 : {
955 : {
956 50 : std::unique_ptr< ImpVclMEdit > xDelete(pImpVclMEdit);
957 50 : pImpVclMEdit = NULL;
958 : }
959 50 : delete pUpdateDataTimer;
960 50 : pUpdateDataTimer = NULL;
961 :
962 50 : Edit::dispose();
963 50 : }
964 :
965 150 : WinBits VclMultiLineEdit::ImplInitStyle( WinBits nStyle )
966 : {
967 150 : if ( !(nStyle & WB_NOTABSTOP) )
968 150 : nStyle |= WB_TABSTOP;
969 :
970 150 : if ( !(nStyle & WB_NOGROUP) )
971 150 : nStyle |= WB_GROUP;
972 :
973 150 : if ( !(nStyle & WB_IGNORETAB ))
974 82 : nStyle |= WB_NODIALOGCONTROL;
975 :
976 150 : return nStyle;
977 : }
978 :
979 48 : void VclMultiLineEdit::ApplySettings(vcl::RenderContext& rRenderContext)
980 : {
981 48 : const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
982 :
983 : // The Font has to be adjusted, as the TextEngine does not take care of
984 : // TextColor/Background
985 :
986 48 : Color aTextColor = rStyleSettings.GetFieldTextColor();
987 48 : if (IsControlForeground())
988 48 : aTextColor = GetControlForeground();
989 :
990 48 : if (!IsEnabled())
991 0 : aTextColor = rStyleSettings.GetDisableColor();
992 :
993 48 : vcl::Font aFont = rStyleSettings.GetFieldFont();
994 48 : aFont.SetTransparent(IsPaintTransparent());
995 48 : ApplyControlFont(rRenderContext, aFont);
996 :
997 96 : vcl::Font theFont = rRenderContext.GetFont();
998 48 : theFont.SetColor(aTextColor);
999 48 : if (IsPaintTransparent())
1000 48 : theFont.SetFillColor(Color(COL_TRANSPARENT));
1001 : else
1002 0 : theFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
1003 :
1004 48 : pImpVclMEdit->GetTextWindow()->SetFont(theFont);
1005 : // FIXME: next call causes infinite invalidation loop, rethink how to properly fix this situation
1006 : // pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(theFont);
1007 48 : pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
1008 :
1009 48 : if (IsPaintTransparent())
1010 : {
1011 48 : pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
1012 48 : pImpVclMEdit->GetTextWindow()->SetBackground();
1013 48 : pImpVclMEdit->GetTextWindow()->SetControlBackground();
1014 48 : rRenderContext.SetBackground();
1015 48 : SetControlBackground();
1016 : }
1017 : else
1018 : {
1019 0 : if (IsControlBackground())
1020 0 : pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
1021 : else
1022 0 : pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
1023 : // also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
1024 0 : rRenderContext.SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
1025 48 : }
1026 48 : }
1027 :
1028 230 : void VclMultiLineEdit::ImplInitSettings(bool /*bFont*/, bool /*bForeground*/, bool bBackground)
1029 : {
1030 230 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1031 :
1032 : // The Font has to be adjusted, as the TextEngine does not take care of
1033 : // TextColor/Background
1034 :
1035 230 : Color aTextColor = rStyleSettings.GetFieldTextColor();
1036 230 : if (IsControlForeground())
1037 93 : aTextColor = GetControlForeground();
1038 230 : if (!IsEnabled())
1039 43 : aTextColor = rStyleSettings.GetDisableColor();
1040 :
1041 230 : vcl::Font aFont = rStyleSettings.GetFieldFont();
1042 230 : aFont.SetTransparent(IsPaintTransparent());
1043 230 : ApplyControlFont(*this, aFont);
1044 :
1045 460 : vcl::Font TheFont = GetFont();
1046 230 : TheFont.SetColor(aTextColor);
1047 230 : if (IsPaintTransparent())
1048 99 : TheFont.SetFillColor(Color(COL_TRANSPARENT));
1049 : else
1050 131 : TheFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
1051 230 : pImpVclMEdit->GetTextWindow()->SetFont(TheFont);
1052 230 : pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(TheFont);
1053 230 : pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
1054 :
1055 230 : if (bBackground)
1056 : {
1057 183 : if (IsPaintTransparent())
1058 : {
1059 96 : pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
1060 96 : pImpVclMEdit->GetTextWindow()->SetBackground();
1061 96 : pImpVclMEdit->GetTextWindow()->SetControlBackground();
1062 96 : SetBackground();
1063 96 : SetControlBackground();
1064 : }
1065 : else
1066 : {
1067 87 : if (IsControlBackground())
1068 0 : pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
1069 : else
1070 87 : pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
1071 : // also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
1072 87 : SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
1073 : }
1074 230 : }
1075 230 : }
1076 :
1077 16 : void VclMultiLineEdit::Modify()
1078 : {
1079 16 : aModifyHdlLink.Call( this );
1080 :
1081 16 : CallEventListeners( VCLEVENT_EDIT_MODIFY );
1082 :
1083 16 : if ( pUpdateDataTimer )
1084 0 : pUpdateDataTimer->Start();
1085 16 : }
1086 :
1087 4 : void VclMultiLineEdit::SelectionChanged()
1088 : {
1089 4 : CallEventListeners(VCLEVENT_EDIT_SELECTIONCHANGED);
1090 4 : }
1091 :
1092 0 : void VclMultiLineEdit::CaretChanged()
1093 : {
1094 0 : CallEventListeners(VCLEVENT_EDIT_CARETCHANGED);
1095 0 : }
1096 :
1097 0 : IMPL_LINK_NOARG_TYPED(VclMultiLineEdit, ImpUpdateDataHdl, Timer *, void)
1098 : {
1099 0 : UpdateData();
1100 0 : }
1101 :
1102 0 : void VclMultiLineEdit::UpdateData()
1103 : {
1104 0 : aUpdateDataHdlLink.Call( this );
1105 0 : }
1106 :
1107 16 : void VclMultiLineEdit::SetModifyFlag()
1108 : {
1109 16 : pImpVclMEdit->SetModified( true );
1110 16 : }
1111 :
1112 0 : void VclMultiLineEdit::ClearModifyFlag()
1113 : {
1114 0 : pImpVclMEdit->SetModified( false );
1115 0 : }
1116 :
1117 0 : bool VclMultiLineEdit::IsModified() const
1118 : {
1119 0 : return pImpVclMEdit->IsModified();
1120 : }
1121 :
1122 0 : void VclMultiLineEdit::EnableUpdateData( sal_uLong nTimeout )
1123 : {
1124 0 : if ( !nTimeout )
1125 0 : DisableUpdateData();
1126 : else
1127 : {
1128 0 : if ( !pUpdateDataTimer )
1129 : {
1130 0 : pUpdateDataTimer = new Timer;
1131 0 : pUpdateDataTimer->SetTimeoutHdl( LINK( this, VclMultiLineEdit, ImpUpdateDataHdl ) );
1132 : }
1133 0 : pUpdateDataTimer->SetTimeout( nTimeout );
1134 : }
1135 0 : }
1136 :
1137 30 : void VclMultiLineEdit::SetReadOnly( bool bReadOnly )
1138 : {
1139 30 : pImpVclMEdit->SetReadOnly( bReadOnly );
1140 30 : Edit::SetReadOnly( bReadOnly );
1141 :
1142 : // #94921# ReadOnly can be overwritten in InitFromStyle() when WB not set.
1143 30 : WinBits nStyle = GetStyle();
1144 30 : if ( bReadOnly )
1145 11 : nStyle |= WB_READONLY;
1146 : else
1147 19 : nStyle &= ~WB_READONLY;
1148 30 : SetStyle( nStyle );
1149 30 : }
1150 :
1151 11 : bool VclMultiLineEdit::IsReadOnly() const
1152 : {
1153 11 : return pImpVclMEdit->IsReadOnly();
1154 : }
1155 :
1156 47 : void VclMultiLineEdit::SetMaxTextLen(sal_Int32 nMaxLen)
1157 : {
1158 47 : pImpVclMEdit->SetMaxTextLen(nMaxLen);
1159 47 : }
1160 :
1161 0 : void VclMultiLineEdit::SetMaxTextWidth( sal_uLong nMaxWidth )
1162 : {
1163 0 : pImpVclMEdit->SetMaxTextWidth(nMaxWidth );
1164 0 : }
1165 :
1166 17 : sal_Int32 VclMultiLineEdit::GetMaxTextLen() const
1167 : {
1168 17 : return pImpVclMEdit->GetMaxTextLen();
1169 : }
1170 :
1171 0 : void VclMultiLineEdit::ReplaceSelected( const OUString& rStr )
1172 : {
1173 0 : pImpVclMEdit->InsertText( rStr );
1174 0 : }
1175 :
1176 0 : void VclMultiLineEdit::DeleteSelected()
1177 : {
1178 0 : pImpVclMEdit->InsertText( OUString() );
1179 0 : }
1180 :
1181 0 : OUString VclMultiLineEdit::GetSelected() const
1182 : {
1183 0 : return pImpVclMEdit->GetSelected();
1184 : }
1185 :
1186 0 : OUString VclMultiLineEdit::GetSelected( LineEnd aSeparator ) const
1187 : {
1188 0 : return pImpVclMEdit->GetSelected( aSeparator );
1189 : }
1190 :
1191 0 : void VclMultiLineEdit::Cut()
1192 : {
1193 0 : pImpVclMEdit->Cut();
1194 0 : }
1195 :
1196 0 : void VclMultiLineEdit::Copy()
1197 : {
1198 0 : pImpVclMEdit->Copy();
1199 0 : }
1200 :
1201 0 : void VclMultiLineEdit::Paste()
1202 : {
1203 0 : pImpVclMEdit->Paste();
1204 0 : }
1205 :
1206 129 : void VclMultiLineEdit::SetText( const OUString& rStr )
1207 : {
1208 129 : pImpVclMEdit->SetText( rStr );
1209 129 : }
1210 :
1211 0 : OUString VclMultiLineEdit::GetText() const
1212 : {
1213 0 : return pImpVclMEdit ? pImpVclMEdit->GetText() : OUString("");
1214 : }
1215 :
1216 0 : OUString VclMultiLineEdit::GetText( LineEnd aSeparator ) const
1217 : {
1218 0 : return pImpVclMEdit ? pImpVclMEdit->GetText( aSeparator ) : OUString("");
1219 : }
1220 :
1221 0 : OUString VclMultiLineEdit::GetTextLines( LineEnd aSeparator ) const
1222 : {
1223 0 : return pImpVclMEdit ? pImpVclMEdit->GetTextLines( aSeparator ) : OUString("");
1224 : }
1225 :
1226 89 : void VclMultiLineEdit::Resize()
1227 : {
1228 89 : pImpVclMEdit->Resize();
1229 89 : }
1230 :
1231 0 : void VclMultiLineEdit::GetFocus()
1232 : {
1233 0 : if ( !pImpVclMEdit ) // might be called from within the dtor, when pImpVclMEdit == NULL is a valid state
1234 0 : return;
1235 :
1236 0 : pImpVclMEdit->GetFocus();
1237 : }
1238 :
1239 17 : void VclMultiLineEdit::SetSelection( const Selection& rSelection )
1240 : {
1241 17 : pImpVclMEdit->SetSelection( rSelection );
1242 17 : }
1243 :
1244 0 : const Selection& VclMultiLineEdit::GetSelection() const
1245 : {
1246 0 : return pImpVclMEdit->GetSelection();
1247 : }
1248 :
1249 0 : Size VclMultiLineEdit::CalcMinimumSize() const
1250 : {
1251 0 : Size aSz = pImpVclMEdit->CalcMinimumSize();
1252 :
1253 : sal_Int32 nLeft, nTop, nRight, nBottom;
1254 0 : static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1255 0 : aSz.Width() += nLeft+nRight;
1256 0 : aSz.Height() += nTop+nBottom;
1257 :
1258 0 : return aSz;
1259 : }
1260 :
1261 0 : Size VclMultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const
1262 : {
1263 0 : Size aSz = rPrefSize;
1264 : sal_Int32 nLeft, nTop, nRight, nBottom;
1265 0 : static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1266 :
1267 : // center vertically for whole lines
1268 :
1269 0 : long nHeight = aSz.Height() - nTop - nBottom;
1270 0 : long nLineHeight = pImpVclMEdit->CalcBlockSize( 1, 1 ).Height();
1271 0 : long nLines = nHeight / nLineHeight;
1272 0 : if ( nLines < 1 )
1273 0 : nLines = 1;
1274 :
1275 0 : aSz.Height() = nLines * nLineHeight;
1276 0 : aSz.Height() += nTop+nBottom;
1277 :
1278 0 : return aSz;
1279 : }
1280 :
1281 0 : Size VclMultiLineEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1282 : {
1283 0 : Size aSz = pImpVclMEdit->CalcBlockSize( nColumns, nLines );
1284 :
1285 : sal_Int32 nLeft, nTop, nRight, nBottom;
1286 0 : static_cast<vcl::Window*>(const_cast<VclMultiLineEdit *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1287 0 : aSz.Width() += nLeft+nRight;
1288 0 : aSz.Height() += nTop+nBottom;
1289 0 : return aSz;
1290 : }
1291 :
1292 0 : void VclMultiLineEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1293 : {
1294 0 : pImpVclMEdit->GetMaxVisColumnsAndLines( rnCols, rnLines );
1295 0 : }
1296 :
1297 566 : void VclMultiLineEdit::StateChanged( StateChangedType nType )
1298 : {
1299 566 : if( nType == StateChangedType::Enable )
1300 : {
1301 11 : pImpVclMEdit->Enable( IsEnabled() );
1302 11 : ImplInitSettings( true, false, false );
1303 : }
1304 555 : else if( nType == StateChangedType::ReadOnly )
1305 : {
1306 11 : pImpVclMEdit->SetReadOnly( IsReadOnly() );
1307 : }
1308 544 : else if ( nType == StateChangedType::Zoom )
1309 : {
1310 0 : pImpVclMEdit->GetTextWindow()->SetZoom( GetZoom() );
1311 0 : ImplInitSettings( true, false, false );
1312 0 : Resize();
1313 : }
1314 544 : else if ( nType == StateChangedType::ControlFont )
1315 : {
1316 33 : ImplInitSettings( true, false, false );
1317 33 : Resize();
1318 33 : Invalidate();
1319 : }
1320 511 : else if ( nType == StateChangedType::ControlForeground )
1321 : {
1322 3 : ImplInitSettings( false, true, false );
1323 3 : Invalidate();
1324 : }
1325 508 : else if ( nType == StateChangedType::ControlBackground )
1326 : {
1327 96 : ImplInitSettings( false, false, true );
1328 96 : Invalidate();
1329 : }
1330 412 : else if ( nType == StateChangedType::Style )
1331 : {
1332 98 : pImpVclMEdit->InitFromStyle( GetStyle() );
1333 98 : SetStyle( ImplInitStyle( GetStyle() ) );
1334 : }
1335 314 : else if ( nType == StateChangedType::InitShow )
1336 : {
1337 48 : if( IsPaintTransparent() )
1338 : {
1339 48 : pImpVclMEdit->GetTextWindow()->SetPaintTransparent( true );
1340 48 : pImpVclMEdit->GetTextWindow()->SetBackground();
1341 48 : pImpVclMEdit->GetTextWindow()->SetControlBackground();
1342 48 : SetBackground();
1343 48 : SetControlBackground();
1344 : }
1345 : }
1346 :
1347 566 : Control::StateChanged( nType );
1348 566 : }
1349 :
1350 35 : void VclMultiLineEdit::DataChanged( const DataChangedEvent& rDCEvt )
1351 : {
1352 140 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1353 140 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1354 : {
1355 35 : ImplInitSettings( true, true, true );
1356 35 : Resize();
1357 35 : Invalidate();
1358 : }
1359 : else
1360 0 : Control::DataChanged( rDCEvt );
1361 35 : }
1362 :
1363 0 : void VclMultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, DrawFlags nFlags )
1364 : {
1365 0 : ImplInitSettings( true, true, true );
1366 :
1367 0 : Point aPos = pDev->LogicToPixel( rPos );
1368 0 : Size aSize = pDev->LogicToPixel( rSize );
1369 0 : vcl::Font aFont = pImpVclMEdit->GetTextWindow()->GetDrawPixelFont( pDev );
1370 0 : aFont.SetTransparent( true );
1371 0 : OutDevType eOutDevType = pDev->GetOutDevType();
1372 :
1373 0 : pDev->Push();
1374 0 : pDev->SetMapMode();
1375 0 : pDev->SetFont( aFont );
1376 0 : pDev->SetTextFillColor();
1377 :
1378 : // Border/Background
1379 0 : pDev->SetLineColor();
1380 0 : pDev->SetFillColor();
1381 0 : bool bBorder = !(nFlags & DrawFlags::NoBorder ) && (GetStyle() & WB_BORDER);
1382 0 : bool bBackground = !(nFlags & DrawFlags::NoBackground) && IsControlBackground();
1383 0 : if ( bBorder || bBackground )
1384 : {
1385 0 : Rectangle aRect( aPos, aSize );
1386 0 : if ( bBorder )
1387 : {
1388 0 : DecorationView aDecoView( pDev );
1389 0 : aRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleIn );
1390 : }
1391 0 : if ( bBackground )
1392 : {
1393 0 : pDev->SetFillColor( GetControlBackground() );
1394 0 : pDev->DrawRect( aRect );
1395 : }
1396 : }
1397 :
1398 : // contents
1399 0 : if ( ( nFlags & DrawFlags::Mono ) || ( eOutDevType == OUTDEV_PRINTER ) )
1400 0 : pDev->SetTextColor( Color( COL_BLACK ) );
1401 : else
1402 : {
1403 0 : if ( !(nFlags & DrawFlags::NoDisable ) && !IsEnabled() )
1404 : {
1405 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1406 0 : pDev->SetTextColor( rStyleSettings.GetDisableColor() );
1407 : }
1408 : else
1409 : {
1410 0 : pDev->SetTextColor( GetTextColor() );
1411 : }
1412 : }
1413 :
1414 0 : OUString aText = GetText();
1415 0 : Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() );
1416 0 : sal_uLong nLines = (sal_uLong) (aSize.Height() / aTextSz.Height());
1417 0 : if ( !nLines )
1418 0 : nLines = 1;
1419 0 : aTextSz.Height() = nLines*aTextSz.Height();
1420 0 : long nOnePixel = GetDrawPixel( pDev, 1 );
1421 0 : long nOffX = 3*nOnePixel;
1422 0 : long nOffY = 2*nOnePixel;
1423 :
1424 : // Clipping?
1425 0 : if ( ( nOffY < 0 ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) )
1426 : {
1427 0 : Rectangle aClip( aPos, aSize );
1428 0 : if ( aTextSz.Height() > aSize.Height() )
1429 0 : aClip.Bottom() += aTextSz.Height() - aSize.Height() + 1; // so that HP-printer does not 'optimize-away'
1430 0 : pDev->IntersectClipRegion( aClip );
1431 : }
1432 :
1433 0 : ExtTextEngine aTE;
1434 0 : aTE.SetText( GetText() );
1435 0 : aTE.SetMaxTextWidth( aSize.Width() );
1436 0 : aTE.SetFont( aFont );
1437 0 : aTE.SetTextAlign( pImpVclMEdit->GetTextWindow()->GetTextEngine()->GetTextAlign() );
1438 0 : aTE.Draw( pDev, Point( aPos.X() + nOffX, aPos.Y() + nOffY ) );
1439 :
1440 0 : pDev->Pop();
1441 0 : }
1442 :
1443 82 : bool VclMultiLineEdit::Notify( NotifyEvent& rNEvt )
1444 : {
1445 82 : bool nDone = false;
1446 82 : if( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
1447 : {
1448 0 : nDone = pImpVclMEdit->HandleCommand( *rNEvt.GetCommandEvent() );
1449 : }
1450 82 : return nDone || Edit::Notify( rNEvt );
1451 : }
1452 :
1453 0 : bool VclMultiLineEdit::PreNotify( NotifyEvent& rNEvt )
1454 : {
1455 0 : bool nDone = false;
1456 :
1457 0 : if( ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) )
1458 : {
1459 0 : const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
1460 0 : if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) )
1461 : {
1462 0 : nDone = true;
1463 0 : TextSelection aSel = pImpVclMEdit->GetTextWindow()->GetTextView()->GetSelection();
1464 0 : if ( aSel.HasRange() )
1465 : {
1466 0 : aSel.GetStart() = aSel.GetEnd();
1467 0 : pImpVclMEdit->GetTextWindow()->GetTextView()->SetSelection( aSel );
1468 : }
1469 : else
1470 : {
1471 0 : switch ( rKEvent.GetKeyCode().GetCode() )
1472 : {
1473 : case KEY_UP:
1474 : {
1475 0 : if ( pImpVclMEdit->GetVScrollBar() )
1476 0 : pImpVclMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEUP );
1477 : }
1478 0 : break;
1479 : case KEY_DOWN:
1480 : {
1481 0 : if ( pImpVclMEdit->GetVScrollBar() )
1482 0 : pImpVclMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEDOWN );
1483 : }
1484 0 : break;
1485 : case KEY_PAGEUP :
1486 : {
1487 0 : if ( pImpVclMEdit->GetVScrollBar() )
1488 0 : pImpVclMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEUP );
1489 : }
1490 0 : break;
1491 : case KEY_PAGEDOWN:
1492 : {
1493 0 : if ( pImpVclMEdit->GetVScrollBar() )
1494 0 : pImpVclMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEDOWN );
1495 : }
1496 0 : break;
1497 : case KEY_LEFT:
1498 : {
1499 0 : if ( pImpVclMEdit->GetHScrollBar() )
1500 0 : pImpVclMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEUP );
1501 : }
1502 0 : break;
1503 : case KEY_RIGHT:
1504 : {
1505 0 : if ( pImpVclMEdit->GetHScrollBar() )
1506 0 : pImpVclMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEDOWN );
1507 : }
1508 0 : break;
1509 : case KEY_HOME:
1510 : {
1511 0 : if ( rKEvent.GetKeyCode().IsMod1() )
1512 0 : pImpVclMEdit->GetTextWindow()->GetTextView()->
1513 0 : SetSelection( TextSelection( TextPaM( 0, 0 ) ) );
1514 : }
1515 0 : break;
1516 : case KEY_END:
1517 : {
1518 0 : if ( rKEvent.GetKeyCode().IsMod1() )
1519 0 : pImpVclMEdit->GetTextWindow()->GetTextView()->
1520 0 : SetSelection( TextSelection( TextPaM( 0xFFFF, 0xFFFF ) ) );
1521 : }
1522 0 : break;
1523 : default:
1524 : {
1525 0 : nDone = false;
1526 : }
1527 : }
1528 : }
1529 : }
1530 : }
1531 :
1532 0 : return nDone || Edit::PreNotify( rNEvt );
1533 : }
1534 :
1535 : // Internals for derived classes, e.g. TextComponent
1536 :
1537 7 : ExtTextEngine* VclMultiLineEdit::GetTextEngine() const
1538 : {
1539 7 : return pImpVclMEdit->GetTextWindow()->GetTextEngine();
1540 : }
1541 :
1542 7 : ExtTextView* VclMultiLineEdit::GetTextView() const
1543 : {
1544 7 : return pImpVclMEdit->GetTextWindow()->GetTextView();
1545 : }
1546 :
1547 0 : ScrollBar* VclMultiLineEdit::GetVScrollBar() const
1548 : {
1549 0 : return pImpVclMEdit->GetVScrollBar();
1550 : }
1551 :
1552 13 : void VclMultiLineEdit::EnableFocusSelectionHide( bool bHide )
1553 : {
1554 13 : pImpVclMEdit->GetTextWindow()->SetAutoFocusHide( bHide );
1555 13 : }
1556 :
1557 0 : void VclMultiLineEdit::SetLeftMargin( sal_uInt16 n )
1558 : {
1559 0 : if ( GetTextEngine() )
1560 0 : GetTextEngine()->SetLeftMargin( n );
1561 0 : }
1562 :
1563 0 : void VclMultiLineEdit::SetRightToLeft( bool bRightToLeft )
1564 : {
1565 0 : if ( GetTextEngine() )
1566 : {
1567 0 : GetTextEngine()->SetRightToLeft( bRightToLeft );
1568 0 : GetTextView()->ShowCursor();
1569 : }
1570 0 : }
1571 :
1572 11 : void VclMultiLineEdit::DisableSelectionOnFocus()
1573 : {
1574 11 : pImpVclMEdit->GetTextWindow()->DisableSelectionOnFocus();
1575 11 : }
1576 :
1577 7 : void VclMultiLineEdit::EnableCursor( bool bEnable )
1578 : {
1579 7 : GetTextView()->EnableCursor( bEnable );
1580 7 : }
1581 :
1582 0 : bool VclMultiLineEdit::set_property(const OString &rKey, const OString &rValue)
1583 : {
1584 0 : if (rKey == "cursor-visible")
1585 0 : EnableCursor(toBool(rValue));
1586 0 : else if (rKey == "accepts-tab")
1587 0 : pImpVclMEdit->GetTextWindow()->SetIgnoreTab(!toBool(rValue));
1588 : else
1589 0 : return Edit::set_property(rKey, rValue);
1590 0 : return true;
1591 801 : }
1592 :
1593 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|