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