Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / app / inputwin.cxx
blobb32fb5d7506ec1c2328fd10d1344ba1640602bb6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <algorithm>
23 #include "scitems.hxx"
24 #include <editeng/eeitem.hxx>
26 #include <sfx2/app.hxx>
27 #include <editeng/adjustitem.hxx>
28 #include <editeng/editview.hxx>
29 #include <editeng/editstat.hxx>
30 #include <editeng/frmdiritem.hxx>
31 #include <editeng/lspcitem.hxx>
32 #include <sfx2/bindings.hxx>
33 #include <sfx2/viewfrm.hxx>
34 #include <sfx2/dispatch.hxx>
35 #include <sfx2/event.hxx>
36 #include <sfx2/imgmgr.hxx>
37 #include <stdlib.h>
38 #include <editeng/scriptspaceitem.hxx>
39 #include <editeng/scripttypeitem.hxx>
40 #include <vcl/cursor.hxx>
41 #include <vcl/help.hxx>
42 #include <svl/stritem.hxx>
43 #include <stdio.h>
45 #include "inputwin.hxx"
46 #include "scmod.hxx"
47 #include "uiitems.hxx"
48 #include "global.hxx"
49 #include "scresid.hxx"
50 #include "sc.hrc"
51 #include "globstr.hrc"
52 #include "reffact.hxx"
53 #include "editutil.hxx"
54 #include "inputhdl.hxx"
55 #include "tabvwsh.hxx"
56 #include "document.hxx"
57 #include "docsh.hxx"
58 #include "appoptio.hxx"
59 #include "rangenam.hxx"
60 #include <formula/compiler.hrc>
61 #include "dbdata.hxx"
62 #include "rangeutl.hxx"
63 #include "docfunc.hxx"
64 #include "funcdesc.hxx"
65 #include "markdata.hxx"
66 #include <editeng/fontitem.hxx>
67 #include <com/sun/star/accessibility/XAccessible.hpp>
68 #include "AccessibleEditObject.hxx"
69 #include "AccessibleText.hxx"
70 #include <svtools/miscopt.hxx>
71 #include <comphelper/string.hxx>
72 #include <com/sun/star/frame/XLayoutManager.hpp>
73 #include <com/sun/star/frame/XModel.hpp>
74 #include <com/sun/star/frame/XController.hpp>
76 #define THESIZE 1000000 //!!! langt... :-)
77 #define TBX_WINDOW_HEIGHT 22 // in Pixeln - fuer alle Systeme gleich?
78 #define LEFT_OFFSET 5
79 #define INPUTWIN_MULTILINES 6
80 const long BUTTON_OFFSET = 2; ///< space between input line and the button to expand / collapse
81 const long ADDITIONAL_BORDER = 1; ///< height of the line at the bottom
82 const long ADDITIONAL_SPACE = 4; ///< additional vertical space when the multiline edit has more lines
84 using com::sun::star::uno::Reference;
85 using com::sun::star::uno::UNO_QUERY;
87 using com::sun::star::frame::XLayoutManager;
88 using com::sun::star::frame::XModel;
89 using com::sun::star::frame::XFrame;
90 using com::sun::star::frame::XController;
91 using com::sun::star::beans::XPropertySet;
94 enum ScNameInputType
96 SC_NAME_INPUT_CELL,
97 SC_NAME_INPUT_RANGE,
98 SC_NAME_INPUT_NAMEDRANGE,
99 SC_NAME_INPUT_DATABASE,
100 SC_NAME_INPUT_ROW,
101 SC_NAME_INPUT_SHEET,
102 SC_NAME_INPUT_DEFINE,
103 SC_NAME_INPUT_BAD_NAME,
104 SC_NAME_INPUT_BAD_SELECTION,
105 SC_MANAGE_NAMES
109 ScTextWndBase::ScTextWndBase( Window* pParent, WinBits nStyle )
110 : Window ( pParent, nStyle )
112 if ( IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) )
114 SetType( WINDOW_CALCINPUTLINE );
115 SetBorderStyle( WINDOW_BORDER_NWF );
119 //==================================================================
120 // class ScInputWindowWrapper
121 //==================================================================
123 SFX_IMPL_CHILDWINDOW_WITHID(ScInputWindowWrapper,FID_INPUTLINE_STATUS)
125 ScInputWindowWrapper::ScInputWindowWrapper( Window* pParentP,
126 sal_uInt16 nId,
127 SfxBindings* pBindings,
128 SfxChildWinInfo* /* pInfo */ )
129 : SfxChildWindow( pParentP, nId )
131 ScInputWindow* pWin=new ScInputWindow( pParentP, pBindings );
132 pWindow = pWin;
134 pWin->Show();
136 pWin->SetSizePixel( pWin->CalcWindowSizePixel() );
138 eChildAlignment = SFX_ALIGN_LOWESTTOP;
139 pBindings->Invalidate( FID_TOGGLEINPUTLINE );
142 // GetInfo fliegt wieder raus, wenn es ein SFX_IMPL_TOOLBOX gibt !!!!
144 SfxChildWinInfo ScInputWindowWrapper::GetInfo() const
146 SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
147 return aInfo;
150 //==================================================================
152 #define IMAGE(id) pImgMgr->SeekImage(id)
153 static bool lcl_isExperimentalMode()
155 // make inputbar feature on by default, leave the switch for the
156 // moment in case we need to back it out easily
157 return true;
160 //==================================================================
161 // class ScInputWindow
162 //==================================================================
164 static ScTextWndBase* lcl_chooseRuntimeImpl( Window* pParent, SfxBindings* pBind )
166 ScTabViewShell* pViewSh = NULL;
167 SfxDispatcher* pDisp = pBind->GetDispatcher();
168 if ( pDisp )
170 SfxViewFrame* pViewFrm = pDisp->GetFrame();
171 if ( pViewFrm )
172 pViewSh = PTR_CAST( ScTabViewShell, pViewFrm->GetViewShell() );
175 if ( !lcl_isExperimentalMode() )
176 return new ScTextWnd( pParent, pViewSh );
177 return new ScInputBarGroup( pParent, pViewSh );
180 ScInputWindow::ScInputWindow( Window* pParent, SfxBindings* pBind ) :
181 // mit WB_CLIPCHILDREN, sonst Flicker
182 ToolBox ( pParent, WinBits(WB_CLIPCHILDREN) ),
183 aWndPos ( this ),
184 pRuntimeWindow ( lcl_chooseRuntimeImpl( this, pBind ) ),
185 aTextWindow ( *pRuntimeWindow ),
186 pInputHdl ( NULL ),
187 aTextOk ( ScResId( SCSTR_QHELP_BTNOK ) ), // nicht immer neu aus Resource
188 aTextCancel ( ScResId( SCSTR_QHELP_BTNCANCEL ) ),
189 aTextSum ( ScResId( SCSTR_QHELP_BTNSUM ) ),
190 aTextEqual ( ScResId( SCSTR_QHELP_BTNEQUAL ) ),
191 mnMaxY (0),
192 bIsOkCancelMode ( false ),
193 bInResize ( false ),
194 mbIsMultiLine ( lcl_isExperimentalMode() )
196 ScModule* pScMod = SC_MOD();
197 SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
199 // #i73615# don't rely on SfxViewShell::Current while constructing the input line
200 // (also for GetInputHdl below)
201 ScTabViewShell* pViewSh = NULL;
202 SfxDispatcher* pDisp = pBind->GetDispatcher();
203 if ( pDisp )
205 SfxViewFrame* pViewFrm = pDisp->GetFrame();
206 if ( pViewFrm )
207 pViewSh = PTR_CAST( ScTabViewShell, pViewFrm->GetViewShell() );
209 OSL_ENSURE( pViewSh, "no view shell for input window" );
211 // Position window, 3 buttons, input window
212 InsertWindow ( 1, &aWndPos, 0, 0 );
213 InsertSeparator ( 1 );
214 InsertItem ( SID_INPUT_FUNCTION, IMAGE( SID_INPUT_FUNCTION ), 0, 2 );
215 InsertItem ( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ), 0, 3 );
216 InsertItem ( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ), 0, 4 );
217 InsertSeparator ( 5 );
218 InsertWindow ( 7, &aTextWindow, 0, 6 );
220 aWndPos .SetQuickHelpText( ScResId( SCSTR_QHELP_POSWND ) );
221 aWndPos .SetHelpId ( HID_INSWIN_POS );
222 aTextWindow.SetQuickHelpText( ScResId( SCSTR_QHELP_INPUTWND ) );
223 aTextWindow.SetHelpId ( HID_INSWIN_INPUT );
225 // kein SetHelpText, die Hilfetexte kommen aus der Hilfe
227 SetItemText ( SID_INPUT_FUNCTION, ScResId( SCSTR_QHELP_BTNCALC ) );
228 SetHelpId ( SID_INPUT_FUNCTION, HID_INSWIN_CALC );
230 SetItemText ( SID_INPUT_SUM, aTextSum );
231 SetHelpId ( SID_INPUT_SUM, HID_INSWIN_SUMME );
233 SetItemText ( SID_INPUT_EQUAL, aTextEqual );
234 SetHelpId ( SID_INPUT_EQUAL, HID_INSWIN_FUNC );
236 SetHelpId( HID_SC_INPUTWIN ); // fuer die ganze Eingabezeile
238 aWndPos .Show();
239 aTextWindow.Show();
241 pInputHdl = SC_MOD()->GetInputHdl( pViewSh, false ); // use own handler even if ref-handler is set
242 if (pInputHdl)
243 pInputHdl->SetInputWindow( this );
245 if (pInputHdl && !pInputHdl->GetFormString().isEmpty())
247 // Umschalten waehrend der Funktionsautopilot aktiv ist
248 // -> Inhalt des Funktionsautopiloten wieder anzeigen
249 //! auch Selektion (am InputHdl gemerkt) wieder anzeigen
251 aTextWindow.SetTextString( pInputHdl->GetFormString() );
253 else if ( pInputHdl && pInputHdl->IsInputMode() )
255 // wenn waehrend des Editierens die Eingabezeile weg war
256 // (Editieren einer Formel, dann umschalten zu fremdem Dokument/Hilfe),
257 // wieder den gerade editierten Text aus dem InputHandler anzeigen
259 aTextWindow.SetTextString( pInputHdl->GetEditString() ); // Text anzeigen
260 if ( pInputHdl->IsTopMode() )
261 pInputHdl->SetMode( SC_INPUT_TABLE ); // Focus kommt eh nach unten
263 else if ( pViewSh )
264 pViewSh->UpdateInputHandler( sal_True ); // unbedingtes Update
266 pImgMgr->RegisterToolBox( this );
267 SetAccessibleName(ScResId(STR_ACC_TOOLBAR_FORMULA));
270 ScInputWindow::~ScInputWindow()
272 sal_Bool bDown = ( ScGlobal::pSysLocale == NULL ); // after Clear?
274 // if any view's input handler has a pointer to this input window, reset it
275 // (may be several ones, #74522#)
276 // member pInputHdl is not used here
278 if ( !bDown )
280 TypeId aScType = TYPE(ScTabViewShell);
281 SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
282 while ( pSh )
284 ScInputHandler* pHdl = ((ScTabViewShell*)pSh)->GetInputHandler();
285 if ( pHdl && pHdl->GetInputWindow() == this )
287 pHdl->SetInputWindow( NULL );
288 pHdl->StopInputWinEngine( false ); // reset pTopView pointer
290 pSh = SfxViewShell::GetNext( *pSh, &aScType );
294 SfxImageManager::GetImageManager( SC_MOD() )->ReleaseToolBox( this );
297 void ScInputWindow::SetInputHandler( ScInputHandler* pNew )
299 // wird im Activate der View gerufen...
301 if ( pNew != pInputHdl )
303 // Bei Reload (letzte Version) ist pInputHdl der Input-Handler der alten,
304 // geloeschten ViewShell, darum hier auf keinen Fall anfassen!
306 pInputHdl = pNew;
307 if (pInputHdl)
308 pInputHdl->SetInputWindow( this );
312 bool ScInputWindow::UseSubTotal(ScRangeList* pRangeList) const
314 bool bSubTotal = false;
315 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
316 if ( pViewSh )
318 ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
319 size_t nRangeCount (pRangeList->size());
320 size_t nRangeIndex (0);
321 while (!bSubTotal && nRangeIndex < nRangeCount)
323 const ScRange* pRange = (*pRangeList)[nRangeIndex];
324 if( pRange )
326 SCTAB nTabEnd(pRange->aEnd.Tab());
327 SCTAB nTab(pRange->aStart.Tab());
328 while (!bSubTotal && nTab <= nTabEnd)
330 SCROW nRowEnd(pRange->aEnd.Row());
331 SCROW nRow(pRange->aStart.Row());
332 while (!bSubTotal && nRow <= nRowEnd)
334 if (pDoc->RowFiltered(nRow, nTab))
335 bSubTotal = true;
336 else
337 ++nRow;
339 ++nTab;
342 ++nRangeIndex;
345 const ScDBCollection::NamedDBs& rDBs = pDoc->GetDBCollection()->getNamedDBs();
346 ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
347 for (; !bSubTotal && itr != itrEnd; ++itr)
349 const ScDBData& rDB = *itr;
350 if (!rDB.HasAutoFilter())
351 continue;
353 nRangeIndex = 0;
354 while (!bSubTotal && nRangeIndex < nRangeCount)
356 const ScRange* pRange = (*pRangeList)[nRangeIndex];
357 if( pRange )
359 ScRange aDBArea;
360 rDB.GetArea(aDBArea);
361 if (aDBArea.Intersects(*pRange))
362 bSubTotal = true;
364 ++nRangeIndex;
368 return bSubTotal;
371 void ScInputWindow::Select()
373 ScModule* pScMod = SC_MOD();
374 ToolBox::Select();
376 switch ( GetCurItemId() )
378 case SID_INPUT_FUNCTION:
380 //! new method at ScModule to query if function autopilot is open
381 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
382 if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
384 pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
385 SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD );
387 // die Toolbox wird sowieso disabled, also braucht auch nicht umgeschaltet
388 // zu werden, egal ob's geklappt hat oder nicht
389 // SetOkCancelMode();
392 break;
394 case SID_INPUT_CANCEL:
395 pScMod->InputCancelHandler();
396 SetSumAssignMode();
397 break;
399 case SID_INPUT_OK:
400 pScMod->InputEnterHandler();
401 SetSumAssignMode();
402 aTextWindow.Invalidate(); // sonst bleibt Selektion stehen
403 break;
405 case SID_INPUT_SUM:
407 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
408 if ( pViewSh )
410 const ScMarkData& rMark = pViewSh->GetViewData()->GetMarkData();
411 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
413 ScRangeList aMarkRangeList;
414 rMark.FillRangeListWithMarks( &aMarkRangeList, false );
415 ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
417 // check if one of the marked ranges is empty
418 bool bEmpty = false;
419 const size_t nCount = aMarkRangeList.size();
420 for ( size_t i = 0; i < nCount; ++i )
422 const ScRange aRange( *aMarkRangeList[i] );
423 if ( pDoc->IsBlockEmpty( aRange.aStart.Tab(),
424 aRange.aStart.Col(), aRange.aStart.Row(),
425 aRange.aEnd.Col(), aRange.aEnd.Row() ) )
427 bEmpty = true;
428 break;
432 if ( bEmpty )
434 ScRangeList aRangeList;
435 const sal_Bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
436 if ( bDataFound )
438 ScAddress aAddr = aRangeList.back()->aEnd;
439 aAddr.IncRow();
440 const sal_Bool bSubTotal( UseSubTotal( &aRangeList ) );
441 pViewSh->EnterAutoSum( aRangeList, bSubTotal, aAddr );
444 else
446 const sal_Bool bSubTotal( UseSubTotal( &aMarkRangeList ) );
447 for ( size_t i = 0; i < nCount; ++i )
449 const ScRange aRange( *aMarkRangeList[i] );
450 const bool bSetCursor = ( i == nCount - 1 ? true : false );
451 const bool bContinue = ( i != 0 ? true : false );
452 if ( !pViewSh->AutoSum( aRange, bSubTotal, bSetCursor, bContinue ) )
454 pViewSh->MarkRange( aRange, false, false );
455 pViewSh->SetCursor( aRange.aEnd.Col(), aRange.aEnd.Row() );
456 const ScRangeList aRangeList;
457 ScAddress aAddr = aRange.aEnd;
458 aAddr.IncRow();
459 const OUString aFormula = pViewSh->GetAutoSumFormula(
460 aRangeList, bSubTotal, aAddr );
461 SetFuncString( aFormula );
462 break;
467 else // nur in Eingabezeile einfuegen
469 ScRangeList aRangeList;
470 const sal_Bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
471 const sal_Bool bSubTotal( UseSubTotal( &aRangeList ) );
472 ScAddress aAddr = pViewSh->GetViewData()->GetCurPos();
473 const OUString aFormula = pViewSh->GetAutoSumFormula( aRangeList, bSubTotal, aAddr );
474 SetFuncString( aFormula );
476 if ( bDataFound && pScMod->IsEditMode() )
478 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
479 if ( pHdl )
481 pHdl->InitRangeFinder( aFormula );
483 //! SetSelection am InputHandler ???
484 //! bSelIsRef setzen ???
485 const sal_Int32 nOpen = aFormula.indexOf('(');
486 const xub_StrLen nLen = aFormula.getLength();
487 if ( nOpen != -1 && nLen > nOpen )
489 sal_uInt8 nAdd(1);
490 if (bSubTotal)
491 nAdd = 3;
492 ESelection aSel(0,nOpen+nAdd,0,nLen-1);
493 EditView* pTableView = pHdl->GetTableView();
494 if (pTableView)
495 pTableView->SetSelection(aSel);
496 EditView* pTopView = pHdl->GetTopView();
497 if (pTopView)
498 pTopView->SetSelection(aSel);
505 break;
507 case SID_INPUT_EQUAL:
509 aTextWindow.StartEditEngine();
510 if ( pScMod->IsEditMode() ) // nicht, wenn z.B. geschuetzt
512 aTextWindow.StartEditEngine();
513 aTextWindow.SetTextString(OUString('='));
515 EditView* pView = aTextWindow.GetEditView();
516 if (pView)
518 pView->SetSelection( ESelection(0,1, 0,1) );
519 pScMod->InputChanged(pView);
520 SetOkCancelMode();
521 pView->SetEditEngineUpdateMode(sal_True);
524 break;
529 void ScInputWindow::Paint( const Rectangle& rRect )
531 ToolBox::Paint( rRect );
533 // draw a line at the bottom to distinguish that from the grid
534 // (we have space for that thanks to ADDITIONAL_BORDER)
535 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
536 SetLineColor( rStyleSettings.GetShadowColor() );
538 Size aSize = GetSizePixel();
539 DrawLine( Point( 0, aSize.Height() - 1 ), Point( aSize.Width() - 1, aSize.Height() - 1 ) );
542 void ScInputWindow::Resize()
544 ToolBox::Resize();
545 if ( mbIsMultiLine )
547 aTextWindow.Resize();
548 Size aSize = GetSizePixel();
549 aSize.Height() = CalcWindowSizePixel().Height() + ADDITIONAL_BORDER;
550 ScInputBarGroup* pGroupBar = dynamic_cast< ScInputBarGroup* > ( pRuntimeWindow.get() );
551 if ( pGroupBar )
553 // To ensure smooth display and prevent the items in the toolbar being
554 // repositioned ( vertically ) we lock the vertical positioning of the toolbox
555 // items when we are displaying > 1 line.
556 // So, we need to adjust the height of the toolbox accordingly. If we don't
557 // then the largest item ( e.g. the GroupBar window ) will actually be
558 // positioned such that the toolbar will cut off the bottom of that item
559 if ( pGroupBar->GetNumLines() > 1 )
560 aSize.Height() += pGroupBar->GetVertOffset() + ADDITIONAL_SPACE;
562 SetSizePixel(aSize);
563 Invalidate();
565 else
567 long nWidth = GetSizePixel().Width();
568 long nLeft = aTextWindow.GetPosPixel().X();
569 Size aSize = aTextWindow.GetSizePixel();
571 aSize.Width() = std::max( ((long)(nWidth - nLeft - 5)), (long)0 );
573 aTextWindow.SetSizePixel( aSize );
574 aTextWindow.Invalidate();
578 void ScInputWindow::SetFuncString( const OUString& rString, sal_Bool bDoEdit )
580 //! new method at ScModule to query if function autopilot is open
581 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
582 EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
583 aTextWindow.StartEditEngine();
585 ScModule* pScMod = SC_MOD();
586 if ( pScMod->IsEditMode() )
588 if ( bDoEdit )
589 aTextWindow.GrabFocus();
590 aTextWindow.SetTextString( rString );
591 EditView* pView = aTextWindow.GetEditView();
592 if (pView)
594 sal_Int32 nLen = rString.getLength();
596 if ( nLen > 0 )
598 nLen--;
599 pView->SetSelection( ESelection( 0, nLen, 0, nLen ) );
602 pScMod->InputChanged(pView);
603 if ( bDoEdit )
604 SetOkCancelMode(); // nicht, wenn gleich hinterher Enter/Cancel
606 pView->SetEditEngineUpdateMode(sal_True);
611 void ScInputWindow::SetPosString( const OUString& rStr )
613 aWndPos.SetPos( rStr );
616 void ScInputWindow::SetTextString( const OUString& rString )
618 if (rString.getLength() <= 32767)
619 aTextWindow.SetTextString(rString);
620 else
621 aTextWindow.SetTextString(rString.copy(0, 32767));
624 void ScInputWindow::SetOkCancelMode()
626 //! new method at ScModule to query if function autopilot is open
627 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
628 EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
630 ScModule* pScMod = SC_MOD();
631 SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
632 if (!bIsOkCancelMode)
634 RemoveItem( 3 ); // SID_INPUT_SUM und SID_INPUT_EQUAL entfernen
635 RemoveItem( 3 );
636 InsertItem( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ), 0, 3 );
637 InsertItem( SID_INPUT_OK, IMAGE( SID_INPUT_OK ), 0, 4 );
638 SetItemText ( SID_INPUT_CANCEL, aTextCancel );
639 SetHelpId ( SID_INPUT_CANCEL, HID_INSWIN_CANCEL );
640 SetItemText ( SID_INPUT_OK, aTextOk );
641 SetHelpId ( SID_INPUT_OK, HID_INSWIN_OK );
642 bIsOkCancelMode = sal_True;
646 void ScInputWindow::SetSumAssignMode()
648 //! new method at ScModule to query if function autopilot is open
649 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
650 EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
652 ScModule* pScMod = SC_MOD();
653 SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
654 if (bIsOkCancelMode)
656 // SID_INPUT_CANCEL, und SID_INPUT_OK entfernen
657 RemoveItem( 3 );
658 RemoveItem( 3 );
659 InsertItem( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ), 0, 3 );
660 InsertItem( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ), 0, 4 );
661 SetItemText ( SID_INPUT_SUM, aTextSum );
662 SetHelpId ( SID_INPUT_SUM, HID_INSWIN_SUMME );
663 SetItemText ( SID_INPUT_EQUAL, aTextEqual );
664 SetHelpId ( SID_INPUT_EQUAL, HID_INSWIN_FUNC );
665 bIsOkCancelMode = false;
667 SetFormulaMode(false); // kein editieren -> keine Formel
671 void ScInputWindow::SetFormulaMode( sal_Bool bSet )
673 aWndPos.SetFormulaMode(bSet);
674 aTextWindow.SetFormulaMode(bSet);
677 void ScInputWindow::SetText( const OUString& rString )
679 ToolBox::SetText(rString);
682 OUString ScInputWindow::GetText() const
684 return ToolBox::GetText();
687 sal_Bool ScInputWindow::IsInputActive()
689 return aTextWindow.IsInputActive();
692 EditView* ScInputWindow::GetEditView()
694 return aTextWindow.GetEditView();
697 void ScInputWindow::MakeDialogEditView()
699 aTextWindow.MakeDialogEditView();
702 void ScInputWindow::StopEditEngine( sal_Bool bAll )
704 aTextWindow.StopEditEngine( bAll );
707 void ScInputWindow::TextGrabFocus()
709 aTextWindow.TextGrabFocus();
712 void ScInputWindow::TextInvalidate()
714 aTextWindow.Invalidate();
717 void ScInputWindow::SwitchToTextWin()
719 // used for shift-ctrl-F2
721 aTextWindow.StartEditEngine();
722 if ( SC_MOD()->IsEditMode() )
724 aTextWindow.TextGrabFocus();
725 EditView* pView = aTextWindow.GetEditView();
726 if (pView)
728 sal_Int32 nPara = pView->GetEditEngine()->GetParagraphCount() ? ( pView->GetEditEngine()->GetParagraphCount() - 1 ) : 0;
729 xub_StrLen nLen = pView->GetEditEngine()->GetTextLen( nPara );
730 ESelection aSel( nPara, nLen, nPara, nLen );
731 pView->SetSelection( aSel ); // set cursor to end of text
736 void ScInputWindow::PosGrabFocus()
738 aWndPos.GrabFocus();
741 void ScInputWindow::EnableButtons( sal_Bool bEnable )
743 // when enabling buttons, always also enable the input window itself
744 if ( bEnable && !IsEnabled() )
745 Enable();
747 EnableItem( SID_INPUT_FUNCTION, bEnable );
748 EnableItem( bIsOkCancelMode ? SID_INPUT_CANCEL : SID_INPUT_SUM, bEnable );
749 EnableItem( bIsOkCancelMode ? SID_INPUT_OK : SID_INPUT_EQUAL, bEnable );
750 // Invalidate();
753 void ScInputWindow::StateChanged( StateChangedType nType )
755 ToolBox::StateChanged( nType );
757 if ( nType == STATE_CHANGE_INITSHOW ) Resize();
760 void ScInputWindow::DataChanged( const DataChangedEvent& rDCEvt )
762 if ( rDCEvt.GetType() == DATACHANGED_SETTINGS && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
764 // update item images
765 ScModule* pScMod = SC_MOD();
766 SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
767 // IMAGE macro uses pScMod, pImgMg
769 SetItemImage( SID_INPUT_FUNCTION, IMAGE( SID_INPUT_FUNCTION ) );
770 if ( bIsOkCancelMode )
772 SetItemImage( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ) );
773 SetItemImage( SID_INPUT_OK, IMAGE( SID_INPUT_OK ) );
775 else
777 SetItemImage( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ) );
778 SetItemImage( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ) );
782 ToolBox::DataChanged( rDCEvt );
785 bool ScInputWindow::IsPointerAtResizePos()
787 if ( GetOutputSizePixel().Height() - GetPointerPosPixel().Y() <= 4 )
788 return true;
789 else
790 return false;
793 void ScInputWindow::MouseMove( const MouseEvent& rMEvt )
795 if ( mbIsMultiLine )
797 Point aPosPixel = GetPointerPosPixel();
799 ScInputBarGroup* pGroupBar = dynamic_cast< ScInputBarGroup* > ( pRuntimeWindow.get() );
801 if ( bInResize || IsPointerAtResizePos() )
802 SetPointer( Pointer( POINTER_WINDOW_SSIZE ) );
803 else
804 SetPointer( Pointer( POINTER_ARROW ) );
806 if ( bInResize )
808 // detect direction
809 long nResizeThreshold = ( (long)TBX_WINDOW_HEIGHT * 0.7 );
810 bool bResetPointerPos = false;
812 // Detect attempt to expand toolbar too much
813 if ( aPosPixel.Y() >= mnMaxY )
815 bResetPointerPos = true;
816 aPosPixel.Y() = mnMaxY;
817 } // or expanding down
818 else if ( GetOutputSizePixel().Height() - aPosPixel.Y() < -nResizeThreshold )
820 pGroupBar->IncrementVerticalSize();
821 bResetPointerPos = true;
822 } // or shrinking up
823 else if ( ( GetOutputSizePixel().Height() - aPosPixel.Y() ) > nResizeThreshold )
825 bResetPointerPos = true;
826 pGroupBar->DecrementVerticalSize();
829 if ( bResetPointerPos )
831 aPosPixel.Y() = GetOutputSizePixel().Height();
832 SetPointerPosPixel( aPosPixel );
836 ToolBox::MouseMove( rMEvt );
839 void ScInputWindow::MouseButtonDown( const MouseEvent& rMEvt )
841 if ( mbIsMultiLine )
843 if ( rMEvt.IsLeft() )
845 if ( IsPointerAtResizePos() )
847 // Don't leave the mouse pointer leave *this* window
848 CaptureMouse();
849 bInResize = true;
850 // find the height of the gridwin, we don't wan't to be
851 // able to expand the toolbar too far so we need to
852 // caculate an upper limit
853 // I'd prefer to leave at least a single column header and a
854 // row but I don't know how to get that value in pixels.
855 // Use TBX_WINDOW_HEIGHT for the moment
856 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
857 mnMaxY = GetOutputSizePixel().Height() + ( pViewSh->GetGridHeight(SC_SPLIT_TOP) + pViewSh->GetGridHeight(SC_SPLIT_BOTTOM) ) - TBX_WINDOW_HEIGHT;
861 ToolBox::MouseButtonDown( rMEvt );
863 void ScInputWindow::MouseButtonUp( const MouseEvent& rMEvt )
865 if ( mbIsMultiLine )
867 ReleaseMouse();
868 if ( rMEvt.IsLeft() )
870 bInResize = false;
871 mnMaxY = 0;
874 ToolBox::MouseButtonUp( rMEvt );
878 //========================================================================
879 // ScInputBarGroup
880 //========================================================================
882 ScInputBarGroup::ScInputBarGroup(Window* pParent, ScTabViewShell* pViewSh)
883 : ScTextWndBase ( pParent, WinBits(WB_HIDE | WB_TABSTOP ) ),
884 aMultiTextWnd ( this, pViewSh ),
885 aButton ( this, WB_TABSTOP | WB_RECTSTYLE | WB_SMALLSTYLE ),
886 aScrollBar ( this, WB_TABSTOP | WB_VERT | WB_DRAG ),
887 nVertOffset ( 0 )
889 aMultiTextWnd.Show();
890 aMultiTextWnd.SetQuickHelpText( ScResId( SCSTR_QHELP_INPUTWND ) );
891 aMultiTextWnd.SetHelpId( HID_INSWIN_INPUT );
893 Size aSize( GetSettings().GetStyleSettings().GetScrollBarSize(), aMultiTextWnd.GetPixelHeightForLines(1) );
895 aButton.SetClickHdl( LINK( this, ScInputBarGroup, ClickHdl ) );
896 aButton.SetSizePixel( aSize );
897 aButton.Enable();
898 aButton.SetSymbol( SYMBOL_SPIN_DOWN );
899 aButton.SetQuickHelpText( ScResId( SCSTR_QHELP_EXPAND_FORMULA ) );
900 aButton.Show();
902 aScrollBar.SetSizePixel( aSize );
903 aScrollBar.SetScrollHdl( LINK( this, ScInputBarGroup, Impl_ScrollHdl ) );
906 ScInputBarGroup::~ScInputBarGroup()
911 void
912 ScInputBarGroup::InsertAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
914 aMultiTextWnd.InsertAccessibleTextData( rTextData );
917 void
918 ScInputBarGroup::RemoveAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
920 aMultiTextWnd.RemoveAccessibleTextData( rTextData );
923 const OUString&
924 ScInputBarGroup::GetTextString() const
926 return aMultiTextWnd.GetTextString();
929 void ScInputBarGroup::SetTextString( const OUString& rString )
931 aMultiTextWnd.SetTextString(rString);
934 void ScInputBarGroup::Resize()
936 Window *w=GetParent();
937 ScInputWindow *pParent;
938 pParent=dynamic_cast<ScInputWindow*>(w);
940 if(pParent==NULL)
942 OSL_FAIL("The parent window pointer pParent is null");
943 return;
946 long nWidth = pParent->GetSizePixel().Width();
947 long nLeft = GetPosPixel().X();
949 Size aSize = GetSizePixel();
950 aSize.Width() = std::max( ((long)(nWidth - nLeft - LEFT_OFFSET)), (long)0 );
952 aScrollBar.SetPosPixel(Point( aSize.Width() - aButton.GetSizePixel().Width(), aButton.GetSizePixel().Height() ) );
954 Size aTmpSize( aSize );
955 aTmpSize.Width() = aTmpSize.Width() - aButton.GetSizePixel().Width() - BUTTON_OFFSET;
956 aMultiTextWnd.SetSizePixel(aTmpSize);
958 aMultiTextWnd.Resize();
960 aSize.Height() = aMultiTextWnd.GetSizePixel().Height();
962 SetSizePixel(aSize);
964 if( aMultiTextWnd.GetNumLines() > 1 )
966 aButton.SetSymbol( SYMBOL_SPIN_UP );
967 aButton.SetQuickHelpText( ScResId( SCSTR_QHELP_COLLAPSE_FORMULA ) );
968 Size scrollSize = aButton.GetSizePixel();
969 scrollSize.Height() = aMultiTextWnd.GetSizePixel().Height() - aButton.GetSizePixel().Height();
970 aScrollBar.SetSizePixel( scrollSize );
972 Size aOutSz = aMultiTextWnd.GetOutputSize();
974 aScrollBar.SetVisibleSize( aOutSz.Height() );
975 aScrollBar.SetPageSize( aOutSz.Height() );
976 aScrollBar.SetLineSize( aMultiTextWnd.GetTextHeight() );
977 aScrollBar.SetRange( Range( 0, aMultiTextWnd.GetEditEngTxtHeight() ) );
979 aScrollBar.Resize();
980 aScrollBar.Show();
982 else
984 aButton.SetSymbol( SYMBOL_SPIN_DOWN );
985 aButton.SetQuickHelpText( ScResId( SCSTR_QHELP_EXPAND_FORMULA ) );
986 aScrollBar.Hide();
989 aButton.SetPosPixel(Point(aSize.Width() - aButton.GetSizePixel().Width(), 0));
991 Invalidate();
994 void ScInputBarGroup::StopEditEngine( sal_Bool bAll )
996 aMultiTextWnd.StopEditEngine( bAll );
999 void ScInputBarGroup::StartEditEngine()
1001 aMultiTextWnd.StartEditEngine();
1005 void ScInputBarGroup::MakeDialogEditView()
1007 aMultiTextWnd.MakeDialogEditView();
1011 EditView* ScInputBarGroup::GetEditView()
1013 return aMultiTextWnd.GetEditView();
1016 sal_Bool ScInputBarGroup::IsInputActive()
1018 return aMultiTextWnd.IsInputActive();
1021 void ScInputBarGroup::SetFormulaMode(sal_Bool bSet)
1023 aMultiTextWnd.SetFormulaMode(bSet);
1026 void ScInputBarGroup::IncrementVerticalSize()
1028 aMultiTextWnd.SetNumLines( aMultiTextWnd.GetNumLines() + 1 );
1029 TriggerToolboxLayout();
1032 void ScInputBarGroup::DecrementVerticalSize()
1034 if ( aMultiTextWnd.GetNumLines() > 1 )
1036 aMultiTextWnd.SetNumLines( aMultiTextWnd.GetNumLines() - 1 );
1037 TriggerToolboxLayout();
1041 IMPL_LINK_NOARG(ScInputBarGroup, ClickHdl)
1043 Window *w=GetParent();
1044 ScInputWindow *pParent;
1045 pParent=dynamic_cast<ScInputWindow*>(w);
1047 if(pParent==NULL)
1049 OSL_FAIL("The parent window pointer pParent is null");
1050 return 1;
1052 if( aMultiTextWnd.GetNumLines() > 1 )
1054 aMultiTextWnd.SetNumLines( 1 );
1056 else
1058 aMultiTextWnd.SetNumLines( aMultiTextWnd.GetLastNumExpandedLines() );
1060 TriggerToolboxLayout();
1061 // Restore focus to input line(s) if necessary
1062 if ( SC_MOD()->GetInputHdl()->IsTopMode() )
1063 aMultiTextWnd.GrabFocus();
1064 return 0;
1067 void ScInputBarGroup::TriggerToolboxLayout()
1069 Window *w=GetParent();
1070 ScInputWindow *pParent;
1071 pParent=dynamic_cast<ScInputWindow*>(w);
1072 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1074 // Capture the vertical position of this window in the toolbar, when we increase
1075 // the size of the toolbar to accomadate expanded line input we need to take this
1076 // into account
1077 if ( !nVertOffset )
1078 nVertOffset = pParent->GetItemPosRect( pParent->GetItemCount() - 1 ).Top();
1080 if ( pViewFrm )
1082 Reference< com::sun::star::beans::XPropertySet > xPropSet( pViewFrm->GetFrame().GetFrameInterface(), UNO_QUERY );
1083 Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1085 if ( xPropSet.is() )
1087 com::sun::star::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
1088 aValue >>= xLayoutManager;
1091 if ( xLayoutManager.is() )
1093 if ( aMultiTextWnd.GetNumLines() > 1)
1094 pParent->SetToolbarLayoutMode( TBX_LAYOUT_LOCKVERT );
1095 else
1096 pParent->SetToolbarLayoutMode( TBX_LAYOUT_NORMAL );
1097 xLayoutManager->lock();
1098 DataChangedEvent aFakeUpdate( DATACHANGED_SETTINGS, NULL, SETTINGS_STYLE );
1099 // this basically will trigger the reposititioning of the
1100 // items in the toolbar from ImplFormat ( which is controlled by
1101 // mnWinHeight ) which in turn is updated in ImplCalcItem which is
1102 // controlled by mbCalc. Additionally the ImplFormat above is
1103 // controlled via mbFormat. It seems the easiest way to get these
1104 // booleans set is to send in the fake event below.
1105 pParent->DataChanged( aFakeUpdate);
1106 // highest item in toolbar will have been calculated via the
1107 // event above. Call resize on InputBar to pick up the height
1108 // change
1109 pParent->Resize();
1110 // unlock relayouts the toolbars in the 4 quadrants
1111 xLayoutManager->unlock();
1116 IMPL_LINK_NOARG(ScInputBarGroup, Impl_ScrollHdl)
1118 aMultiTextWnd.DoScroll();
1119 return 0;
1122 void ScInputBarGroup::TextGrabFocus()
1124 aMultiTextWnd.TextGrabFocus();
1127 //========================================================================
1128 // ScMultiTextWnd
1129 //========================================================================
1131 ScMultiTextWnd::ScMultiTextWnd( ScInputBarGroup* pParen, ScTabViewShell* pViewSh )
1133 ScTextWnd( pParen, pViewSh ),
1134 mrGroupBar(* pParen ),
1135 mnLines( 1 ),
1136 mnLastExpandedLines( INPUTWIN_MULTILINES ),
1137 mbInvalidate( false )
1139 Size aBorder;
1140 aBorder = CalcWindowSize( aBorder);
1141 mnBorderHeight = aBorder.Height();
1144 ScMultiTextWnd::~ScMultiTextWnd()
1148 void ScMultiTextWnd::Paint( const Rectangle& rRect )
1150 EditView* pView = GetEditView();
1151 if ( pView )
1153 if ( mbInvalidate )
1155 pView->Invalidate();
1156 mbInvalidate = false;
1158 pEditView->Paint( rRect );
1162 EditView* ScMultiTextWnd::GetEditView()
1164 if ( !pEditView )
1165 InitEditEngine();
1166 return pEditView;
1169 long ScMultiTextWnd::GetPixelHeightForLines( long nLines )
1171 // add padding ( for the borders of the window )
1172 return ( nLines * LogicToPixel( Size( 0, GetTextHeight() ) ).Height() ) + mnBorderHeight;
1175 void ScMultiTextWnd::SetNumLines( long nLines )
1177 mnLines = nLines;
1178 if ( nLines > 1 )
1180 mnLastExpandedLines = nLines;
1181 Resize();
1185 void ScMultiTextWnd::Resize()
1187 // Only Height is recalculated here, Width is applied from
1188 // parent/container window
1189 Size aTextBoxSize = GetSizePixel();
1191 aTextBoxSize.Height() = GetPixelHeightForLines( mnLines );
1192 SetSizePixel( aTextBoxSize );
1194 if(pEditView)
1196 Size aOutputSize = GetOutputSizePixel();
1197 Rectangle aOutputArea = PixelToLogic( Rectangle( Point(), aOutputSize ));
1198 pEditView->SetOutputArea( aOutputArea );
1200 // Don't leave an empty area at the bottom if we can move the text down.
1201 long nMaxVisAreaTop = pEditEngine->GetTextHeight() - aOutputArea.GetHeight();
1202 if (pEditView->GetVisArea().Top() > nMaxVisAreaTop)
1204 pEditView->Scroll(0, pEditView->GetVisArea().Top() - nMaxVisAreaTop);
1207 pEditEngine->SetPaperSize( PixelToLogic( Size( aOutputSize.Width(), 10000 ) ) );
1210 SetScrollBarRange();
1213 IMPL_LINK(ScMultiTextWnd, ModifyHdl, EENotify*, pNotify)
1215 ScTextWnd::NotifyHdl( pNotify );
1216 return 0;
1219 IMPL_LINK(ScMultiTextWnd, NotifyHdl, EENotify*, pNotify)
1221 // need to process EE_NOTIFY_TEXTVIEWSCROLLED here
1222 // sometimes we don't seem to get EE_NOTIFY_TEXTVIEWSCROLLED e.g. when
1223 // we insert text at the beginning of the text so the cursor never moves
1224 // down to generate a scroll event
1226 if ( pNotify && ( pNotify->eNotificationType == EE_NOTIFY_TEXTVIEWSCROLLED
1227 || pNotify->eNotificationType == EE_NOTIFY_TEXTHEIGHTCHANGED ) )
1228 SetScrollBarRange();
1229 return 0;
1232 long ScMultiTextWnd::GetEditEngTxtHeight()
1234 return pEditView ? pEditView->GetEditEngine()->GetTextHeight() : 0;
1237 void ScMultiTextWnd::SetScrollBarRange()
1239 if ( pEditView )
1241 ScrollBar& rVBar = mrGroupBar.GetScrollBar();
1242 rVBar.SetRange( Range( 0, GetEditEngTxtHeight() ) );
1243 long currentDocPos = pEditView->GetVisArea().TopLeft().Y();
1244 rVBar.SetThumbPos( currentDocPos );
1248 void
1249 ScMultiTextWnd::DoScroll()
1251 if ( pEditView )
1253 ScrollBar& rVBar = mrGroupBar.GetScrollBar();
1254 long currentDocPos = pEditView->GetVisArea().TopLeft().Y();
1255 long nDiff = currentDocPos - rVBar.GetThumbPos();
1256 pEditView->Scroll( 0, nDiff );
1257 currentDocPos = pEditView->GetVisArea().TopLeft().Y();
1258 rVBar.SetThumbPos( currentDocPos );
1262 void ScMultiTextWnd::StartEditEngine()
1264 // Bei "eigener Modalitaet" (Doc-modale Dialoge) nicht aktivieren
1265 SfxObjectShell* pObjSh = SfxObjectShell::Current();
1266 if ( pObjSh && pObjSh->IsInModalMode() )
1267 return;
1269 if ( !pEditView || !pEditEngine )
1271 InitEditEngine();
1274 SC_MOD()->SetInputMode( SC_INPUT_TOP );
1276 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1277 if (pViewFrm)
1278 pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
1281 static void lcl_ExtendEditFontAttribs( SfxItemSet& rSet )
1283 const SfxPoolItem& rFontItem = rSet.Get( EE_CHAR_FONTINFO );
1284 rSet.Put( rFontItem, EE_CHAR_FONTINFO_CJK );
1285 rSet.Put( rFontItem, EE_CHAR_FONTINFO_CTL );
1286 const SfxPoolItem& rHeightItem = rSet.Get( EE_CHAR_FONTHEIGHT );
1287 rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CJK );
1288 rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CTL );
1289 const SfxPoolItem& rWeightItem = rSet.Get( EE_CHAR_WEIGHT );
1290 rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CJK );
1291 rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CTL );
1292 const SfxPoolItem& rItalicItem = rSet.Get( EE_CHAR_ITALIC );
1293 rSet.Put( rItalicItem, EE_CHAR_ITALIC_CJK );
1294 rSet.Put( rItalicItem, EE_CHAR_ITALIC_CTL );
1295 const SfxPoolItem& rLangItem = rSet.Get( EE_CHAR_LANGUAGE );
1296 rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CJK );
1297 rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CTL );
1300 static void lcl_ModifyRTLDefaults( SfxItemSet& rSet )
1302 rSet.Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) );
1304 // always using rtl writing direction would break formulas
1305 //rSet.Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) );
1307 // PaperSize width is limited to USHRT_MAX in RTL mode (because of EditEngine's
1308 // sal_uInt16 values in EditLine), so the text may be wrapped and line spacing must be
1309 // increased to not see the beginning of the next line.
1310 SvxLineSpacingItem aItem( SVX_LINESPACE_TWO_LINES, EE_PARA_SBL );
1311 aItem.SetPropLineSpace( 200 );
1312 rSet.Put( aItem );
1315 static void lcl_ModifyRTLVisArea( EditView* pEditView )
1317 Rectangle aVisArea = pEditView->GetVisArea();
1318 Size aPaper = pEditView->GetEditEngine()->GetPaperSize();
1319 long nDiff = aPaper.Width() - aVisArea.Right();
1320 aVisArea.Left() += nDiff;
1321 aVisArea.Right() += nDiff;
1322 pEditView->SetVisArea(aVisArea);
1326 void ScMultiTextWnd::InitEditEngine()
1328 ScFieldEditEngine* pNew;
1329 ScTabViewShell* pViewSh = GetViewShell();
1330 ScDocShell* pDocSh = NULL;
1331 if ( pViewSh )
1333 pDocSh = pViewSh->GetViewData()->GetDocShell();
1334 ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
1335 pNew = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
1337 else
1338 pNew = new ScFieldEditEngine(NULL, EditEngine::CreatePool(), NULL, true);
1339 pNew->SetExecuteURL( false );
1340 pEditEngine = pNew;
1342 Size barSize=GetSizePixel();
1343 pEditEngine->SetUpdateMode( false );
1344 pEditEngine->SetPaperSize( PixelToLogic(Size(barSize.Width(),10000)) );
1345 pEditEngine->SetWordDelimiters(
1346 ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1348 UpdateAutoCorrFlag();
1351 SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1352 pEditEngine->SetFontInfoInItemSet( *pSet, aTextFont );
1353 lcl_ExtendEditFontAttribs( *pSet );
1354 // turn off script spacing to match DrawText output
1355 pSet->Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) );
1356 if ( bIsRTL )
1357 lcl_ModifyRTLDefaults( *pSet );
1358 pEditEngine->SetDefaults( pSet );
1361 // Wenn in der Zelle URL-Felder enthalten sind, muessen die auch in
1362 // die Eingabezeile uebernommen werden, weil sonst die Positionen nicht stimmen.
1364 sal_Bool bFilled = false;
1365 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1366 if ( pHdl ) //! Testen, ob's der richtige InputHdl ist?
1367 bFilled = pHdl->GetTextAndFields( *pEditEngine );
1369 pEditEngine->SetUpdateMode( sal_True );
1371 // aString ist die Wahrheit...
1372 if (bFilled && pEditEngine->GetText() == aString)
1373 Invalidate(); // Repaint fuer (hinterlegte) Felder
1374 else
1375 pEditEngine->SetText(aString); // dann wenigstens den richtigen Text
1377 pEditView = new EditView( pEditEngine, this );
1378 pEditView->SetInsertMode(bIsInsertMode);
1380 // Text aus Clipboard wird als ASCII einzeilig uebernommen
1381 sal_uLong n = pEditView->GetControlWord();
1382 pEditView->SetControlWord( n | EV_CNTRL_SINGLELINEPASTE );
1384 pEditEngine->InsertView( pEditView, EE_APPEND );
1386 Resize();
1388 if ( bIsRTL )
1389 lcl_ModifyRTLVisArea( pEditView );
1391 pEditEngine->SetModifyHdl(LINK(this, ScMultiTextWnd, ModifyHdl));
1392 pEditEngine->SetNotifyHdl(LINK(this, ScMultiTextWnd, NotifyHdl));
1394 if (!maAccTextDatas.empty())
1395 maAccTextDatas.back()->StartEdit();
1397 // as long as EditEngine and DrawText sometimes differ for CTL text,
1398 // repaint now to have the EditEngine's version visible
1399 if (pDocSh)
1401 ScDocument* pDoc = pDocSh->GetDocument(); // any document
1402 sal_uInt8 nScript = pDoc->GetStringScriptType( aString );
1403 if ( nScript & SCRIPTTYPE_COMPLEX )
1404 Invalidate();
1408 void ScMultiTextWnd::StopEditEngine( sal_Bool bAll )
1410 if ( pEditEngine )
1411 pEditEngine->SetNotifyHdl(Link());
1412 ScTextWnd::StopEditEngine( bAll );
1415 void ScMultiTextWnd::SetTextString( const OUString& rNewString )
1417 // Ideally it would be best to create on demand the EditEngine/EditView here, but... for
1418 // the initialisation scenario where a cell is first clicked on we end up with the text in the
1419 // inputbar window scrolled to the bottom if we do that here ( because the tableview and topview
1420 // are synced I guess ).
1421 // should fix that I suppose :-/ need to look a bit further into that
1422 mbInvalidate = true; // ensure next Paint ( that uses editengine ) call will call Invalidate first
1423 ScTextWnd::SetTextString( rNewString );
1424 SetScrollBarRange();
1425 DoScroll();
1427 //========================================================================
1428 // ScTextWnd
1429 //========================================================================
1431 ScTextWnd::ScTextWnd( Window* pParent, ScTabViewShell* pViewSh )
1432 : ScTextWndBase ( pParent, WinBits(WB_HIDE | WB_BORDER) ),
1433 DragSourceHelper( this ),
1434 pEditEngine ( NULL ),
1435 pEditView ( NULL ),
1436 bIsInsertMode( sal_True ),
1437 bFormulaMode ( false ),
1438 bInputMode ( false ),
1439 mpViewShell(pViewSh)
1441 EnableRTL( false ); // EditEngine can't be used with VCL EnableRTL
1443 bIsRTL = GetSettings().GetLayoutRTL();
1445 // always use application font, so a font with cjk chars can be installed
1446 Font aAppFont = GetFont();
1447 aTextFont = aAppFont;
1448 aTextFont.SetSize( PixelToLogic( aAppFont.GetSize(), MAP_TWIP ) ); // AppFont ist in Pixeln
1450 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1452 Color aBgColor= rStyleSettings.GetWindowColor();
1453 Color aTxtColor= rStyleSettings.GetWindowTextColor();
1455 aTextFont.SetTransparent ( sal_True );
1456 aTextFont.SetFillColor ( aBgColor );
1457 //aTextFont.SetColor ( COL_FIELDTEXT );
1458 aTextFont.SetColor (aTxtColor);
1459 aTextFont.SetWeight ( WEIGHT_NORMAL );
1461 Size aSize(1,TBX_WINDOW_HEIGHT);
1462 Size aMinEditSize( Edit::GetMinimumEditSize() );
1463 if( aMinEditSize.Height() > aSize.Height() )
1464 aSize.Height() = aMinEditSize.Height();
1465 SetSizePixel ( aSize );
1466 SetBackground ( aBgColor );
1467 SetLineColor ( COL_BLACK );
1468 SetMapMode ( MAP_TWIP );
1469 SetPointer ( POINTER_TEXT );
1470 SetFont( aTextFont );
1473 ScTextWnd::~ScTextWnd()
1475 while (!maAccTextDatas.empty()) {
1476 maAccTextDatas.back()->Dispose();
1478 delete pEditView;
1479 delete pEditEngine;
1482 void ScTextWnd::Paint( const Rectangle& rRect )
1484 if (pEditView)
1485 pEditView->Paint( rRect );
1486 else
1488 SetFont( aTextFont );
1490 long nDiff = GetOutputSizePixel().Height()
1491 - LogicToPixel( Size( 0, GetTextHeight() ) ).Height();
1492 // if (nDiff<2) nDiff=2; // mind. 1 Pixel
1494 long nStartPos = 0;
1495 if ( bIsRTL )
1497 // right-align
1498 nStartPos += GetOutputSizePixel().Width() -
1499 LogicToPixel( Size( GetTextWidth( aString ), 0 ) ).Width();
1501 // LayoutMode isn't changed as long as ModifyRTLDefaults doesn't include SvxFrameDirectionItem
1504 DrawText( PixelToLogic( Point( nStartPos, nDiff/2 ) ), aString );
1508 void ScTextWnd::Resize()
1510 if (pEditView)
1512 Size aSize = GetOutputSizePixel();
1513 long nDiff = aSize.Height()
1514 - LogicToPixel( Size( 0, GetTextHeight() ) ).Height();
1516 pEditView->SetOutputArea(
1517 PixelToLogic( Rectangle( Point( 0, (nDiff > 0) ? nDiff/2 : 1 ),
1518 aSize ) ) );
1522 void ScTextWnd::MouseMove( const MouseEvent& rMEvt )
1524 if (pEditView)
1525 pEditView->MouseMove( rMEvt );
1528 void ScTextWnd::MouseButtonDown( const MouseEvent& rMEvt )
1530 if (!HasFocus())
1532 StartEditEngine();
1533 if ( SC_MOD()->IsEditMode() )
1534 GrabFocus();
1537 if (pEditView)
1539 pEditView->SetEditEngineUpdateMode( sal_True );
1540 pEditView->MouseButtonDown( rMEvt );
1544 void ScTextWnd::MouseButtonUp( const MouseEvent& rMEvt )
1546 if (pEditView)
1547 if (pEditView->MouseButtonUp( rMEvt ))
1549 if ( rMEvt.IsMiddle() &&
1550 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
1552 // EditView may have pasted from selection
1553 SC_MOD()->InputChanged( pEditView );
1555 else
1556 SC_MOD()->InputSelection( pEditView );
1560 void ScTextWnd::Command( const CommandEvent& rCEvt )
1562 bInputMode = sal_True;
1563 sal_uInt16 nCommand = rCEvt.GetCommand();
1564 if ( pEditView /* && nCommand == COMMAND_STARTDRAG */ )
1566 ScModule* pScMod = SC_MOD();
1567 ScTabViewShell* pStartViewSh = ScTabViewShell::GetActiveViewShell();
1569 // don't modify the font defaults here - the right defaults are
1570 // already set in StartEditEngine when the EditEngine is created
1572 // verhindern, dass die EditView beim View-Umschalten wegkommt
1573 pScMod->SetInEditCommand( true );
1574 pEditView->Command( rCEvt );
1575 pScMod->SetInEditCommand( false );
1577 // COMMAND_STARTDRAG heiss noch lange nicht, dass der Inhalt geaendert wurde
1578 // darum in dem Fall kein InputChanged
1579 //! erkennen, ob mit Move gedraggt wurde, oder Drag&Move irgendwie verbieten
1581 if ( nCommand == COMMAND_STARTDRAG )
1583 // ist auf eine andere View gedraggt worden?
1584 ScTabViewShell* pEndViewSh = ScTabViewShell::GetActiveViewShell();
1585 if ( pEndViewSh != pStartViewSh && pStartViewSh != NULL )
1587 ScViewData* pViewData = pStartViewSh->GetViewData();
1588 ScInputHandler* pHdl = pScMod->GetInputHdl( pStartViewSh );
1589 if ( pHdl && pViewData->HasEditView( pViewData->GetActivePart() ) )
1591 pHdl->CancelHandler();
1592 pViewData->GetView()->ShowCursor(); // fehlt bei KillEditView, weil nicht aktiv
1596 else if ( nCommand == COMMAND_CURSORPOS )
1598 // don't call InputChanged for COMMAND_CURSORPOS
1600 else if ( nCommand == COMMAND_INPUTLANGUAGECHANGE )
1602 // #i55929# Font and font size state depends on input language if nothing is selected,
1603 // so the slots have to be invalidated when the input language is changed.
1605 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1606 if (pViewFrm)
1608 SfxBindings& rBindings = pViewFrm->GetBindings();
1609 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
1610 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
1613 else if ( nCommand == COMMAND_WHEEL )
1615 //don't call InputChanged for COMMAND_WHEEL
1617 else
1618 SC_MOD()->InputChanged( pEditView );
1620 else
1621 Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern...
1623 bInputMode = false;
1626 void ScTextWnd::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
1628 if ( pEditView )
1630 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True );
1631 pEditView->Command( aDragEvent );
1633 // handling of d&d to different view (CancelHandler) can't be done here,
1634 // because the call returns before d&d is complete.
1638 void ScTextWnd::KeyInput(const KeyEvent& rKEvt)
1640 bInputMode = sal_True;
1641 if (!SC_MOD()->InputKeyEvent( rKEvt ))
1643 sal_Bool bUsed = false;
1644 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1645 if ( pViewSh )
1646 bUsed = pViewSh->SfxKeyInput(rKEvt); // nur Acceleratoren, keine Eingabe
1647 if (!bUsed)
1648 Window::KeyInput( rKEvt );
1650 bInputMode = false;
1653 void ScTextWnd::GetFocus()
1655 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1656 if ( pViewSh )
1657 pViewSh->SetFormShellAtTop( false ); // focus in input line -> FormShell no longer on top
1660 void ScTextWnd::LoseFocus()
1664 OUString ScTextWnd::GetText() const
1666 // ueberladen, um per Testtool an den Text heranzukommen
1668 if ( pEditEngine )
1669 return pEditEngine->GetText();
1670 else
1671 return GetTextString();
1674 void ScTextWnd::SetFormulaMode( sal_Bool bSet )
1676 if ( bSet != bFormulaMode )
1678 bFormulaMode = bSet;
1679 UpdateAutoCorrFlag();
1683 void ScTextWnd::UpdateAutoCorrFlag()
1685 if ( pEditEngine )
1687 sal_uLong nControl = pEditEngine->GetControlWord();
1688 sal_uLong nOld = nControl;
1689 if ( bFormulaMode )
1690 nControl &= ~EE_CNTRL_AUTOCORRECT; // keine Autokorrektur in Formeln
1691 else
1692 nControl |= EE_CNTRL_AUTOCORRECT; // sonst schon
1693 if ( nControl != nOld )
1694 pEditEngine->SetControlWord( nControl );
1698 ScTabViewShell* ScTextWnd::GetViewShell()
1700 return mpViewShell;
1703 void ScTextWnd::StartEditEngine()
1705 // Bei "eigener Modalitaet" (Doc-modale Dialoge) nicht aktivieren
1706 SfxObjectShell* pObjSh = SfxObjectShell::Current();
1707 if ( pObjSh && pObjSh->IsInModalMode() )
1708 return;
1710 if ( !pEditView || !pEditEngine )
1712 ScFieldEditEngine* pNew;
1713 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1714 if ( pViewSh )
1716 ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
1717 pNew = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
1719 else
1720 pNew = new ScFieldEditEngine(NULL, EditEngine::CreatePool(), NULL, true);
1721 pNew->SetExecuteURL( false );
1722 pEditEngine = pNew;
1724 pEditEngine->SetUpdateMode( false );
1725 pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
1726 pEditEngine->SetWordDelimiters(
1727 ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1729 UpdateAutoCorrFlag();
1732 SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1733 pEditEngine->SetFontInfoInItemSet( *pSet, aTextFont );
1734 lcl_ExtendEditFontAttribs( *pSet );
1735 // turn off script spacing to match DrawText output
1736 pSet->Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) );
1737 if ( bIsRTL )
1738 lcl_ModifyRTLDefaults( *pSet );
1739 pEditEngine->SetDefaults( pSet );
1742 // Wenn in der Zelle URL-Felder enthalten sind, muessen die auch in
1743 // die Eingabezeile uebernommen werden, weil sonst die Positionen nicht stimmen.
1745 sal_Bool bFilled = false;
1746 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1747 if ( pHdl ) //! Testen, ob's der richtige InputHdl ist?
1748 bFilled = pHdl->GetTextAndFields( *pEditEngine );
1750 pEditEngine->SetUpdateMode( sal_True );
1752 // aString ist die Wahrheit...
1753 if (bFilled && pEditEngine->GetText() == aString)
1754 Invalidate(); // Repaint fuer (hinterlegte) Felder
1755 else
1756 pEditEngine->SetText(aString); // dann wenigstens den richtigen Text
1758 pEditView = new EditView( pEditEngine, this );
1759 pEditView->SetInsertMode(bIsInsertMode);
1761 // Text aus Clipboard wird als ASCII einzeilig uebernommen
1762 sal_uLong n = pEditView->GetControlWord();
1763 pEditView->SetControlWord( n | EV_CNTRL_SINGLELINEPASTE );
1765 pEditEngine->InsertView( pEditView, EE_APPEND );
1767 Resize();
1769 if ( bIsRTL )
1770 lcl_ModifyRTLVisArea( pEditView );
1772 pEditEngine->SetModifyHdl(LINK(this, ScTextWnd, NotifyHdl));
1774 if (!maAccTextDatas.empty())
1775 maAccTextDatas.back()->StartEdit();
1777 // as long as EditEngine and DrawText sometimes differ for CTL text,
1778 // repaint now to have the EditEngine's version visible
1779 // SfxObjectShell* pObjSh = SfxObjectShell::Current();
1780 if ( pObjSh && pObjSh->ISA(ScDocShell) )
1782 ScDocument* pDoc = ((ScDocShell*)pObjSh)->GetDocument(); // any document
1783 sal_uInt8 nScript = pDoc->GetStringScriptType( aString );
1784 if ( nScript & SCRIPTTYPE_COMPLEX )
1785 Invalidate();
1789 SC_MOD()->SetInputMode( SC_INPUT_TOP );
1791 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1792 if (pViewFrm)
1793 pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
1796 IMPL_LINK_NOARG(ScTextWnd, NotifyHdl)
1798 if (pEditView && !bInputMode)
1800 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1802 // Use the InputHandler's InOwnChange flag to prevent calling InputChanged
1803 // while an InputHandler method is modifying the EditEngine content
1805 if ( pHdl && !pHdl->IsInOwnChange() )
1806 pHdl->InputChanged( pEditView, sal_True ); // #i20282# InputChanged must know if called from modify handler
1809 return 0;
1812 void ScTextWnd::StopEditEngine( sal_Bool bAll )
1814 if (pEditView)
1816 if (!maAccTextDatas.empty())
1817 maAccTextDatas.back()->EndEdit();
1819 ScModule* pScMod = SC_MOD();
1821 if (!bAll)
1822 pScMod->InputSelection( pEditView );
1823 aString = pEditEngine->GetText();
1824 bIsInsertMode = pEditView->IsInsertMode();
1825 sal_Bool bSelection = pEditView->HasSelection();
1826 pEditEngine->SetModifyHdl(Link());
1827 DELETEZ(pEditView);
1828 DELETEZ(pEditEngine);
1830 if ( pScMod->IsEditMode() && !bAll )
1831 pScMod->SetInputMode(SC_INPUT_TABLE);
1833 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1834 if (pViewFrm)
1835 pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
1837 if (bSelection)
1838 Invalidate(); // damit Selektion nicht stehenbleibt
1842 static sal_Int32 findFirstNonMatchingChar(const OUString& rStr1, const OUString rStr2)
1844 // Search the string for unmatching chars
1845 const sal_Unicode* pStr1 = rStr1.getStr();
1846 const sal_Unicode* pStr2 = rStr2.getStr();
1847 sal_Int32 i = 0;
1848 while ( i < rStr1.getLength() )
1850 // Abort on the first unmatching char
1851 if ( *pStr1 != *pStr2 )
1852 return i;
1853 ++pStr1,
1854 ++pStr2,
1855 ++i;
1858 return i;
1861 void ScTextWnd::SetTextString( const OUString& rNewString )
1863 if ( rNewString != aString )
1865 bInputMode = sal_True;
1867 // Position der Aenderung suchen, nur Rest painten
1869 if (!pEditEngine)
1871 sal_Bool bPaintAll;
1872 if ( bIsRTL )
1873 bPaintAll = sal_True;
1874 else
1876 // test if CTL script type is involved
1877 sal_uInt8 nOldScript = 0;
1878 sal_uInt8 nNewScript = 0;
1879 SfxObjectShell* pObjSh = SfxObjectShell::Current();
1880 if ( pObjSh && pObjSh->ISA(ScDocShell) )
1882 // any document can be used (used only for its break iterator)
1883 ScDocument* pDoc = ((ScDocShell*)pObjSh)->GetDocument();
1884 nOldScript = pDoc->GetStringScriptType( aString );
1885 nNewScript = pDoc->GetStringScriptType( rNewString );
1887 bPaintAll = ( nOldScript & SCRIPTTYPE_COMPLEX ) || ( nNewScript & SCRIPTTYPE_COMPLEX );
1890 if ( bPaintAll )
1892 // if CTL is involved, the whole text has to be redrawn
1893 Invalidate();
1895 else
1897 long nTextSize = 0;
1898 sal_Int32 nDifPos;
1899 if (rNewString.getLength() > aString.getLength())
1900 nDifPos = findFirstNonMatchingChar(rNewString, aString);
1901 else
1902 nDifPos = findFirstNonMatchingChar(aString, rNewString);
1904 long nSize1 = GetTextWidth(aString);
1905 long nSize2 = GetTextWidth(rNewString);
1906 if ( nSize1>0 && nSize2>0 )
1907 nTextSize = std::max( nSize1, nSize2 );
1908 else
1909 nTextSize = GetOutputSize().Width(); // Ueberlauf
1911 Point aLogicStart = PixelToLogic(Point(0,0));
1912 long nStartPos = aLogicStart.X();
1913 long nInvPos = nStartPos;
1914 if (nDifPos)
1915 nInvPos += GetTextWidth(aString,0,nDifPos);
1917 sal_uInt16 nFlags = 0;
1918 if ( nDifPos == aString.getLength() ) // only new characters appended
1919 nFlags = INVALIDATE_NOERASE; // then background is already clear
1920 Invalidate( Rectangle( nInvPos, 0,
1921 nStartPos+nTextSize, GetOutputSize().Height()-1 ),
1922 nFlags );
1925 else
1927 pEditEngine->SetText(rNewString);
1930 aString = rNewString;
1932 if (!maAccTextDatas.empty())
1933 maAccTextDatas.back()->TextChanged();
1935 bInputMode = false;
1939 const OUString& ScTextWnd::GetTextString() const
1941 return aString;
1944 sal_Bool ScTextWnd::IsInputActive()
1946 return HasFocus();
1949 EditView* ScTextWnd::GetEditView()
1951 return pEditView;
1954 void ScTextWnd::MakeDialogEditView()
1956 if ( pEditView ) return;
1958 ScFieldEditEngine* pNew;
1959 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1960 if ( pViewSh )
1962 ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
1963 pNew = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
1965 else
1966 pNew = new ScFieldEditEngine(NULL, EditEngine::CreatePool(), NULL, true);
1967 pNew->SetExecuteURL( false );
1968 pEditEngine = pNew;
1970 pEditEngine->SetUpdateMode( false );
1971 pEditEngine->SetWordDelimiters( pEditEngine->GetWordDelimiters() + "=" );
1972 pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
1974 SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1975 pEditEngine->SetFontInfoInItemSet( *pSet, aTextFont );
1976 lcl_ExtendEditFontAttribs( *pSet );
1977 if ( bIsRTL )
1978 lcl_ModifyRTLDefaults( *pSet );
1979 pEditEngine->SetDefaults( pSet );
1980 pEditEngine->SetUpdateMode( sal_True );
1982 pEditView = new EditView( pEditEngine, this );
1983 pEditEngine->InsertView( pEditView, EE_APPEND );
1985 Resize();
1987 if ( bIsRTL )
1988 lcl_ModifyRTLVisArea( pEditView );
1990 if (!maAccTextDatas.empty())
1991 maAccTextDatas.back()->StartEdit();
1994 void ScTextWnd::ImplInitSettings()
1996 bIsRTL = GetSettings().GetLayoutRTL();
1998 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2000 Color aBgColor= rStyleSettings.GetWindowColor();
2001 Color aTxtColor= rStyleSettings.GetWindowTextColor();
2003 aTextFont.SetFillColor ( aBgColor );
2004 aTextFont.SetColor (aTxtColor);
2005 SetBackground ( aBgColor );
2006 Invalidate();
2009 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ScTextWnd::CreateAccessible()
2011 return new ScAccessibleEditObject(GetAccessibleParentWindow()->GetAccessible(), NULL, this,
2012 OUString(ScResId(STR_ACC_EDITLINE_NAME)),
2013 OUString(ScResId(STR_ACC_EDITLINE_DESCR)), ScAccessibleEditObject::EditLine);
2016 void ScTextWnd::InsertAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
2018 OSL_ENSURE( ::std::find( maAccTextDatas.begin(), maAccTextDatas.end(), &rTextData ) == maAccTextDatas.end(),
2019 "ScTextWnd::InsertAccessibleTextData - passed object already registered" );
2020 maAccTextDatas.push_back( &rTextData );
2023 void ScTextWnd::RemoveAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
2025 AccTextDataVector::iterator aEnd = maAccTextDatas.end();
2026 AccTextDataVector::iterator aIt = ::std::find( maAccTextDatas.begin(), aEnd, &rTextData );
2027 OSL_ENSURE( aIt != aEnd, "ScTextWnd::RemoveAccessibleTextData - passed object not registered" );
2028 if( aIt != aEnd )
2029 maAccTextDatas.erase( aIt );
2032 // -----------------------------------------------------------------------
2034 void ScTextWnd::DataChanged( const DataChangedEvent& rDCEvt )
2036 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
2037 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
2039 ImplInitSettings();
2040 Invalidate();
2042 else
2043 Window::DataChanged( rDCEvt );
2046 void ScTextWnd::TextGrabFocus()
2048 GrabFocus();
2051 //========================================================================
2052 // Positionsfenster
2053 //========================================================================
2055 ScPosWnd::ScPosWnd( Window* pParent ) :
2056 ComboBox ( pParent, WinBits(WB_HIDE | WB_DROPDOWN) ),
2057 pAccel ( NULL ),
2058 nTipVisible ( 0 ),
2059 bFormulaMode( false )
2061 Size aSize( GetTextWidth( OUString("GW99999:GW99999") ),
2062 GetTextHeight() );
2063 aSize.Width() += 25; // ??
2064 aSize.Height() = CalcWindowSizePixel(11); // Funktionen: 10 MRU + "andere..."
2065 SetSizePixel( aSize );
2067 FillRangeNames();
2069 StartListening( *SFX_APP() ); // fuer Navigator-Bereichsnamen-Updates
2072 ScPosWnd::~ScPosWnd()
2074 EndListening( *SFX_APP() );
2076 HideTip();
2078 delete pAccel;
2081 void ScPosWnd::SetFormulaMode( sal_Bool bSet )
2083 if ( bSet != bFormulaMode )
2085 bFormulaMode = bSet;
2087 if ( bSet )
2088 FillFunctions();
2089 else
2090 FillRangeNames();
2092 HideTip();
2096 void ScPosWnd::SetPos( const OUString& rPosStr )
2098 if ( aPosStr != rPosStr )
2100 aPosStr = rPosStr;
2101 SetText(aPosStr);
2105 namespace {
2107 OUString createLocalRangeName(const OUString& rName, const OUString& rTableName)
2109 OUStringBuffer aString (rName);
2110 aString.append(OUString(" ("));
2111 aString.append(rTableName);
2112 aString.append(OUString(")"));
2113 return aString.makeStringAndClear();
2118 void ScPosWnd::FillRangeNames()
2120 Clear();
2122 SfxObjectShell* pObjSh = SfxObjectShell::Current();
2123 if ( pObjSh && pObjSh->ISA(ScDocShell) )
2125 ScDocument* pDoc = ((ScDocShell*)pObjSh)->GetDocument();
2127 InsertEntry(ScGlobal::GetRscString( STR_MANAGE_NAMES ));
2128 SetSeparatorPos(0);
2130 ScRange aDummy;
2131 std::set<OUString> aSet;
2132 ScRangeName* pRangeNames = pDoc->GetRangeName();
2133 if (!pRangeNames->empty())
2135 ScRangeName::const_iterator itrBeg = pRangeNames->begin(), itrEnd = pRangeNames->end();
2136 for (ScRangeName::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
2138 if (itr->second->IsValidReference(aDummy))
2139 aSet.insert(itr->second->GetName());
2142 for (SCTAB i = 0; i < pDoc->GetTableCount(); ++i)
2144 ScRangeName* pLocalRangeName = pDoc->GetRangeName(i);
2145 if (pLocalRangeName && !pLocalRangeName->empty())
2147 OUString aTableName;
2148 pDoc->GetName(i, aTableName);
2149 for (ScRangeName::const_iterator itr = pLocalRangeName->begin(); itr != pLocalRangeName->end(); ++itr)
2151 if (itr->second->IsValidReference(aDummy))
2152 aSet.insert(createLocalRangeName(itr->second->GetName(), aTableName));
2157 if (!aSet.empty())
2159 for (std::set<OUString>::iterator itr = aSet.begin();
2160 itr != aSet.end(); ++itr)
2162 InsertEntry(*itr);
2166 SetText(aPosStr);
2169 void ScPosWnd::FillFunctions()
2171 Clear();
2173 OUString aFirstName;
2174 const ScAppOptions& rOpt = SC_MOD()->GetAppOptions();
2175 sal_uInt16 nMRUCount = rOpt.GetLRUFuncListCount();
2176 const sal_uInt16* pMRUList = rOpt.GetLRUFuncList();
2177 if (pMRUList)
2179 const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
2180 sal_uLong nListCount = pFuncList->GetCount();
2181 for (sal_uInt16 i=0; i<nMRUCount; i++)
2183 sal_uInt16 nId = pMRUList[i];
2184 for (sal_uLong j=0; j<nListCount; j++)
2186 const ScFuncDesc* pDesc = pFuncList->GetFunction( j );
2187 if ( pDesc->nFIndex == nId && pDesc->pFuncName )
2189 InsertEntry( *pDesc->pFuncName );
2190 if (aFirstName.isEmpty())
2191 aFirstName = *pDesc->pFuncName;
2192 break; // nicht weitersuchen
2198 //! Eintrag "Andere..." fuer Funktions-Autopilot wieder aufnehmen,
2199 //! wenn der Funktions-Autopilot mit dem bisher eingegebenen Text arbeiten kann!
2201 // InsertEntry( ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) );
2203 SetText(aFirstName);
2206 void ScPosWnd::Notify( SfxBroadcaster&, const SfxHint& rHint )
2208 if ( !bFormulaMode )
2210 // muss die Liste der Bereichsnamen updgedated werden?
2212 if ( rHint.ISA(SfxSimpleHint) )
2214 sal_uLong nHintId = ((SfxSimpleHint&)rHint).GetId();
2215 if ( nHintId == SC_HINT_AREAS_CHANGED || nHintId == SC_HINT_NAVIGATOR_UPDATEALL)
2216 FillRangeNames();
2218 else if ( rHint.ISA(SfxEventHint) )
2220 sal_uLong nEventId = ((SfxEventHint&)rHint).GetEventId();
2221 if ( nEventId == SFX_EVENT_ACTIVATEDOC )
2222 FillRangeNames();
2227 void ScPosWnd::HideTip()
2229 if ( nTipVisible )
2231 Help::HideTip( nTipVisible );
2232 nTipVisible = 0;
2236 static ScNameInputType lcl_GetInputType( const OUString& rText )
2238 ScNameInputType eRet = SC_NAME_INPUT_BAD_NAME; // the more general error
2240 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2241 if ( pViewSh )
2243 ScViewData* pViewData = pViewSh->GetViewData();
2244 ScDocument* pDoc = pViewData->GetDocument();
2245 SCTAB nTab = pViewData->GetTabNo();
2246 formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
2248 // test in same order as in SID_CURRENTCELL execute
2250 ScRange aRange;
2251 ScAddress aAddress;
2252 ScRangeUtil aRangeUtil;
2253 SCTAB nNameTab;
2254 sal_Int32 nNumeric;
2256 if (rText == ScGlobal::GetRscString(STR_MANAGE_NAMES))
2257 eRet = SC_MANAGE_NAMES;
2258 else if ( aRange.Parse( rText, pDoc, eConv ) & SCA_VALID )
2259 eRet = SC_NAME_INPUT_RANGE;
2260 else if ( aAddress.Parse( rText, pDoc, eConv ) & SCA_VALID )
2261 eRet = SC_NAME_INPUT_CELL;
2262 else if ( aRangeUtil.MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_NAMES, eConv ) )
2263 eRet = SC_NAME_INPUT_NAMEDRANGE;
2264 else if ( aRangeUtil.MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_DBASE, eConv ) )
2265 eRet = SC_NAME_INPUT_DATABASE;
2266 else if ( comphelper::string::isdigitAsciiString( rText ) &&
2267 ( nNumeric = rText.toInt32() ) > 0 && nNumeric <= MAXROW+1 )
2268 eRet = SC_NAME_INPUT_ROW;
2269 else if ( pDoc->GetTable( rText, nNameTab ) )
2270 eRet = SC_NAME_INPUT_SHEET;
2271 else if ( ScRangeData::IsNameValid( rText, pDoc ) ) // nothing found, create new range?
2273 if ( pViewData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
2274 eRet = SC_NAME_INPUT_DEFINE;
2275 else
2276 eRet = SC_NAME_INPUT_BAD_SELECTION;
2278 else
2279 eRet = SC_NAME_INPUT_BAD_NAME;
2282 return eRet;
2285 void ScPosWnd::Modify()
2287 ComboBox::Modify();
2289 HideTip();
2291 if ( !IsTravelSelect() && !bFormulaMode )
2293 // determine the action that would be taken for the current input
2295 ScNameInputType eType = lcl_GetInputType( GetText() ); // uses current view
2296 sal_uInt16 nStrId = 0;
2297 switch ( eType )
2299 case SC_NAME_INPUT_CELL:
2300 nStrId = STR_NAME_INPUT_CELL;
2301 break;
2302 case SC_NAME_INPUT_RANGE:
2303 case SC_NAME_INPUT_NAMEDRANGE:
2304 nStrId = STR_NAME_INPUT_RANGE; // named range or range reference
2305 break;
2306 case SC_NAME_INPUT_DATABASE:
2307 nStrId = STR_NAME_INPUT_DBRANGE;
2308 break;
2309 case SC_NAME_INPUT_ROW:
2310 nStrId = STR_NAME_INPUT_ROW;
2311 break;
2312 case SC_NAME_INPUT_SHEET:
2313 nStrId = STR_NAME_INPUT_SHEET;
2314 break;
2315 case SC_NAME_INPUT_DEFINE:
2316 nStrId = STR_NAME_INPUT_DEFINE;
2317 break;
2318 default:
2319 // other cases (error): no tip help
2320 break;
2323 if ( nStrId )
2325 // show the help tip at the text cursor position
2327 Window* pWin = GetSubEdit();
2328 if (!pWin)
2329 pWin = this;
2330 Point aPos;
2331 Cursor* pCur = pWin->GetCursor();
2332 if (pCur)
2333 aPos = pWin->LogicToPixel( pCur->GetPos() );
2334 aPos = pWin->OutputToScreenPixel( aPos );
2335 Rectangle aRect( aPos, aPos );
2337 OUString aText = ScGlobal::GetRscString( nStrId );
2338 sal_uInt16 nAlign = QUICKHELP_LEFT|QUICKHELP_BOTTOM;
2339 nTipVisible = Help::ShowTip(pWin, aRect, aText, nAlign);
2344 void ScPosWnd::Select()
2346 ComboBox::Select(); // in VCL gibt GetText() erst danach den ausgewaehlten Eintrag
2348 HideTip();
2350 if (!IsTravelSelect())
2351 DoEnter();
2354 void ScPosWnd::DoEnter()
2356 OUString aText = GetText();
2357 if ( !aText.isEmpty() )
2359 if ( bFormulaMode )
2361 ScModule* pScMod = SC_MOD();
2362 if ( aText == ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) )
2364 // Funktions-Autopilot
2365 //! mit dem bisher eingegebenen Text weiterarbeiten !!!
2367 //! new method at ScModule to query if function autopilot is open
2368 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
2369 if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
2370 pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
2371 SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD );
2373 else
2375 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
2376 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
2377 if (pHdl)
2378 pHdl->InsertFunction( aText );
2381 else
2383 // depending on the input, select something or create a new named range
2385 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2386 if ( pViewSh )
2388 ScViewData* pViewData = pViewSh->GetViewData();
2389 ScDocShell* pDocShell = pViewData->GetDocShell();
2390 ScDocument* pDoc = pDocShell->GetDocument();
2392 ScNameInputType eType = lcl_GetInputType( aText );
2393 if ( eType == SC_NAME_INPUT_BAD_NAME || eType == SC_NAME_INPUT_BAD_SELECTION )
2395 sal_uInt16 nId = ( eType == SC_NAME_INPUT_BAD_NAME ) ? STR_NAME_ERROR_NAME : STR_NAME_ERROR_SELECTION;
2396 pViewSh->ErrorMessage( nId );
2398 else if ( eType == SC_NAME_INPUT_DEFINE )
2400 ScRangeName* pNames = pDoc->GetRangeName();
2401 ScRange aSelection;
2402 if ( pNames && !pNames->findByUpperName(ScGlobal::pCharClass->uppercase(aText)) &&
2403 (pViewData->GetSimpleArea( aSelection ) == SC_MARK_SIMPLE) )
2405 ScRangeName aNewRanges( *pNames );
2406 ScAddress aCursor( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
2407 OUString aContent(aSelection.Format(SCR_ABS_3D, pDoc, pDoc->GetAddressConvention()));
2408 ScRangeData* pNew = new ScRangeData( pDoc, aText, aContent, aCursor );
2409 if ( aNewRanges.insert(pNew) )
2411 pDocShell->GetDocFunc().ModifyRangeNames( aNewRanges );
2412 pViewSh->UpdateInputHandler(true);
2416 else if (eType == SC_MANAGE_NAMES)
2418 sal_uInt16 nId = ScNameDlgWrapper::GetChildWindowId();
2419 SfxViewFrame* pViewFrm = pViewSh->GetViewFrame();
2420 SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId );
2422 SC_MOD()->SetRefDialog( nId, pWnd ? false : sal_True );
2424 else
2426 // for all selection types, excecute the SID_CURRENTCELL slot.
2427 if (eType == SC_NAME_INPUT_CELL || eType == SC_NAME_INPUT_RANGE)
2429 // Note that SID_CURRENTCELL always expects address to
2430 // be in Calc A1 format. Convert the text.
2431 ScRange aRange(0,0,pViewData->GetTabNo());
2432 aRange.ParseAny(aText, pDoc, pDoc->GetAddressConvention());
2433 aText = aRange.Format(SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO);
2436 SfxStringItem aPosItem( SID_CURRENTCELL, aText );
2437 SfxBoolItem aUnmarkItem( FN_PARAM_1, sal_True ); // remove existing selection
2439 pViewSh->GetViewData()->GetDispatcher().Execute( SID_CURRENTCELL,
2440 SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD,
2441 &aPosItem, &aUnmarkItem, 0L );
2446 else
2447 SetText( aPosStr );
2449 ReleaseFocus_Impl();
2452 long ScPosWnd::Notify( NotifyEvent& rNEvt )
2454 long nHandled = 0;
2456 if ( rNEvt.GetType() == EVENT_KEYINPUT )
2458 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
2460 switch ( pKEvt->GetKeyCode().GetCode() )
2462 case KEY_RETURN:
2463 DoEnter();
2464 nHandled = 1;
2465 break;
2467 case KEY_ESCAPE:
2468 if (nTipVisible)
2470 // escape when the tip help is shown: only hide the tip
2471 HideTip();
2473 else
2475 if (!bFormulaMode)
2476 SetText( aPosStr );
2477 ReleaseFocus_Impl();
2479 nHandled = 1;
2480 break;
2484 if ( !nHandled )
2485 nHandled = ComboBox::Notify( rNEvt );
2487 if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2488 HideTip();
2490 return nHandled;
2493 void ScPosWnd::ReleaseFocus_Impl()
2495 HideTip();
2497 SfxViewShell* pCurSh = SfxViewShell::Current();
2498 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( PTR_CAST( ScTabViewShell, pCurSh ) );
2499 if ( pHdl && pHdl->IsTopMode() )
2501 // Focus wieder in die Eingabezeile?
2503 ScInputWindow* pInputWin = pHdl->GetInputWindow();
2504 if (pInputWin)
2506 pInputWin->TextGrabFocus();
2507 return;
2511 // Focus auf die aktive View
2513 if ( pCurSh )
2515 Window* pShellWnd = pCurSh->GetWindow();
2517 if ( pShellWnd )
2518 pShellWnd->GrabFocus();
2527 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */