fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / app / inputwin.cxx
blobb3776fd30e8a6627b9daea4532fdb0aea8e1ff86
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <algorithm>
22 #include "scitems.hxx"
23 #include <editeng/eeitem.hxx>
25 #include <sfx2/app.hxx>
26 #include <editeng/adjustitem.hxx>
27 #include <editeng/editview.hxx>
28 #include <editeng/editstat.hxx>
29 #include <editeng/frmdiritem.hxx>
30 #include <editeng/lspcitem.hxx>
31 #include <sfx2/bindings.hxx>
32 #include <sfx2/viewfrm.hxx>
33 #include <sfx2/dispatch.hxx>
34 #include <sfx2/event.hxx>
35 #include <sfx2/imgmgr.hxx>
36 #include <stdlib.h>
37 #include <editeng/scriptspaceitem.hxx>
38 #include <editeng/scripttypeitem.hxx>
39 #include <vcl/cursor.hxx>
40 #include <vcl/help.hxx>
41 #include <vcl/settings.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 // Should be more than enough!
77 #define TBX_WINDOW_HEIGHT 22 // in pixel - TODO: The same on all systems?
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;
93 enum ScNameInputType
95 SC_NAME_INPUT_CELL,
96 SC_NAME_INPUT_RANGE,
97 SC_NAME_INPUT_NAMEDRANGE,
98 SC_NAME_INPUT_DATABASE,
99 SC_NAME_INPUT_ROW,
100 SC_NAME_INPUT_SHEET,
101 SC_NAME_INPUT_DEFINE,
102 SC_NAME_INPUT_BAD_NAME,
103 SC_NAME_INPUT_BAD_SELECTION,
104 SC_MANAGE_NAMES
107 ScTextWndBase::ScTextWndBase( vcl::Window* pParent, WinBits nStyle )
108 : Window ( pParent, nStyle )
110 if ( IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) )
112 SetType( WINDOW_CALCINPUTLINE );
113 SetBorderStyle( WindowBorderStyle::NWF );
117 // class ScInputWindowWrapper
119 SFX_IMPL_CHILDWINDOW_WITHID(ScInputWindowWrapper,FID_INPUTLINE_STATUS)
121 ScInputWindowWrapper::ScInputWindowWrapper( vcl::Window* pParentP,
122 sal_uInt16 nId,
123 SfxBindings* pBindings,
124 SfxChildWinInfo* /* pInfo */ )
125 : SfxChildWindow( pParentP, nId )
127 VclPtr<ScInputWindow> pWin=VclPtr<ScInputWindow>::Create( pParentP, pBindings );
128 pWindow = pWin;
130 pWin->Show();
132 pWin->SetSizePixel( pWin->CalcWindowSizePixel() );
134 eChildAlignment = SfxChildAlignment::LOWESTTOP;
135 pBindings->Invalidate( FID_TOGGLEINPUTLINE );
139 * GetInfo is disposed of if there's a SFX_IMPL_TOOLBOX!
141 SfxChildWinInfo ScInputWindowWrapper::GetInfo() const
143 SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
144 return aInfo;
147 #define IMAGE(id) pImgMgr->SeekImage(id)
148 static inline bool lcl_isExperimentalMode()
150 // make inputbar feature on by default, leave the switch for the
151 // moment in case we need to back it out easily
152 return true;
155 // class ScInputWindow
157 static VclPtr<ScTextWndBase> lcl_chooseRuntimeImpl( vcl::Window* pParent, SfxBindings* pBind )
159 ScTabViewShell* pViewSh = NULL;
160 SfxDispatcher* pDisp = pBind->GetDispatcher();
161 if ( pDisp )
163 SfxViewFrame* pViewFrm = pDisp->GetFrame();
164 if ( pViewFrm )
165 pViewSh = PTR_CAST( ScTabViewShell, pViewFrm->GetViewShell() );
168 if ( !lcl_isExperimentalMode() )
169 return VclPtr<ScTextWnd>::Create( pParent, pViewSh );
170 return VclPtr<ScInputBarGroup>::Create( pParent, pViewSh );
173 ScInputWindow::ScInputWindow( vcl::Window* pParent, SfxBindings* pBind ) :
174 // With WB_CLIPCHILDREN otherwise we get flickering
175 ToolBox ( pParent, WinBits(WB_CLIPCHILDREN) ),
176 aWndPos ( VclPtr<ScPosWnd>::Create(this) ),
177 pRuntimeWindow ( lcl_chooseRuntimeImpl( this, pBind ) ),
178 aTextWindow ( *pRuntimeWindow ),
179 pInputHdl ( NULL ),
180 aTextOk ( ScResId( SCSTR_QHELP_BTNOK ) ), // Not always new as a Resource
181 aTextCancel ( ScResId( SCSTR_QHELP_BTNCANCEL ) ),
182 aTextSum ( ScResId( SCSTR_QHELP_BTNSUM ) ),
183 aTextEqual ( ScResId( SCSTR_QHELP_BTNEQUAL ) ),
184 mnMaxY (0),
185 bIsOkCancelMode ( false ),
186 bInResize ( false ),
187 mbIsMultiLine ( lcl_isExperimentalMode() )
189 ScModule* pScMod = SC_MOD();
190 SfxImageManager* pImgMgr = SfxImageManager::GetImageManager(*pScMod);
192 // #i73615# don't rely on SfxViewShell::Current while constructing the input line
193 // (also for GetInputHdl below)
194 ScTabViewShell* pViewSh = NULL;
195 SfxDispatcher* pDisp = pBind->GetDispatcher();
196 if ( pDisp )
198 SfxViewFrame* pViewFrm = pDisp->GetFrame();
199 if ( pViewFrm )
200 pViewSh = PTR_CAST( ScTabViewShell, pViewFrm->GetViewShell() );
202 OSL_ENSURE( pViewSh, "no view shell for input window" );
204 // Position window, 3 buttons, input window
205 InsertWindow (1, aWndPos.get(), ToolBoxItemBits::NONE, 0);
206 InsertSeparator (1);
207 InsertItem (SID_INPUT_FUNCTION, IMAGE(SID_INPUT_FUNCTION), ToolBoxItemBits::NONE, 2);
208 InsertItem (SID_INPUT_SUM, IMAGE(SID_INPUT_SUM), ToolBoxItemBits::NONE, 3);
209 InsertItem (SID_INPUT_EQUAL, IMAGE(SID_INPUT_EQUAL), ToolBoxItemBits::NONE, 4);
210 InsertSeparator (5);
211 InsertWindow (7, &aTextWindow, ToolBoxItemBits::NONE, 6);
213 aWndPos ->SetQuickHelpText(ScResId(SCSTR_QHELP_POSWND));
214 aWndPos ->SetHelpId (HID_INSWIN_POS);
215 aTextWindow.SetQuickHelpText(ScResId(SCSTR_QHELP_INPUTWND));
216 aTextWindow.SetHelpId (HID_INSWIN_INPUT);
218 // No SetHelpText: the helptexts come from the Help
219 SetItemText (SID_INPUT_FUNCTION, ScResId(SCSTR_QHELP_BTNCALC));
220 SetHelpId (SID_INPUT_FUNCTION, HID_INSWIN_CALC);
222 SetItemText (SID_INPUT_SUM, aTextSum);
223 SetHelpId (SID_INPUT_SUM, HID_INSWIN_SUMME);
225 SetItemText (SID_INPUT_EQUAL, aTextEqual);
226 SetHelpId (SID_INPUT_EQUAL, HID_INSWIN_FUNC);
228 SetHelpId( HID_SC_INPUTWIN ); // For the whole input row
230 aWndPos ->Show();
231 aTextWindow.Show();
233 pInputHdl = SC_MOD()->GetInputHdl( pViewSh, false ); // use own handler even if ref-handler is set
234 if (pInputHdl)
235 pInputHdl->SetInputWindow( this );
237 if (pInputHdl && !pInputHdl->GetFormString().isEmpty())
239 // Switch over while the Function AutoPilot is active
240 // -> show content of the Function AutoPilot again
241 // Also show selection (remember at the InputHdl)
242 aTextWindow.SetTextString( pInputHdl->GetFormString() );
244 else if (pInputHdl && pInputHdl->IsInputMode())
246 // If the input row was hidden while editing (e.g. when editing a formula
247 // and then switching to another document or the help), display the text
248 // we just edited from the InputHandler
249 aTextWindow.SetTextString( pInputHdl->GetEditString() ); // Dispaly text
250 if ( pInputHdl->IsTopMode() )
251 pInputHdl->SetMode( SC_INPUT_TABLE ); // Focus ends up at the bottom anyways
253 else if (pViewSh)
254 pViewSh->UpdateInputHandler(true); // Absolutely necessary update
256 pImgMgr->RegisterToolBox(this);
257 SetAccessibleName(ScResId(STR_ACC_TOOLBAR_FORMULA));
260 ScInputWindow::~ScInputWindow()
262 disposeOnce();
265 void ScInputWindow::dispose()
267 bool bDown = ( ScGlobal::pSysLocale == NULL ); // after Clear?
269 // if any view's input handler has a pointer to this input window, reset it
270 // (may be several ones, #74522#)
271 // member pInputHdl is not used here
273 if ( !bDown )
275 TypeId aScType = TYPE(ScTabViewShell);
276 SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
277 while ( pSh )
279 ScInputHandler* pHdl = static_cast<ScTabViewShell*>(pSh)->GetInputHandler();
280 if ( pHdl && pHdl->GetInputWindow() == this )
282 pHdl->SetInputWindow( NULL );
283 pHdl->StopInputWinEngine( false ); // reset pTopView pointer
285 pSh = SfxViewShell::GetNext( *pSh, &aScType );
289 SfxImageManager::GetImageManager( *SC_MOD() )->ReleaseToolBox( this );
291 pRuntimeWindow.disposeAndClear();
292 aWndPos.disposeAndClear();
294 ToolBox::dispose();
297 void ScInputWindow::SetInputHandler( ScInputHandler* pNew )
299 // Is called in the Activate of the View ...
300 if ( pNew != pInputHdl )
302 // On Reload (last version) the pInputHdl is the InputHandler of the old, deleted
303 // ViewShell: so don't touch it here!
304 pInputHdl = pNew;
305 if (pInputHdl)
306 pInputHdl->SetInputWindow( this );
310 bool ScInputWindow::UseSubTotal(ScRangeList* pRangeList)
312 bool bSubTotal = false;
313 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
314 if ( pViewSh )
316 ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
317 size_t nRangeCount (pRangeList->size());
318 size_t nRangeIndex (0);
319 while (!bSubTotal && nRangeIndex < nRangeCount)
321 const ScRange* pRange = (*pRangeList)[nRangeIndex];
322 if( pRange )
324 SCTAB nTabEnd(pRange->aEnd.Tab());
325 SCTAB nTab(pRange->aStart.Tab());
326 while (!bSubTotal && nTab <= nTabEnd)
328 SCROW nRowEnd(pRange->aEnd.Row());
329 SCROW nRow(pRange->aStart.Row());
330 while (!bSubTotal && nRow <= nRowEnd)
332 if (pDoc->RowFiltered(nRow, nTab))
333 bSubTotal = true;
334 else
335 ++nRow;
337 ++nTab;
340 ++nRangeIndex;
343 const ScDBCollection::NamedDBs& rDBs = pDoc->GetDBCollection()->getNamedDBs();
344 ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
345 for (; !bSubTotal && itr != itrEnd; ++itr)
347 const ScDBData& rDB = *itr;
348 if (!rDB.HasAutoFilter())
349 continue;
351 nRangeIndex = 0;
352 while (!bSubTotal && nRangeIndex < nRangeCount)
354 const ScRange* pRange = (*pRangeList)[nRangeIndex];
355 if( pRange )
357 ScRange aDBArea;
358 rDB.GetArea(aDBArea);
359 if (aDBArea.Intersects(*pRange))
360 bSubTotal = true;
362 ++nRangeIndex;
366 return bSubTotal;
369 void ScInputWindow::Select()
371 ScModule* pScMod = SC_MOD();
372 ToolBox::Select();
374 switch ( GetCurItemId() )
376 case SID_INPUT_FUNCTION:
378 //! new method at ScModule to query if function autopilot is open
379 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
380 if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
382 pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
383 SfxCallMode::SYNCHRON | SfxCallMode::RECORD );
385 // The Toolbox will be disabled anyways, so we don't need to switch here,
386 // regardless whether it succeeded or not!
387 // SetOkCancelMode();
390 break;
392 case SID_INPUT_CANCEL:
393 pScMod->InputCancelHandler();
394 SetSumAssignMode();
395 break;
397 case SID_INPUT_OK:
398 pScMod->InputEnterHandler();
399 SetSumAssignMode();
400 aTextWindow.Invalidate(); // Or else the Selection remains
401 break;
403 case SID_INPUT_SUM:
405 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
406 if ( pViewSh )
408 const ScMarkData& rMark = pViewSh->GetViewData().GetMarkData();
409 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
411 ScRangeList aMarkRangeList;
412 rMark.FillRangeListWithMarks( &aMarkRangeList, false );
413 ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
415 // check if one of the marked ranges is empty
416 bool bEmpty = false;
417 const size_t nCount = aMarkRangeList.size();
418 for ( size_t i = 0; i < nCount; ++i )
420 const ScRange aRange( *aMarkRangeList[i] );
421 if ( pDoc->IsBlockEmpty( aRange.aStart.Tab(),
422 aRange.aStart.Col(), aRange.aStart.Row(),
423 aRange.aEnd.Col(), aRange.aEnd.Row() ) )
425 bEmpty = true;
426 break;
430 if ( bEmpty )
432 ScRangeList aRangeList;
433 const bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
434 if ( bDataFound )
436 ScAddress aAddr = aRangeList.back()->aEnd;
437 aAddr.IncRow();
438 const bool bSubTotal( UseSubTotal( &aRangeList ) );
439 pViewSh->EnterAutoSum( aRangeList, bSubTotal, aAddr );
442 else
444 const bool bSubTotal( UseSubTotal( &aMarkRangeList ) );
445 for ( size_t i = 0; i < nCount; ++i )
447 const ScRange aRange( *aMarkRangeList[i] );
448 const bool bSetCursor = ( i == nCount - 1 );
449 const bool bContinue = ( i != 0 );
450 if ( !pViewSh->AutoSum( aRange, bSubTotal, bSetCursor, bContinue ) )
452 pViewSh->MarkRange( aRange, false, false );
453 pViewSh->SetCursor( aRange.aEnd.Col(), aRange.aEnd.Row() );
454 const ScRangeList aRangeList;
455 ScAddress aAddr = aRange.aEnd;
456 aAddr.IncRow();
457 const OUString aFormula = pViewSh->GetAutoSumFormula(
458 aRangeList, bSubTotal, aAddr );
459 SetFuncString( aFormula );
460 break;
465 else // Only insert into input row
467 ScRangeList aRangeList;
468 const bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
469 const bool bSubTotal( UseSubTotal( &aRangeList ) );
470 ScAddress aAddr = pViewSh->GetViewData().GetCurPos();
471 const OUString aFormula = pViewSh->GetAutoSumFormula( aRangeList, bSubTotal, aAddr );
472 SetFuncString( aFormula );
474 if ( bDataFound && pScMod->IsEditMode() )
476 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
477 if ( pHdl )
479 pHdl->InitRangeFinder( aFormula );
481 //! SetSelection at the InputHandler?
482 //! Set bSelIsRef?
483 const sal_Int32 nOpen = aFormula.indexOf('(');
484 const sal_Int32 nLen = aFormula.getLength();
485 if ( nOpen != -1 && nLen > nOpen )
487 sal_uInt8 nAdd(1);
488 if (bSubTotal)
489 nAdd = 3;
490 ESelection aSel(0,nOpen+nAdd,0,nLen-1);
491 EditView* pTableView = pHdl->GetTableView();
492 if (pTableView)
493 pTableView->SetSelection(aSel);
494 EditView* pTopView = pHdl->GetTopView();
495 if (pTopView)
496 pTopView->SetSelection(aSel);
503 break;
505 case SID_INPUT_EQUAL:
507 aTextWindow.StartEditEngine();
508 if ( pScMod->IsEditMode() ) // Isn't if e.g. protected
510 aTextWindow.StartEditEngine();
512 sal_Int32 nStartPos = 1;
513 sal_Int32 nEndPos = 1;
515 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
516 if ( pViewSh )
518 const OUString& rString = aTextWindow.GetTextString();
519 const sal_Int32 nLen = rString.getLength();
521 ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
522 CellType eCellType = pDoc->GetCellType( pViewSh->GetViewData().GetCurPos() );
523 switch ( eCellType )
525 case CELLTYPE_VALUE:
527 nEndPos = nLen + 1;
528 aTextWindow.SetTextString("=" + rString);
529 break;
531 case CELLTYPE_STRING:
532 case CELLTYPE_EDIT:
533 nStartPos = 0;
534 nEndPos = nLen;
535 break;
536 case CELLTYPE_FORMULA:
537 nEndPos = nLen;
538 break;
539 default:
540 aTextWindow.SetTextString("=");
541 break;
545 EditView* pView = aTextWindow.GetEditView();
546 if (pView)
548 pView->SetSelection( ESelection(0, nStartPos, 0, nEndPos) );
549 pScMod->InputChanged(pView);
550 SetOkCancelMode();
551 pView->SetEditEngineUpdateMode(true);
554 break;
559 void ScInputWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
561 ToolBox::Paint(rRenderContext, rRect);
563 // draw a line at the bottom to distinguish that from the grid
564 // (we have space for that thanks to ADDITIONAL_BORDER)
565 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
566 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
568 Size aSize = GetSizePixel();
569 rRenderContext.DrawLine(Point(0, aSize.Height() - 1),
570 Point(aSize.Width() - 1, aSize.Height() - 1));
573 void ScInputWindow::Resize()
575 ToolBox::Resize();
576 if ( mbIsMultiLine )
578 aTextWindow.Resize();
579 Size aSize = GetSizePixel();
580 aSize.Height() = CalcWindowSizePixel().Height() + ADDITIONAL_BORDER;
581 ScInputBarGroup* pGroupBar = dynamic_cast< ScInputBarGroup* > ( pRuntimeWindow.get() );
582 if ( pGroupBar )
584 // To ensure smooth display and prevent the items in the toolbar being
585 // repositioned ( vertically ) we lock the vertical positioning of the toolbox
586 // items when we are displaying > 1 line.
587 // So, we need to adjust the height of the toolbox accordingly. If we don't
588 // then the largest item ( e.g. the GroupBar window ) will actually be
589 // positioned such that the toolbar will cut off the bottom of that item
590 if ( pGroupBar->GetNumLines() > 1 )
591 aSize.Height() += pGroupBar->GetVertOffset() + ADDITIONAL_SPACE;
593 SetSizePixel(aSize);
594 Invalidate();
596 else
598 long nWidth = GetSizePixel().Width();
599 long nLeft = aTextWindow.GetPosPixel().X();
600 Size aSize = aTextWindow.GetSizePixel();
602 aSize.Width() = std::max( ((long)(nWidth - nLeft - 5)), (long)0 );
604 aTextWindow.SetSizePixel( aSize );
605 aTextWindow.Invalidate();
609 void ScInputWindow::SetFuncString( const OUString& rString, bool bDoEdit )
611 //! new method at ScModule to query if function autopilot is open
612 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
613 EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
614 aTextWindow.StartEditEngine();
616 ScModule* pScMod = SC_MOD();
617 if ( pScMod->IsEditMode() )
619 if ( bDoEdit )
620 aTextWindow.GrabFocus();
621 aTextWindow.SetTextString( rString );
622 EditView* pView = aTextWindow.GetEditView();
623 if (pView)
625 sal_Int32 nLen = rString.getLength();
627 if ( nLen > 0 )
629 nLen--;
630 pView->SetSelection( ESelection( 0, nLen, 0, nLen ) );
633 pScMod->InputChanged(pView);
634 if ( bDoEdit )
635 SetOkCancelMode(); // Not the case if immediately followed by Enter/Cancel
637 pView->SetEditEngineUpdateMode(true);
642 void ScInputWindow::SetPosString( const OUString& rStr )
644 aWndPos->SetPos( rStr );
647 void ScInputWindow::SetTextString( const OUString& rString )
649 if (rString.getLength() <= 32767)
650 aTextWindow.SetTextString(rString);
651 else
652 aTextWindow.SetTextString(rString.copy(0, 32767));
655 void ScInputWindow::SetOkCancelMode()
657 //! new method at ScModule to query if function autopilot is open
658 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
659 EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
661 ScModule* pScMod = SC_MOD();
662 SfxImageManager* pImgMgr = SfxImageManager::GetImageManager(*pScMod);
663 if (!bIsOkCancelMode)
665 RemoveItem( 3 ); // Remove SID_INPUT_SUM and SID_INPUT_EQUAL
666 RemoveItem( 3 );
667 InsertItem( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ), ToolBoxItemBits::NONE, 3 );
668 InsertItem( SID_INPUT_OK, IMAGE( SID_INPUT_OK ), ToolBoxItemBits::NONE, 4 );
669 SetItemText ( SID_INPUT_CANCEL, aTextCancel );
670 SetHelpId ( SID_INPUT_CANCEL, HID_INSWIN_CANCEL );
671 SetItemText ( SID_INPUT_OK, aTextOk );
672 SetHelpId ( SID_INPUT_OK, HID_INSWIN_OK );
673 bIsOkCancelMode = true;
677 void ScInputWindow::SetSumAssignMode()
679 //! new method at ScModule to query if function autopilot is open
680 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
681 EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
683 ScModule* pScMod = SC_MOD();
684 SfxImageManager* pImgMgr = SfxImageManager::GetImageManager(*pScMod);
685 if (bIsOkCancelMode)
687 // Remove SID_INPUT_CANCEL, and SID_INPUT_OK
688 RemoveItem( 3 );
689 RemoveItem( 3 );
690 InsertItem( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ), ToolBoxItemBits::NONE, 3 );
691 InsertItem( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ), ToolBoxItemBits::NONE, 4 );
692 SetItemText ( SID_INPUT_SUM, aTextSum );
693 SetHelpId ( SID_INPUT_SUM, HID_INSWIN_SUMME );
694 SetItemText ( SID_INPUT_EQUAL, aTextEqual );
695 SetHelpId ( SID_INPUT_EQUAL, HID_INSWIN_FUNC );
696 bIsOkCancelMode = false;
698 SetFormulaMode(false); // No editing -> no formula
702 void ScInputWindow::SetFormulaMode( bool bSet )
704 aWndPos->SetFormulaMode(bSet);
705 aTextWindow.SetFormulaMode(bSet);
708 void ScInputWindow::SetText( const OUString& rString )
710 ToolBox::SetText(rString);
713 OUString ScInputWindow::GetText() const
715 return ToolBox::GetText();
718 bool ScInputWindow::IsInputActive()
720 return aTextWindow.IsInputActive();
723 EditView* ScInputWindow::GetEditView()
725 return aTextWindow.GetEditView();
728 void ScInputWindow::MakeDialogEditView()
730 aTextWindow.MakeDialogEditView();
733 void ScInputWindow::StopEditEngine( bool bAll )
735 aTextWindow.StopEditEngine( bAll );
738 void ScInputWindow::TextGrabFocus()
740 aTextWindow.TextGrabFocus();
743 void ScInputWindow::TextInvalidate()
745 aTextWindow.Invalidate();
748 void ScInputWindow::SwitchToTextWin()
750 // used for shift-ctrl-F2
752 aTextWindow.StartEditEngine();
753 if ( SC_MOD()->IsEditMode() )
755 aTextWindow.TextGrabFocus();
756 EditView* pView = aTextWindow.GetEditView();
757 if (pView)
759 sal_Int32 nPara = pView->GetEditEngine()->GetParagraphCount() ? ( pView->GetEditEngine()->GetParagraphCount() - 1 ) : 0;
760 sal_Int32 nLen = pView->GetEditEngine()->GetTextLen( nPara );
761 ESelection aSel( nPara, nLen, nPara, nLen );
762 pView->SetSelection( aSel ); // set cursor to end of text
767 void ScInputWindow::PosGrabFocus()
769 aWndPos->GrabFocus();
772 void ScInputWindow::EnableButtons( bool bEnable )
774 // when enabling buttons, always also enable the input window itself
775 if ( bEnable && !IsEnabled() )
776 Enable();
778 EnableItem( SID_INPUT_FUNCTION, bEnable );
779 EnableItem( bIsOkCancelMode ? SID_INPUT_CANCEL : SID_INPUT_SUM, bEnable );
780 EnableItem( bIsOkCancelMode ? SID_INPUT_OK : SID_INPUT_EQUAL, bEnable );
781 // Invalidate();
784 void ScInputWindow::StateChanged( StateChangedType nType )
786 ToolBox::StateChanged( nType );
788 if ( nType == StateChangedType::InitShow ) Resize();
791 void ScInputWindow::DataChanged( const DataChangedEvent& rDCEvt )
793 if ( rDCEvt.GetType() == DataChangedEventType::SETTINGS && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
795 // update item images
796 ScModule* pScMod = SC_MOD();
797 SfxImageManager* pImgMgr = SfxImageManager::GetImageManager(*pScMod);
799 // IMAGE macro uses pScMod, pImgMg
800 SetItemImage( SID_INPUT_FUNCTION, IMAGE( SID_INPUT_FUNCTION ) );
801 if ( bIsOkCancelMode )
803 SetItemImage( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ) );
804 SetItemImage( SID_INPUT_OK, IMAGE( SID_INPUT_OK ) );
806 else
808 SetItemImage( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ) );
809 SetItemImage( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ) );
813 ToolBox::DataChanged( rDCEvt );
816 bool ScInputWindow::IsPointerAtResizePos()
818 if ( GetOutputSizePixel().Height() - GetPointerPosPixel().Y() <= 4 )
819 return true;
820 else
821 return false;
824 void ScInputWindow::MouseMove( const MouseEvent& rMEvt )
826 if ( mbIsMultiLine )
828 Point aPosPixel = GetPointerPosPixel();
830 ScInputBarGroup* pGroupBar = dynamic_cast< ScInputBarGroup* > ( pRuntimeWindow.get() );
832 if ( bInResize || IsPointerAtResizePos() )
833 SetPointer( Pointer( PointerStyle::WindowSSize ) );
834 else
835 SetPointer( Pointer( PointerStyle::Arrow ) );
837 if ( bInResize )
839 // detect direction
840 long nResizeThreshold = ( (long)TBX_WINDOW_HEIGHT * 0.7 );
841 bool bResetPointerPos = false;
843 // Detect attempt to expand toolbar too much
844 if ( aPosPixel.Y() >= mnMaxY )
846 bResetPointerPos = true;
847 aPosPixel.Y() = mnMaxY;
848 } // or expanding down
849 else if ( GetOutputSizePixel().Height() - aPosPixel.Y() < -nResizeThreshold )
851 pGroupBar->IncrementVerticalSize();
852 bResetPointerPos = true;
853 } // or shrinking up
854 else if ( ( GetOutputSizePixel().Height() - aPosPixel.Y() ) > nResizeThreshold )
856 bResetPointerPos = true;
857 pGroupBar->DecrementVerticalSize();
860 if ( bResetPointerPos )
862 aPosPixel.Y() = GetOutputSizePixel().Height();
863 SetPointerPosPixel( aPosPixel );
867 ToolBox::MouseMove( rMEvt );
870 void ScInputWindow::MouseButtonDown( const MouseEvent& rMEvt )
872 if ( mbIsMultiLine )
874 if ( rMEvt.IsLeft() )
876 if ( IsPointerAtResizePos() )
878 // Don't leave the mouse pointer leave *this* window
879 CaptureMouse();
880 bInResize = true;
882 // find the height of the gridwin, we don't wan't to be
883 // able to expand the toolbar too far so we need to
884 // calculate an upper limit
885 // I'd prefer to leave at least a single column header and a
886 // row but I don't know how to get that value in pixels.
887 // Use TBX_WINDOW_HEIGHT for the moment
888 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
889 mnMaxY = GetOutputSizePixel().Height() + ( pViewSh->GetGridHeight(SC_SPLIT_TOP) + pViewSh->GetGridHeight(SC_SPLIT_BOTTOM) ) - TBX_WINDOW_HEIGHT;
893 ToolBox::MouseButtonDown( rMEvt );
895 void ScInputWindow::MouseButtonUp( const MouseEvent& rMEvt )
897 if ( mbIsMultiLine )
899 ReleaseMouse();
900 if ( rMEvt.IsLeft() )
902 bInResize = false;
903 mnMaxY = 0;
906 ToolBox::MouseButtonUp( rMEvt );
909 ScInputBarGroup::ScInputBarGroup(vcl::Window* pParent, ScTabViewShell* pViewSh)
910 : ScTextWndBase ( pParent, WinBits(WB_HIDE | WB_TABSTOP ) ),
911 aMultiTextWnd ( VclPtr<ScMultiTextWnd>::Create(this, pViewSh) ),
912 aButton ( VclPtr<ImageButton>::Create(this, WB_TABSTOP | WB_RECTSTYLE | WB_SMALLSTYLE) ),
913 aScrollBar ( VclPtr<ScrollBar>::Create(this, WB_TABSTOP | WB_VERT | WB_DRAG) ),
914 nVertOffset ( 0 )
916 aMultiTextWnd->Show();
917 aMultiTextWnd->SetQuickHelpText( ScResId( SCSTR_QHELP_INPUTWND ) );
918 aMultiTextWnd->SetHelpId( HID_INSWIN_INPUT );
920 Size aSize( GetSettings().GetStyleSettings().GetScrollBarSize(), aMultiTextWnd->GetPixelHeightForLines(1) );
922 aButton->SetClickHdl( LINK( this, ScInputBarGroup, ClickHdl ) );
923 aButton->SetSizePixel( aSize );
924 aButton->Enable();
925 aButton->SetSymbol( SymbolType::SPIN_DOWN );
926 aButton->SetQuickHelpText( ScResId( SCSTR_QHELP_EXPAND_FORMULA ) );
927 aButton->Show();
929 aScrollBar->SetSizePixel( aSize );
930 aScrollBar->SetScrollHdl( LINK( this, ScInputBarGroup, Impl_ScrollHdl ) );
933 ScInputBarGroup::~ScInputBarGroup()
935 disposeOnce();
938 void ScInputBarGroup::dispose()
940 aMultiTextWnd.disposeAndClear();
941 aButton.disposeAndClear();
942 aScrollBar.disposeAndClear();
943 ScTextWndBase::dispose();
946 void
947 ScInputBarGroup::InsertAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
949 aMultiTextWnd->InsertAccessibleTextData( rTextData );
952 void
953 ScInputBarGroup::RemoveAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
955 aMultiTextWnd->RemoveAccessibleTextData( rTextData );
958 const OUString&
959 ScInputBarGroup::GetTextString() const
961 return aMultiTextWnd->GetTextString();
964 void ScInputBarGroup::SetTextString( const OUString& rString )
966 aMultiTextWnd->SetTextString(rString);
969 void ScInputBarGroup::Resize()
971 vcl::Window*w = GetParent();
972 ScInputWindow *pParent;
973 pParent = dynamic_cast<ScInputWindow*>(w);
975 if (pParent == NULL)
977 OSL_FAIL("The parent window pointer pParent is null");
978 return;
981 long nWidth = pParent->GetSizePixel().Width();
982 long nLeft = GetPosPixel().X();
984 Size aSize = GetSizePixel();
985 aSize.Width() = std::max(long(nWidth - nLeft - LEFT_OFFSET), long(0));
987 aScrollBar->SetPosPixel(Point( aSize.Width() - aButton->GetSizePixel().Width(), aButton->GetSizePixel().Height() ) );
989 Size aTmpSize( aSize );
990 aTmpSize.Width() = aTmpSize.Width() - aButton->GetSizePixel().Width() - BUTTON_OFFSET;
991 aMultiTextWnd->SetSizePixel(aTmpSize);
993 aMultiTextWnd->Resize();
995 aSize.Height() = aMultiTextWnd->GetSizePixel().Height();
997 SetSizePixel(aSize);
999 if (aMultiTextWnd->GetNumLines() > 1)
1001 aButton->SetSymbol( SymbolType::SPIN_UP );
1002 aButton->SetQuickHelpText( ScResId( SCSTR_QHELP_COLLAPSE_FORMULA ) );
1003 Size scrollSize = aButton->GetSizePixel();
1004 scrollSize.Height() = aMultiTextWnd->GetSizePixel().Height() - aButton->GetSizePixel().Height();
1005 aScrollBar->SetSizePixel( scrollSize );
1007 Size aOutSz = aMultiTextWnd->GetOutputSize();
1009 aScrollBar->SetVisibleSize( aOutSz.Height() );
1010 aScrollBar->SetPageSize( aOutSz.Height() );
1011 aScrollBar->SetLineSize( aMultiTextWnd->GetTextHeight() );
1012 aScrollBar->SetRange( Range( 0, aMultiTextWnd->GetEditEngTxtHeight() ) );
1014 aScrollBar->Resize();
1015 aScrollBar->Show();
1017 else
1019 aButton->SetSymbol( SymbolType::SPIN_DOWN );
1020 aButton->SetQuickHelpText( ScResId( SCSTR_QHELP_EXPAND_FORMULA ) );
1021 aScrollBar->Hide();
1024 aButton->SetPosPixel(Point(aSize.Width() - aButton->GetSizePixel().Width(), 0));
1026 Invalidate();
1029 void ScInputBarGroup::StopEditEngine( bool bAll )
1031 aMultiTextWnd->StopEditEngine( bAll );
1034 void ScInputBarGroup::StartEditEngine()
1036 aMultiTextWnd->StartEditEngine();
1039 void ScInputBarGroup::MakeDialogEditView()
1041 aMultiTextWnd->MakeDialogEditView();
1044 EditView* ScInputBarGroup::GetEditView()
1046 return aMultiTextWnd->GetEditView();
1049 bool ScInputBarGroup::IsInputActive()
1051 return aMultiTextWnd->IsInputActive();
1054 void ScInputBarGroup::SetFormulaMode(bool bSet)
1056 aMultiTextWnd->SetFormulaMode(bSet);
1059 void ScInputBarGroup::IncrementVerticalSize()
1061 aMultiTextWnd->SetNumLines( aMultiTextWnd->GetNumLines() + 1 );
1062 TriggerToolboxLayout();
1065 void ScInputBarGroup::DecrementVerticalSize()
1067 if ( aMultiTextWnd->GetNumLines() > 1 )
1069 aMultiTextWnd->SetNumLines( aMultiTextWnd->GetNumLines() - 1 );
1070 TriggerToolboxLayout();
1074 IMPL_LINK_NOARG(ScInputBarGroup, ClickHdl)
1076 vcl::Window* w = GetParent();
1077 ScInputWindow* pParent;
1078 pParent = dynamic_cast<ScInputWindow*>(w);
1080 if (pParent == NULL)
1082 OSL_FAIL("The parent window pointer pParent is null");
1083 return 1;
1085 if (aMultiTextWnd->GetNumLines() > 1)
1087 aMultiTextWnd->SetNumLines(1);
1089 else
1091 aMultiTextWnd->SetNumLines(aMultiTextWnd->GetLastNumExpandedLines());
1093 TriggerToolboxLayout();
1095 // Restore focus to input line(s) if necessary
1096 if ( SC_MOD()->GetInputHdl()->IsTopMode() )
1097 aMultiTextWnd->GrabFocus();
1098 return 0;
1101 void ScInputBarGroup::TriggerToolboxLayout()
1103 vcl::Window *w=GetParent();
1104 ScInputWindow &rParent = dynamic_cast<ScInputWindow&>(*w);
1105 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1107 // Capture the vertical position of this window in the toolbar, when we increase
1108 // the size of the toolbar to accommodate expanded line input we need to take this
1109 // into account
1110 if ( !nVertOffset )
1111 nVertOffset = rParent.GetItemPosRect( rParent.GetItemCount() - 1 ).Top();
1113 if ( pViewFrm )
1115 Reference< com::sun::star::beans::XPropertySet > xPropSet( pViewFrm->GetFrame().GetFrameInterface(), UNO_QUERY );
1116 Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1118 if ( xPropSet.is() )
1120 com::sun::star::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
1121 aValue >>= xLayoutManager;
1124 if ( xLayoutManager.is() )
1126 if ( aMultiTextWnd->GetNumLines() > 1)
1127 rParent.SetToolbarLayoutMode( TBX_LAYOUT_LOCKVERT );
1128 else
1129 rParent.SetToolbarLayoutMode( TBX_LAYOUT_NORMAL );
1130 xLayoutManager->lock();
1131 DataChangedEvent aFakeUpdate( DataChangedEventType::SETTINGS, NULL, AllSettingsFlags::STYLE );
1133 // this basically will trigger the reposititioning of the
1134 // items in the toolbar from ImplFormat ( which is controlled by
1135 // mnWinHeight ) which in turn is updated in ImplCalcItem which is
1136 // controlled by mbCalc. Additionally the ImplFormat above is
1137 // controlled via mbFormat. It seems the easiest way to get these
1138 // booleans set is to send in the fake event below.
1139 rParent.DataChanged( aFakeUpdate);
1141 // highest item in toolbar will have been calculated via the
1142 // event above. Call resize on InputBar to pick up the height
1143 // change
1144 rParent.Resize();
1146 // unlock relayouts the toolbars in the 4 quadrants
1147 xLayoutManager->unlock();
1152 IMPL_LINK_NOARG(ScInputBarGroup, Impl_ScrollHdl)
1154 aMultiTextWnd->DoScroll();
1155 return 0;
1158 void ScInputBarGroup::TextGrabFocus()
1160 aMultiTextWnd->TextGrabFocus();
1163 ScMultiTextWnd::ScMultiTextWnd( ScInputBarGroup* pParen, ScTabViewShell* pViewSh )
1164 : ScTextWnd( pParen, pViewSh ),
1165 mrGroupBar(* pParen ),
1166 mnLines( 1 ),
1167 mnLastExpandedLines( INPUTWIN_MULTILINES ),
1168 mbInvalidate( false )
1170 Size aBorder;
1171 aBorder = CalcWindowSize(aBorder);
1172 mnBorderHeight = aBorder.Height();
1175 ScMultiTextWnd::~ScMultiTextWnd()
1179 void ScMultiTextWnd::Paint( vcl::RenderContext& rRenderContext, const Rectangle& rRect )
1181 EditView* pView = GetEditView();
1182 if (pView)
1184 if (mbInvalidate)
1186 pView->Invalidate();
1187 mbInvalidate = false;
1189 pEditView->Paint(rRect, &rRenderContext);
1193 EditView* ScMultiTextWnd::GetEditView()
1195 if ( !pEditView )
1196 InitEditEngine();
1197 return pEditView;
1200 long ScMultiTextWnd::GetPixelHeightForLines( long nLines )
1202 // add padding ( for the borders of the window )
1203 return ( nLines * LogicToPixel( Size( 0, GetTextHeight() ) ).Height() ) + mnBorderHeight;
1206 void ScMultiTextWnd::SetNumLines( long nLines )
1208 mnLines = nLines;
1209 if ( nLines > 1 )
1211 mnLastExpandedLines = nLines;
1212 Resize();
1216 void ScMultiTextWnd::Resize()
1218 // Only Height is recalculated here, Width is applied from
1219 // parent/container window
1220 Size aTextBoxSize = GetSizePixel();
1222 aTextBoxSize.Height() = GetPixelHeightForLines( mnLines );
1223 SetSizePixel( aTextBoxSize );
1225 if(pEditView)
1227 Size aOutputSize = GetOutputSizePixel();
1228 Rectangle aOutputArea = PixelToLogic( Rectangle( Point(), aOutputSize ));
1229 pEditView->SetOutputArea( aOutputArea );
1231 // Don't leave an empty area at the bottom if we can move the text down.
1232 long nMaxVisAreaTop = pEditEngine->GetTextHeight() - aOutputArea.GetHeight();
1233 if (pEditView->GetVisArea().Top() > nMaxVisAreaTop)
1235 pEditView->Scroll(0, pEditView->GetVisArea().Top() - nMaxVisAreaTop);
1238 pEditEngine->SetPaperSize( PixelToLogic( Size( aOutputSize.Width(), 10000 ) ) );
1241 SetScrollBarRange();
1244 IMPL_LINK(ScMultiTextWnd, ModifyHdl, EENotify*, pNotify)
1246 ScTextWnd::NotifyHdl( pNotify );
1247 return 0;
1250 IMPL_LINK(ScMultiTextWnd, NotifyHdl, EENotify*, pNotify)
1252 // need to process EE_NOTIFY_TEXTVIEWSCROLLED here
1253 // sometimes we don't seem to get EE_NOTIFY_TEXTVIEWSCROLLED e.g. when
1254 // we insert text at the beginning of the text so the cursor never moves
1255 // down to generate a scroll event
1257 if ( pNotify && ( pNotify->eNotificationType == EE_NOTIFY_TEXTVIEWSCROLLED
1258 || pNotify->eNotificationType == EE_NOTIFY_TEXTHEIGHTCHANGED ) )
1259 SetScrollBarRange();
1260 return 0;
1263 long ScMultiTextWnd::GetEditEngTxtHeight()
1265 return pEditView ? pEditView->GetEditEngine()->GetTextHeight() : 0;
1268 void ScMultiTextWnd::SetScrollBarRange()
1270 if ( pEditView )
1272 ScrollBar& rVBar = mrGroupBar.GetScrollBar();
1273 rVBar.SetRange( Range( 0, GetEditEngTxtHeight() ) );
1274 long currentDocPos = pEditView->GetVisArea().TopLeft().Y();
1275 rVBar.SetThumbPos( currentDocPos );
1279 void
1280 ScMultiTextWnd::DoScroll()
1282 if ( pEditView )
1284 ScrollBar& rVBar = mrGroupBar.GetScrollBar();
1285 long currentDocPos = pEditView->GetVisArea().TopLeft().Y();
1286 long nDiff = currentDocPos - rVBar.GetThumbPos();
1287 pEditView->Scroll( 0, nDiff );
1288 currentDocPos = pEditView->GetVisArea().TopLeft().Y();
1289 rVBar.SetThumbPos( currentDocPos );
1293 void ScMultiTextWnd::StartEditEngine()
1295 // Don't activate if we're a modal dialog ourselves (Doc-modal dialog)
1296 SfxObjectShell* pObjSh = SfxObjectShell::Current();
1297 if ( pObjSh && pObjSh->IsInModalMode() )
1298 return;
1300 if ( !pEditView || !pEditEngine )
1302 InitEditEngine();
1305 SC_MOD()->SetInputMode( SC_INPUT_TOP );
1307 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1308 if (pViewFrm)
1309 pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
1312 static void lcl_ExtendEditFontAttribs( SfxItemSet& rSet )
1314 const SfxPoolItem& rFontItem = rSet.Get( EE_CHAR_FONTINFO );
1315 rSet.Put( rFontItem, EE_CHAR_FONTINFO_CJK );
1316 rSet.Put( rFontItem, EE_CHAR_FONTINFO_CTL );
1317 const SfxPoolItem& rHeightItem = rSet.Get( EE_CHAR_FONTHEIGHT );
1318 rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CJK );
1319 rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CTL );
1320 const SfxPoolItem& rWeightItem = rSet.Get( EE_CHAR_WEIGHT );
1321 rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CJK );
1322 rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CTL );
1323 const SfxPoolItem& rItalicItem = rSet.Get( EE_CHAR_ITALIC );
1324 rSet.Put( rItalicItem, EE_CHAR_ITALIC_CJK );
1325 rSet.Put( rItalicItem, EE_CHAR_ITALIC_CTL );
1326 const SfxPoolItem& rLangItem = rSet.Get( EE_CHAR_LANGUAGE );
1327 rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CJK );
1328 rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CTL );
1331 static void lcl_ModifyRTLDefaults( SfxItemSet& rSet )
1333 rSet.Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) );
1335 // always using rtl writing direction would break formulas
1336 //rSet.Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) );
1338 // PaperSize width is limited to USHRT_MAX in RTL mode (because of EditEngine's
1339 // sal_uInt16 values in EditLine), so the text may be wrapped and line spacing must be
1340 // increased to not see the beginning of the next line.
1341 SvxLineSpacingItem aItem( SVX_LINESPACE_TWO_LINES, EE_PARA_SBL );
1342 aItem.SetPropLineSpace( 200 );
1343 rSet.Put( aItem );
1346 static void lcl_ModifyRTLVisArea( EditView* pEditView )
1348 Rectangle aVisArea = pEditView->GetVisArea();
1349 Size aPaper = pEditView->GetEditEngine()->GetPaperSize();
1350 long nDiff = aPaper.Width() - aVisArea.Right();
1351 aVisArea.Left() += nDiff;
1352 aVisArea.Right() += nDiff;
1353 pEditView->SetVisArea(aVisArea);
1356 void ScMultiTextWnd::InitEditEngine()
1358 ScFieldEditEngine* pNew;
1359 ScTabViewShell* pViewSh = GetViewShell();
1360 ScDocShell* pDocSh = NULL;
1361 if ( pViewSh )
1363 pDocSh = pViewSh->GetViewData().GetDocShell();
1364 ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
1365 pNew = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
1367 else
1368 pNew = new ScFieldEditEngine(NULL, EditEngine::CreatePool(), NULL, true);
1369 pNew->SetExecuteURL( false );
1370 pEditEngine = pNew;
1372 Size barSize=GetSizePixel();
1373 pEditEngine->SetUpdateMode( false );
1374 pEditEngine->SetPaperSize( PixelToLogic(Size(barSize.Width(),10000)) );
1375 pEditEngine->SetWordDelimiters(
1376 ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1378 UpdateAutoCorrFlag();
1381 SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1382 EditEngine::SetFontInfoInItemSet( *pSet, aTextFont );
1383 lcl_ExtendEditFontAttribs( *pSet );
1384 // turn off script spacing to match DrawText output
1385 pSet->Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) );
1386 if ( bIsRTL )
1387 lcl_ModifyRTLDefaults( *pSet );
1388 pEditEngine->SetDefaults( pSet );
1391 // If the Cell contains URLFields, they need to be taken over into the entry row,
1392 // or else the position is not correct anymore
1393 bool bFilled = false;
1394 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1395 if ( pHdl ) //! Test if it's the right InputHdl?
1396 bFilled = pHdl->GetTextAndFields( *pEditEngine );
1398 pEditEngine->SetUpdateMode( true );
1400 // aString is the truth ...
1401 if (bFilled && pEditEngine->GetText() == aString)
1402 Invalidate(); // Repaint for (filled) Field
1403 else
1404 pEditEngine->SetText(aString); // At least the right text then
1406 pEditView = new EditView( pEditEngine, this );
1407 pEditView->SetInsertMode(bIsInsertMode);
1409 // Text from Clipboard is taken over as ASCII in a single row
1410 EVControlBits n = pEditView->GetControlWord();
1411 pEditView->SetControlWord( n | EVControlBits::SINGLELINEPASTE );
1413 pEditEngine->InsertView( pEditView, EE_APPEND );
1415 Resize();
1417 if ( bIsRTL )
1418 lcl_ModifyRTLVisArea( pEditView );
1420 pEditEngine->SetModifyHdl(LINK(this, ScMultiTextWnd, ModifyHdl));
1421 pEditEngine->SetNotifyHdl(LINK(this, ScMultiTextWnd, NotifyHdl));
1423 if (!maAccTextDatas.empty())
1424 maAccTextDatas.back()->StartEdit();
1426 // as long as EditEngine and DrawText sometimes differ for CTL text,
1427 // repaint now to have the EditEngine's version visible
1428 if (pDocSh)
1430 ScDocument& rDoc = pDocSh->GetDocument(); // any document
1431 SvtScriptType nScript = rDoc.GetStringScriptType( aString );
1432 if ( nScript & SvtScriptType::COMPLEX )
1433 Invalidate();
1437 void ScMultiTextWnd::StopEditEngine( bool bAll )
1439 if ( pEditEngine )
1440 pEditEngine->SetNotifyHdl(Link<>());
1441 ScTextWnd::StopEditEngine( bAll );
1444 void ScMultiTextWnd::SetTextString( const OUString& rNewString )
1446 // Ideally it would be best to create on demand the EditEngine/EditView here, but... for
1447 // the initialisation scenario where a cell is first clicked on we end up with the text in the
1448 // inputbar window scrolled to the bottom if we do that here ( because the tableview and topview
1449 // are synced I guess ).
1450 // should fix that I suppose :-/ need to look a bit further into that
1451 mbInvalidate = true; // ensure next Paint ( that uses editengine ) call will call Invalidate first
1452 ScTextWnd::SetTextString( rNewString );
1453 SetScrollBarRange();
1454 DoScroll();
1457 ScTextWnd::ScTextWnd( vcl::Window* pParent, ScTabViewShell* pViewSh )
1458 : ScTextWndBase(pParent, WinBits(WB_HIDE | WB_BORDER)),
1459 DragSourceHelper(this),
1460 pEditEngine (NULL),
1461 pEditView (NULL),
1462 bIsInsertMode(true),
1463 bFormulaMode (false),
1464 bInputMode (false),
1465 mpViewShell(pViewSh)
1467 EnableRTL(false); // EditEngine can't be used with VCL EnableRTL
1469 bIsRTL = AllSettings::GetLayoutRTL();
1471 // always use application font, so a font with cjk chars can be installed
1472 vcl::Font aAppFont = GetFont();
1473 aTextFont = aAppFont;
1474 aTextFont.SetSize(PixelToLogic(aAppFont.GetSize(), MAP_TWIP)); // AppFont is in pixels
1476 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1478 Color aBgColor = rStyleSettings.GetWindowColor();
1479 Color aTxtColor = rStyleSettings.GetWindowTextColor();
1481 aTextFont.SetTransparent(true);
1482 aTextFont.SetFillColor(aBgColor);
1483 aTextFont.SetColor(aTxtColor);
1484 aTextFont.SetWeight(WEIGHT_NORMAL);
1486 Size aSize(1,TBX_WINDOW_HEIGHT);
1487 Size aMinEditSize( Edit::GetMinimumEditSize() );
1488 if( aMinEditSize.Height() > aSize.Height() )
1489 aSize.Height() = aMinEditSize.Height();
1491 SetSizePixel(aSize);
1492 SetBackground(aBgColor);
1493 SetLineColor(COL_BLACK);
1494 SetMapMode(MAP_TWIP);
1495 SetPointer(PointerStyle::Text);
1496 SetFont(aTextFont);
1499 ScTextWnd::~ScTextWnd()
1501 disposeOnce();
1504 void ScTextWnd::dispose()
1506 while (!maAccTextDatas.empty()) {
1507 maAccTextDatas.back()->Dispose();
1509 delete pEditView;
1510 pEditView = NULL;
1511 delete pEditEngine;
1512 pEditEngine = NULL;
1514 ScTextWndBase::dispose();
1517 void ScTextWnd::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
1519 if (pEditView)
1521 Size aSize(GetOutputSizePixel());
1522 long nDiff = aSize.Height() - rRenderContext.LogicToPixel(Size(0, rRenderContext.GetTextHeight())).Height();
1523 pEditView->SetOutputArea(rRenderContext.PixelToLogic(Rectangle(Point(0, (nDiff > 0) ? nDiff / 2 : 1), aSize)));
1525 pEditView->Paint(rRect, &rRenderContext);
1527 else
1529 Size aSize = GetOutputSizePixel();
1530 SetFont(aTextFont);
1532 long nDiff = aSize.Height() - rRenderContext.LogicToPixel(Size(0, rRenderContext.GetTextHeight())).Height();
1534 // if (nDiff<2) nDiff=2; // At least 1 pixel
1536 long nStartPos = 0;
1537 if (bIsRTL)
1539 // right-align
1540 nStartPos += aSize.Width() - rRenderContext.LogicToPixel(Size(rRenderContext.GetTextWidth(aString), 0)).Width();
1542 // LayoutMode isn't changed as long as ModifyRTLDefaults doesn't include SvxFrameDirectionItem
1544 rRenderContext.DrawText(rRenderContext.PixelToLogic(Point(nStartPos, nDiff / 2)), aString);
1546 rRenderContext.Pop();
1549 void ScTextWnd::Resize()
1551 Invalidate();
1554 void ScTextWnd::MouseMove( const MouseEvent& rMEvt )
1556 if (pEditView)
1557 pEditView->MouseMove( rMEvt );
1560 void ScTextWnd::MouseButtonDown( const MouseEvent& rMEvt )
1562 if (!HasFocus())
1564 StartEditEngine();
1565 if ( SC_MOD()->IsEditMode() )
1566 GrabFocus();
1569 if (pEditView)
1571 pEditView->SetEditEngineUpdateMode( true );
1572 pEditView->MouseButtonDown( rMEvt );
1576 void ScTextWnd::MouseButtonUp( const MouseEvent& rMEvt )
1578 if (pEditView)
1579 if (pEditView->MouseButtonUp( rMEvt ))
1581 if ( rMEvt.IsMiddle() &&
1582 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MouseMiddleButtonAction::PasteSelection )
1584 // EditView may have pasted from selection
1585 SC_MOD()->InputChanged( pEditView );
1587 else
1588 SC_MOD()->InputSelection( pEditView );
1592 void ScTextWnd::Command( const CommandEvent& rCEvt )
1594 bInputMode = true;
1595 CommandEventId nCommand = rCEvt.GetCommand();
1596 if ( pEditView /* && nCommand == CommandEventId::StartDrag */ )
1598 ScModule* pScMod = SC_MOD();
1599 ScTabViewShell* pStartViewSh = ScTabViewShell::GetActiveViewShell();
1601 // don't modify the font defaults here - the right defaults are
1602 // already set in StartEditEngine when the EditEngine is created
1604 // Prevent that the EditView is lost when switching between Views
1605 pScMod->SetInEditCommand( true );
1606 pEditView->Command( rCEvt );
1607 pScMod->SetInEditCommand( false );
1609 // CommandEventId::StartDrag does not mean by far that the content was actually changed,
1610 // so don't trigger an InputChanged.
1611 //! Detect if dragged with Move or forbid Drag&Move somehow
1613 if ( nCommand == CommandEventId::StartDrag )
1615 // Is dragged onto another View?
1616 ScTabViewShell* pEndViewSh = ScTabViewShell::GetActiveViewShell();
1617 if ( pEndViewSh != pStartViewSh && pStartViewSh != NULL )
1619 ScViewData& rViewData = pStartViewSh->GetViewData();
1620 ScInputHandler* pHdl = pScMod->GetInputHdl( pStartViewSh );
1621 if ( pHdl && rViewData.HasEditView( rViewData.GetActivePart() ) )
1623 pHdl->CancelHandler();
1624 rViewData.GetView()->ShowCursor(); // Missing for KillEditView, due to being inactive
1628 else if ( nCommand == CommandEventId::CursorPos )
1630 // don't call InputChanged for CommandEventId::CursorPos
1632 else if ( nCommand == CommandEventId::InputLanguageChange )
1634 // #i55929# Font and font size state depends on input language if nothing is selected,
1635 // so the slots have to be invalidated when the input language is changed.
1637 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1638 if (pViewFrm)
1640 SfxBindings& rBindings = pViewFrm->GetBindings();
1641 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
1642 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
1645 else if ( nCommand == CommandEventId::Wheel )
1647 //don't call InputChanged for CommandEventId::Wheel
1649 else
1650 SC_MOD()->InputChanged( pEditView );
1652 else
1653 Window::Command(rCEvt); // Or else let the base class handle it...
1655 bInputMode = false;
1658 void ScTextWnd::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
1660 if ( pEditView )
1662 CommandEvent aDragEvent( rPosPixel, CommandEventId::StartDrag, true );
1663 pEditView->Command( aDragEvent );
1665 // handling of d&d to different view (CancelHandler) can't be done here,
1666 // because the call returns before d&d is complete.
1670 void ScTextWnd::KeyInput(const KeyEvent& rKEvt)
1672 bInputMode = true;
1673 if (!SC_MOD()->InputKeyEvent( rKEvt ))
1675 bool bUsed = false;
1676 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1677 if ( pViewSh )
1678 bUsed = pViewSh->SfxKeyInput(rKEvt); // Only accelerators, no input
1679 if (!bUsed)
1680 Window::KeyInput( rKEvt );
1682 bInputMode = false;
1685 void ScTextWnd::GetFocus()
1687 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1688 if ( pViewSh )
1689 pViewSh->SetFormShellAtTop( false ); // focus in input line -> FormShell no longer on top
1692 void ScTextWnd::LoseFocus()
1696 OUString ScTextWnd::GetText() const
1698 // Override to get the text via the testtool
1699 if ( pEditEngine )
1700 return pEditEngine->GetText();
1701 else
1702 return GetTextString();
1705 void ScTextWnd::SetFormulaMode( bool bSet )
1707 if ( bSet != bFormulaMode )
1709 bFormulaMode = bSet;
1710 UpdateAutoCorrFlag();
1714 void ScTextWnd::UpdateAutoCorrFlag()
1716 if ( pEditEngine )
1718 EEControlBits nControl = pEditEngine->GetControlWord();
1719 EEControlBits nOld = nControl;
1720 if ( bFormulaMode )
1721 nControl &= ~EEControlBits::AUTOCORRECT; // No AutoCorrect in Formulas
1722 else
1723 nControl |= EEControlBits::AUTOCORRECT; // Else do enable it
1725 if ( nControl != nOld )
1726 pEditEngine->SetControlWord( nControl );
1730 void ScTextWnd::StartEditEngine()
1732 // Don't activate if we're a modal ourselves (Doc modal Dialog)
1733 SfxObjectShell* pObjSh = SfxObjectShell::Current();
1734 if ( pObjSh && pObjSh->IsInModalMode() )
1735 return;
1737 if ( !pEditView || !pEditEngine )
1739 ScFieldEditEngine* pNew;
1740 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1741 if ( pViewSh )
1743 ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
1744 pNew = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
1746 else
1747 pNew = new ScFieldEditEngine(NULL, EditEngine::CreatePool(), NULL, true);
1748 pNew->SetExecuteURL( false );
1749 pEditEngine = pNew;
1751 pEditEngine->SetUpdateMode( false );
1752 pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
1753 pEditEngine->SetWordDelimiters(
1754 ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1756 UpdateAutoCorrFlag();
1759 SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1760 EditEngine::SetFontInfoInItemSet( *pSet, aTextFont );
1761 lcl_ExtendEditFontAttribs( *pSet );
1763 // turn off script spacing to match DrawText output
1764 pSet->Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) );
1765 if ( bIsRTL )
1766 lcl_ModifyRTLDefaults( *pSet );
1767 pEditEngine->SetDefaults( pSet );
1770 // If the Cell contains URLFields, they need to be taken over into the entry row,
1771 // or else the position is not correct anymore
1772 bool bFilled = false;
1773 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1774 if ( pHdl ) //! Check if it's the right InputHdl?
1775 bFilled = pHdl->GetTextAndFields( *pEditEngine );
1777 pEditEngine->SetUpdateMode( true );
1779 // aString is the truth...
1780 if (bFilled && pEditEngine->GetText() == aString)
1781 Invalidate(); // Repaint for (filled) Fields
1782 else
1783 pEditEngine->SetText(aString); // At least the right text then
1785 pEditView = new EditView( pEditEngine, this );
1786 pEditView->SetInsertMode(bIsInsertMode);
1788 // The text from the Clipboard is taken over as ASCII in a single row
1789 EVControlBits n = pEditView->GetControlWord();
1790 pEditView->SetControlWord( n | EVControlBits::SINGLELINEPASTE );
1792 pEditEngine->InsertView( pEditView, EE_APPEND );
1794 Resize();
1796 if ( bIsRTL )
1797 lcl_ModifyRTLVisArea( pEditView );
1799 pEditEngine->SetModifyHdl(LINK(this, ScTextWnd, NotifyHdl));
1801 if (!maAccTextDatas.empty())
1802 maAccTextDatas.back()->StartEdit();
1804 // as long as EditEngine and DrawText sometimes differ for CTL text,
1805 // repaint now to have the EditEngine's version visible
1806 // SfxObjectShell* pObjSh = SfxObjectShell::Current();
1807 if ( pObjSh && pObjSh->ISA(ScDocShell) )
1809 ScDocument& rDoc = static_cast<ScDocShell*>(pObjSh)->GetDocument(); // any document
1810 SvtScriptType nScript = rDoc.GetStringScriptType( aString );
1811 if ( nScript & SvtScriptType::COMPLEX )
1812 Invalidate();
1816 SC_MOD()->SetInputMode( SC_INPUT_TOP );
1818 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1819 if (pViewFrm)
1820 pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
1823 IMPL_LINK_NOARG(ScTextWnd, NotifyHdl)
1825 if (pEditView && !bInputMode)
1827 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1829 // Use the InputHandler's InOwnChange flag to prevent calling InputChanged
1830 // while an InputHandler method is modifying the EditEngine content
1832 if ( pHdl && !pHdl->IsInOwnChange() )
1833 pHdl->InputChanged( pEditView, true ); // #i20282# InputChanged must know if called from modify handler
1836 return 0;
1839 void ScTextWnd::StopEditEngine( bool bAll )
1841 if (pEditView)
1843 if (!maAccTextDatas.empty())
1844 maAccTextDatas.back()->EndEdit();
1846 ScModule* pScMod = SC_MOD();
1848 if (!bAll)
1849 pScMod->InputSelection( pEditView );
1850 aString = pEditEngine->GetText();
1851 bIsInsertMode = pEditView->IsInsertMode();
1852 bool bSelection = pEditView->HasSelection();
1853 pEditEngine->SetModifyHdl(Link<>());
1854 DELETEZ(pEditView);
1855 DELETEZ(pEditEngine);
1857 if ( pScMod->IsEditMode() && !bAll )
1858 pScMod->SetInputMode(SC_INPUT_TABLE);
1860 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1861 if (pViewFrm)
1862 pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
1864 if (bSelection)
1865 Invalidate(); // So that the Selection is not left there
1869 static sal_Int32 findFirstNonMatchingChar(const OUString& rStr1, const OUString& rStr2)
1871 // Search the string for unmatching chars
1872 const sal_Unicode* pStr1 = rStr1.getStr();
1873 const sal_Unicode* pStr2 = rStr2.getStr();
1874 sal_Int32 i = 0;
1875 while ( i < rStr1.getLength() )
1877 // Abort on the first unmatching char
1878 if ( *pStr1 != *pStr2 )
1879 return i;
1880 ++pStr1,
1881 ++pStr2,
1882 ++i;
1885 return i;
1888 void ScTextWnd::SetTextString( const OUString& rNewString )
1890 if ( rNewString != aString )
1892 bInputMode = true;
1894 // Find position of the change, only paint the rest
1895 if (!pEditEngine)
1897 bool bPaintAll;
1898 if ( bIsRTL )
1899 bPaintAll = true;
1900 else
1902 // test if CTL script type is involved
1903 SvtScriptType nOldScript = SvtScriptType::NONE;
1904 SvtScriptType nNewScript = SvtScriptType::NONE;
1905 SfxObjectShell* pObjSh = SfxObjectShell::Current();
1906 if ( pObjSh && pObjSh->ISA(ScDocShell) )
1908 // any document can be used (used only for its break iterator)
1909 ScDocument& rDoc = static_cast<ScDocShell*>(pObjSh)->GetDocument();
1910 nOldScript = rDoc.GetStringScriptType( aString );
1911 nNewScript = rDoc.GetStringScriptType( rNewString );
1913 bPaintAll = ( nOldScript & SvtScriptType::COMPLEX ) || ( nNewScript & SvtScriptType::COMPLEX );
1916 if ( bPaintAll )
1918 // if CTL is involved, the whole text has to be redrawn
1919 Invalidate();
1921 else
1923 long nTextSize = 0;
1924 sal_Int32 nDifPos;
1925 if (rNewString.getLength() > aString.getLength())
1926 nDifPos = findFirstNonMatchingChar(rNewString, aString);
1927 else
1928 nDifPos = findFirstNonMatchingChar(aString, rNewString);
1930 long nSize1 = GetTextWidth(aString);
1931 long nSize2 = GetTextWidth(rNewString);
1932 if ( nSize1>0 && nSize2>0 )
1933 nTextSize = std::max( nSize1, nSize2 );
1934 else
1935 nTextSize = GetOutputSize().Width(); // Overflow
1937 Point aLogicStart = PixelToLogic(Point(0,0));
1938 long nStartPos = aLogicStart.X();
1939 long nInvPos = nStartPos;
1940 if (nDifPos)
1941 nInvPos += GetTextWidth(aString,0,nDifPos);
1943 sal_uInt16 nFlags = 0;
1944 if ( nDifPos == aString.getLength() ) // only new characters appended
1945 nFlags = INVALIDATE_NOERASE; // then background is already clear
1947 Invalidate( Rectangle( nInvPos, 0, nStartPos+nTextSize, GetOutputSize().Height()-1 ), nFlags );
1950 else
1952 pEditEngine->SetText(rNewString);
1955 aString = rNewString;
1957 if (!maAccTextDatas.empty())
1958 maAccTextDatas.back()->TextChanged();
1960 bInputMode = false;
1964 const OUString& ScTextWnd::GetTextString() const
1966 return aString;
1969 bool ScTextWnd::IsInputActive()
1971 return HasFocus();
1974 EditView* ScTextWnd::GetEditView()
1976 return pEditView;
1979 void ScTextWnd::MakeDialogEditView()
1981 if ( pEditView ) return;
1983 ScFieldEditEngine* pNew;
1984 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1985 if ( pViewSh )
1987 ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
1988 pNew = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
1990 else
1991 pNew = new ScFieldEditEngine(NULL, EditEngine::CreatePool(), NULL, true);
1992 pNew->SetExecuteURL( false );
1993 pEditEngine = pNew;
1995 pEditEngine->SetUpdateMode( false );
1996 pEditEngine->SetWordDelimiters( pEditEngine->GetWordDelimiters() + "=" );
1997 pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
1999 SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
2000 EditEngine::SetFontInfoInItemSet( *pSet, aTextFont );
2001 lcl_ExtendEditFontAttribs( *pSet );
2002 if ( bIsRTL )
2003 lcl_ModifyRTLDefaults( *pSet );
2004 pEditEngine->SetDefaults( pSet );
2005 pEditEngine->SetUpdateMode( true );
2007 pEditView = new EditView( pEditEngine, this );
2008 pEditEngine->InsertView( pEditView, EE_APPEND );
2010 Resize();
2012 if ( bIsRTL )
2013 lcl_ModifyRTLVisArea( pEditView );
2015 if (!maAccTextDatas.empty())
2016 maAccTextDatas.back()->StartEdit();
2019 void ScTextWnd::ImplInitSettings()
2021 bIsRTL = AllSettings::GetLayoutRTL();
2023 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2025 Color aBgColor= rStyleSettings.GetWindowColor();
2026 Color aTxtColor= rStyleSettings.GetWindowTextColor();
2028 aTextFont.SetFillColor ( aBgColor );
2029 aTextFont.SetColor (aTxtColor);
2030 SetBackground ( aBgColor );
2031 Invalidate();
2034 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ScTextWnd::CreateAccessible()
2036 return new ScAccessibleEditObject(GetAccessibleParentWindow()->GetAccessible(), NULL, this,
2037 OUString(ScResId(STR_ACC_EDITLINE_NAME)),
2038 OUString(ScResId(STR_ACC_EDITLINE_DESCR)), ScAccessibleEditObject::EditLine);
2041 void ScTextWnd::InsertAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
2043 OSL_ENSURE( ::std::find( maAccTextDatas.begin(), maAccTextDatas.end(), &rTextData ) == maAccTextDatas.end(),
2044 "ScTextWnd::InsertAccessibleTextData - passed object already registered" );
2045 maAccTextDatas.push_back( &rTextData );
2048 void ScTextWnd::RemoveAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
2050 AccTextDataVector::iterator aEnd = maAccTextDatas.end();
2051 AccTextDataVector::iterator aIt = ::std::find( maAccTextDatas.begin(), aEnd, &rTextData );
2052 OSL_ENSURE( aIt != aEnd, "ScTextWnd::RemoveAccessibleTextData - passed object not registered" );
2053 if( aIt != aEnd )
2054 maAccTextDatas.erase( aIt );
2057 void ScTextWnd::DataChanged( const DataChangedEvent& rDCEvt )
2059 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2060 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
2062 ImplInitSettings();
2063 Invalidate();
2065 else
2066 Window::DataChanged( rDCEvt );
2069 void ScTextWnd::TextGrabFocus()
2071 GrabFocus();
2074 // Position window
2076 ScPosWnd::ScPosWnd( vcl::Window* pParent ) :
2077 ComboBox ( pParent, WinBits(WB_HIDE | WB_DROPDOWN) ),
2078 pAccel ( NULL ),
2079 nTipVisible ( 0 ),
2080 bFormulaMode( false )
2082 Size aSize( GetTextWidth( OUString("GW99999:GW99999") ),
2083 GetTextHeight() );
2084 aSize.Width() += 25; // FIXME: ??
2085 aSize.Height() = CalcWindowSizePixel(11); // Functions: 10 MRU + "others..."
2086 SetSizePixel( aSize );
2088 FillRangeNames();
2090 StartListening( *SfxGetpApp() ); // For Navigator rangename updates
2093 ScPosWnd::~ScPosWnd()
2095 disposeOnce();
2098 void ScPosWnd::dispose()
2100 EndListening( *SfxGetpApp() );
2102 HideTip();
2104 delete pAccel;
2105 ComboBox::dispose();
2108 void ScPosWnd::SetFormulaMode( bool bSet )
2110 if ( bSet != bFormulaMode )
2112 bFormulaMode = bSet;
2114 if ( bSet )
2115 FillFunctions();
2116 else
2117 FillRangeNames();
2119 HideTip();
2123 void ScPosWnd::SetPos( const OUString& rPosStr )
2125 if ( aPosStr != rPosStr )
2127 aPosStr = rPosStr;
2128 SetText(aPosStr);
2132 namespace {
2134 OUString createLocalRangeName(const OUString& rName, const OUString& rTableName)
2136 OUStringBuffer aString (rName);
2137 aString.append(" (");
2138 aString.append(rTableName);
2139 aString.append(")");
2140 return aString.makeStringAndClear();
2145 void ScPosWnd::FillRangeNames()
2147 Clear();
2149 SfxObjectShell* pObjSh = SfxObjectShell::Current();
2150 if ( pObjSh && pObjSh->ISA(ScDocShell) )
2152 ScDocument& rDoc = static_cast<ScDocShell*>(pObjSh)->GetDocument();
2154 InsertEntry(ScGlobal::GetRscString( STR_MANAGE_NAMES ));
2155 SetSeparatorPos(0);
2157 ScRange aDummy;
2158 std::set<OUString> aSet;
2159 ScRangeName* pRangeNames = rDoc.GetRangeName();
2160 if (!pRangeNames->empty())
2162 ScRangeName::const_iterator itrBeg = pRangeNames->begin(), itrEnd = pRangeNames->end();
2163 for (ScRangeName::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
2165 if (itr->second->IsValidReference(aDummy))
2166 aSet.insert(itr->second->GetName());
2169 for (SCTAB i = 0; i < rDoc.GetTableCount(); ++i)
2171 ScRangeName* pLocalRangeName = rDoc.GetRangeName(i);
2172 if (pLocalRangeName && !pLocalRangeName->empty())
2174 OUString aTableName;
2175 rDoc.GetName(i, aTableName);
2176 for (ScRangeName::const_iterator itr = pLocalRangeName->begin(); itr != pLocalRangeName->end(); ++itr)
2178 if (itr->second->IsValidReference(aDummy))
2179 aSet.insert(createLocalRangeName(itr->second->GetName(), aTableName));
2184 if (!aSet.empty())
2186 for (std::set<OUString>::iterator itr = aSet.begin();
2187 itr != aSet.end(); ++itr)
2189 InsertEntry(*itr);
2193 SetText(aPosStr);
2196 void ScPosWnd::FillFunctions()
2198 Clear();
2200 OUString aFirstName;
2201 const ScAppOptions& rOpt = SC_MOD()->GetAppOptions();
2202 sal_uInt16 nMRUCount = rOpt.GetLRUFuncListCount();
2203 const sal_uInt16* pMRUList = rOpt.GetLRUFuncList();
2204 if (pMRUList)
2206 const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
2207 sal_uLong nListCount = pFuncList->GetCount();
2208 for (sal_uInt16 i=0; i<nMRUCount; i++)
2210 sal_uInt16 nId = pMRUList[i];
2211 for (sal_uLong j=0; j<nListCount; j++)
2213 const ScFuncDesc* pDesc = pFuncList->GetFunction( j );
2214 if ( pDesc->nFIndex == nId && pDesc->pFuncName )
2216 InsertEntry( *pDesc->pFuncName );
2217 if (aFirstName.isEmpty())
2218 aFirstName = *pDesc->pFuncName;
2219 break; // Stop searching
2225 //! Re-add entry "Other..." for Function AutoPilot if it can work with text that
2226 // has been entered so far
2228 // InsertEntry( ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) );
2230 SetText(aFirstName);
2233 void ScPosWnd::Notify( SfxBroadcaster&, const SfxHint& rHint )
2235 if ( !bFormulaMode )
2237 // Does the list of range names need updating?
2238 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
2239 if ( pSimpleHint )
2241 sal_uLong nHintId = pSimpleHint->GetId();
2242 if ( nHintId == SC_HINT_AREAS_CHANGED || nHintId == SC_HINT_NAVIGATOR_UPDATEALL)
2243 FillRangeNames();
2245 else if ( dynamic_cast<const SfxEventHint*>(&rHint) )
2247 sal_uLong nEventId = static_cast<const SfxEventHint*>(&rHint)->GetEventId();
2248 if ( nEventId == SFX_EVENT_ACTIVATEDOC )
2249 FillRangeNames();
2254 void ScPosWnd::HideTip()
2256 if ( nTipVisible )
2258 Help::HideTip( nTipVisible );
2259 nTipVisible = 0;
2263 static ScNameInputType lcl_GetInputType( const OUString& rText )
2265 ScNameInputType eRet = SC_NAME_INPUT_BAD_NAME; // the more general error
2267 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2268 if ( pViewSh )
2270 ScViewData& rViewData = pViewSh->GetViewData();
2271 ScDocument* pDoc = rViewData.GetDocument();
2272 SCTAB nTab = rViewData.GetTabNo();
2273 formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
2275 // test in same order as in SID_CURRENTCELL execute
2277 ScRange aRange;
2278 ScAddress aAddress;
2279 ScRangeUtil aRangeUtil;
2280 SCTAB nNameTab;
2281 sal_Int32 nNumeric;
2283 if (rText == ScGlobal::GetRscString(STR_MANAGE_NAMES))
2284 eRet = SC_MANAGE_NAMES;
2285 else if ( aRange.Parse( rText, pDoc, eConv ) & SCA_VALID )
2286 eRet = SC_NAME_INPUT_RANGE;
2287 else if ( aAddress.Parse( rText, pDoc, eConv ) & SCA_VALID )
2288 eRet = SC_NAME_INPUT_CELL;
2289 else if ( ScRangeUtil::MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_NAMES, eConv ) )
2290 eRet = SC_NAME_INPUT_NAMEDRANGE;
2291 else if ( ScRangeUtil::MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_DBASE, eConv ) )
2292 eRet = SC_NAME_INPUT_DATABASE;
2293 else if ( comphelper::string::isdigitAsciiString( rText ) &&
2294 ( nNumeric = rText.toInt32() ) > 0 && nNumeric <= MAXROW+1 )
2295 eRet = SC_NAME_INPUT_ROW;
2296 else if ( pDoc->GetTable( rText, nNameTab ) )
2297 eRet = SC_NAME_INPUT_SHEET;
2298 else if ( ScRangeData::IsNameValid( rText, pDoc ) ) // nothing found, create new range?
2300 if ( rViewData.GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
2301 eRet = SC_NAME_INPUT_DEFINE;
2302 else
2303 eRet = SC_NAME_INPUT_BAD_SELECTION;
2305 else
2306 eRet = SC_NAME_INPUT_BAD_NAME;
2309 return eRet;
2312 void ScPosWnd::Modify()
2314 ComboBox::Modify();
2316 HideTip();
2318 if ( !IsTravelSelect() && !bFormulaMode )
2320 // determine the action that would be taken for the current input
2322 ScNameInputType eType = lcl_GetInputType( GetText() ); // uses current view
2323 sal_uInt16 nStrId = 0;
2324 switch ( eType )
2326 case SC_NAME_INPUT_CELL:
2327 nStrId = STR_NAME_INPUT_CELL;
2328 break;
2329 case SC_NAME_INPUT_RANGE:
2330 case SC_NAME_INPUT_NAMEDRANGE:
2331 nStrId = STR_NAME_INPUT_RANGE; // named range or range reference
2332 break;
2333 case SC_NAME_INPUT_DATABASE:
2334 nStrId = STR_NAME_INPUT_DBRANGE;
2335 break;
2336 case SC_NAME_INPUT_ROW:
2337 nStrId = STR_NAME_INPUT_ROW;
2338 break;
2339 case SC_NAME_INPUT_SHEET:
2340 nStrId = STR_NAME_INPUT_SHEET;
2341 break;
2342 case SC_NAME_INPUT_DEFINE:
2343 nStrId = STR_NAME_INPUT_DEFINE;
2344 break;
2345 default:
2346 // other cases (error): no tip help
2347 break;
2350 if ( nStrId )
2352 // show the help tip at the text cursor position
2354 vcl::Window* pWin = GetSubEdit();
2355 if (!pWin)
2356 pWin = this;
2357 Point aPos;
2358 vcl::Cursor* pCur = pWin->GetCursor();
2359 if (pCur)
2360 aPos = pWin->LogicToPixel( pCur->GetPos() );
2361 aPos = pWin->OutputToScreenPixel( aPos );
2362 Rectangle aRect( aPos, aPos );
2364 OUString aText = ScGlobal::GetRscString( nStrId );
2365 QuickHelpFlags nAlign = QuickHelpFlags::Left|QuickHelpFlags::Bottom;
2366 nTipVisible = Help::ShowTip(pWin, aRect, aText, nAlign);
2371 void ScPosWnd::Select()
2373 ComboBox::Select(); // In VCL GetText() only return the selected entry afterwards
2375 HideTip();
2377 if (!IsTravelSelect())
2378 DoEnter();
2381 void ScPosWnd::DoEnter()
2383 OUString aText = GetText();
2384 if ( !aText.isEmpty() )
2386 if ( bFormulaMode )
2388 ScModule* pScMod = SC_MOD();
2389 if ( aText == ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) )
2391 // Function AutoPilot
2392 //! Continue working with the text entered so far
2394 //! new method at ScModule to query if function autopilot is open
2395 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
2396 if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
2397 pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
2398 SfxCallMode::SYNCHRON | SfxCallMode::RECORD );
2400 else
2402 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
2403 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
2404 if (pHdl)
2405 pHdl->InsertFunction( aText );
2408 else
2410 // depending on the input, select something or create a new named range
2412 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2413 if ( pViewSh )
2415 ScViewData& rViewData = pViewSh->GetViewData();
2416 ScDocShell* pDocShell = rViewData.GetDocShell();
2417 ScDocument& rDoc = pDocShell->GetDocument();
2419 ScNameInputType eType = lcl_GetInputType( aText );
2420 if ( eType == SC_NAME_INPUT_BAD_NAME || eType == SC_NAME_INPUT_BAD_SELECTION )
2422 sal_uInt16 nId = ( eType == SC_NAME_INPUT_BAD_NAME ) ? STR_NAME_ERROR_NAME : STR_NAME_ERROR_SELECTION;
2423 pViewSh->ErrorMessage( nId );
2425 else if ( eType == SC_NAME_INPUT_DEFINE )
2427 ScRangeName* pNames = rDoc.GetRangeName();
2428 ScRange aSelection;
2429 if ( pNames && !pNames->findByUpperName(ScGlobal::pCharClass->uppercase(aText)) &&
2430 (rViewData.GetSimpleArea( aSelection ) == SC_MARK_SIMPLE) )
2432 ScRangeName aNewRanges( *pNames );
2433 ScAddress aCursor( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() );
2434 OUString aContent(aSelection.Format(SCR_ABS_3D, &rDoc, rDoc.GetAddressConvention()));
2435 ScRangeData* pNew = new ScRangeData( &rDoc, aText, aContent, aCursor );
2436 if ( aNewRanges.insert(pNew) )
2438 pDocShell->GetDocFunc().ModifyRangeNames( aNewRanges );
2439 pViewSh->UpdateInputHandler(true);
2443 else if (eType == SC_MANAGE_NAMES)
2445 sal_uInt16 nId = ScNameDlgWrapper::GetChildWindowId();
2446 SfxViewFrame* pViewFrm = pViewSh->GetViewFrame();
2447 SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId );
2449 SC_MOD()->SetRefDialog( nId, pWnd == nullptr );
2451 else
2453 // for all selection types, execute the SID_CURRENTCELL slot.
2454 if (eType == SC_NAME_INPUT_CELL || eType == SC_NAME_INPUT_RANGE)
2456 // Note that SID_CURRENTCELL always expects address to
2457 // be in Calc A1 format. Convert the text.
2458 ScRange aRange(0,0, rViewData.GetTabNo());
2459 aRange.ParseAny(aText, &rDoc, rDoc.GetAddressConvention());
2460 aText = aRange.Format(SCR_ABS_3D, &rDoc, ::formula::FormulaGrammar::CONV_OOO);
2463 SfxStringItem aPosItem( SID_CURRENTCELL, aText );
2464 SfxBoolItem aUnmarkItem( FN_PARAM_1, true ); // remove existing selection
2466 pViewSh->GetViewData().GetDispatcher().Execute( SID_CURRENTCELL,
2467 SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
2468 &aPosItem, &aUnmarkItem, 0L );
2473 else
2474 SetText( aPosStr );
2476 ReleaseFocus_Impl();
2479 bool ScPosWnd::Notify( NotifyEvent& rNEvt )
2481 bool bHandled = true;
2483 switch (rNEvt.GetType())
2485 case MouseNotifyEvent::KEYINPUT:
2487 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
2489 switch ( pKEvt->GetKeyCode().GetCode() )
2491 case KEY_RETURN:
2492 DoEnter();
2493 break;
2495 case KEY_ESCAPE:
2496 if (nTipVisible)
2498 // escape when the tip help is shown: only hide the tip
2499 HideTip();
2501 else
2503 if (!bFormulaMode)
2504 SetText( aPosStr );
2505 ReleaseFocus_Impl();
2507 break;
2509 default:
2510 bHandled = false;
2511 break;
2514 break;
2515 case MouseNotifyEvent::GETFOCUS:
2517 // Select the whole text upon focus.
2518 OUString aStr = GetText();
2519 SetSelection(Selection(0, aStr.getLength()));
2521 break;
2522 case MouseNotifyEvent::LOSEFOCUS:
2523 HideTip();
2524 bHandled = false;
2525 break;
2526 default:
2527 bHandled = false;
2530 if (!bHandled)
2531 bHandled = ComboBox::Notify(rNEvt);
2533 return bHandled;
2536 void ScPosWnd::ReleaseFocus_Impl()
2538 HideTip();
2540 SfxViewShell* pCurSh = SfxViewShell::Current();
2541 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( PTR_CAST( ScTabViewShell, pCurSh ) );
2542 if ( pHdl && pHdl->IsTopMode() )
2544 // Focus back in input row?
2545 ScInputWindow* pInputWin = pHdl->GetInputWindow();
2546 if (pInputWin)
2548 pInputWin->TextGrabFocus();
2549 return;
2553 // Set focus to active View
2554 if ( pCurSh )
2556 vcl::Window* pShellWnd = pCurSh->GetWindow();
2558 if ( pShellWnd )
2559 pShellWnd->GrabFocus();
2563 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */