1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
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>
45 #include "inputwin.hxx"
47 #include "uiitems.hxx"
49 #include "scresid.hxx"
51 #include "globstr.hrc"
52 #include "reffact.hxx"
53 #include "editutil.hxx"
54 #include "inputhdl.hxx"
55 #include "tabvwsh.hxx"
56 #include "document.hxx"
58 #include "appoptio.hxx"
59 #include "rangenam.hxx"
60 #include <formula/compiler.hrc>
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?
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
;
97 SC_NAME_INPUT_NAMEDRANGE
,
98 SC_NAME_INPUT_DATABASE
,
101 SC_NAME_INPUT_DEFINE
,
102 SC_NAME_INPUT_BAD_NAME
,
103 SC_NAME_INPUT_BAD_SELECTION
,
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
,
123 SfxBindings
* pBindings
,
124 SfxChildWinInfo
* /* pInfo */ )
125 : SfxChildWindow( pParentP
, nId
)
127 VclPtr
<ScInputWindow
> pWin
=VclPtr
<ScInputWindow
>::Create( pParentP
, pBindings
);
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();
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
155 // class ScInputWindow
157 static VclPtr
<ScTextWndBase
> lcl_chooseRuntimeImpl( vcl::Window
* pParent
, SfxBindings
* pBind
)
159 ScTabViewShell
* pViewSh
= NULL
;
160 SfxDispatcher
* pDisp
= pBind
->GetDispatcher();
163 SfxViewFrame
* pViewFrm
= pDisp
->GetFrame();
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
),
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
) ),
185 bIsOkCancelMode ( 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();
198 SfxViewFrame
* pViewFrm
= pDisp
->GetFrame();
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);
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);
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
233 pInputHdl
= SC_MOD()->GetInputHdl( pViewSh
, false ); // use own handler even if ref-handler is set
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
254 pViewSh
->UpdateInputHandler(true); // Absolutely necessary update
256 pImgMgr
->RegisterToolBox(this);
257 SetAccessibleName(ScResId(STR_ACC_TOOLBAR_FORMULA
));
260 ScInputWindow::~ScInputWindow()
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
275 TypeId aScType
= TYPE(ScTabViewShell
);
276 SfxViewShell
* pSh
= SfxViewShell::GetFirst( &aScType
);
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();
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!
306 pInputHdl
->SetInputWindow( this );
310 bool ScInputWindow::UseSubTotal(ScRangeList
* pRangeList
)
312 bool bSubTotal
= false;
313 ScTabViewShell
* pViewSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
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
];
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
))
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())
352 while (!bSubTotal
&& nRangeIndex
< nRangeCount
)
354 const ScRange
* pRange
= (*pRangeList
)[nRangeIndex
];
358 rDB
.GetArea(aDBArea
);
359 if (aDBArea
.Intersects(*pRange
))
369 void ScInputWindow::Select()
371 ScModule
* pScMod
= SC_MOD();
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();
392 case SID_INPUT_CANCEL
:
393 pScMod
->InputCancelHandler();
398 pScMod
->InputEnterHandler();
400 aTextWindow
.Invalidate(); // Or else the Selection remains
405 ScTabViewShell
* pViewSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
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
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() ) )
432 ScRangeList aRangeList
;
433 const bool bDataFound
= pViewSh
->GetAutoSumArea( aRangeList
);
436 ScAddress aAddr
= aRangeList
.back()->aEnd
;
438 const bool bSubTotal( UseSubTotal( &aRangeList
) );
439 pViewSh
->EnterAutoSum( aRangeList
, bSubTotal
, aAddr
);
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
;
457 const OUString aFormula
= pViewSh
->GetAutoSumFormula(
458 aRangeList
, bSubTotal
, aAddr
);
459 SetFuncString( aFormula
);
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
);
479 pHdl
->InitRangeFinder( aFormula
);
481 //! SetSelection at the InputHandler?
483 const sal_Int32 nOpen
= aFormula
.indexOf('(');
484 const sal_Int32 nLen
= aFormula
.getLength();
485 if ( nOpen
!= -1 && nLen
> nOpen
)
490 ESelection
aSel(0,nOpen
+nAdd
,0,nLen
-1);
491 EditView
* pTableView
= pHdl
->GetTableView();
493 pTableView
->SetSelection(aSel
);
494 EditView
* pTopView
= pHdl
->GetTopView();
496 pTopView
->SetSelection(aSel
);
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() );
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() );
528 aTextWindow
.SetTextString("=" + rString
);
531 case CELLTYPE_STRING
:
536 case CELLTYPE_FORMULA
:
540 aTextWindow
.SetTextString("=");
545 EditView
* pView
= aTextWindow
.GetEditView();
548 pView
->SetSelection( ESelection(0, nStartPos
, 0, nEndPos
) );
549 pScMod
->InputChanged(pView
);
551 pView
->SetEditEngineUpdateMode(true);
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()
578 aTextWindow
.Resize();
579 Size aSize
= GetSizePixel();
580 aSize
.Height() = CalcWindowSizePixel().Height() + ADDITIONAL_BORDER
;
581 ScInputBarGroup
* pGroupBar
= dynamic_cast< ScInputBarGroup
* > ( pRuntimeWindow
.get() );
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
;
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() )
620 aTextWindow
.GrabFocus();
621 aTextWindow
.SetTextString( rString
);
622 EditView
* pView
= aTextWindow
.GetEditView();
625 sal_Int32 nLen
= rString
.getLength();
630 pView
->SetSelection( ESelection( 0, nLen
, 0, nLen
) );
633 pScMod
->InputChanged(pView
);
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
);
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
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
);
687 // Remove SID_INPUT_CANCEL, and SID_INPUT_OK
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();
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() )
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
);
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
) );
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 )
824 void ScInputWindow::MouseMove( const MouseEvent
& rMEvt
)
828 Point aPosPixel
= GetPointerPosPixel();
830 ScInputBarGroup
* pGroupBar
= dynamic_cast< ScInputBarGroup
* > ( pRuntimeWindow
.get() );
832 if ( bInResize
|| IsPointerAtResizePos() )
833 SetPointer( Pointer( PointerStyle::WindowSSize
) );
835 SetPointer( Pointer( PointerStyle::Arrow
) );
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;
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
)
874 if ( rMEvt
.IsLeft() )
876 if ( IsPointerAtResizePos() )
878 // Don't leave the mouse pointer leave *this* window
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
)
900 if ( rMEvt
.IsLeft() )
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
) ),
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
);
925 aButton
->SetSymbol( SymbolType::SPIN_DOWN
);
926 aButton
->SetQuickHelpText( ScResId( SCSTR_QHELP_EXPAND_FORMULA
) );
929 aScrollBar
->SetSizePixel( aSize
);
930 aScrollBar
->SetScrollHdl( LINK( this, ScInputBarGroup
, Impl_ScrollHdl
) );
933 ScInputBarGroup::~ScInputBarGroup()
938 void ScInputBarGroup::dispose()
940 aMultiTextWnd
.disposeAndClear();
941 aButton
.disposeAndClear();
942 aScrollBar
.disposeAndClear();
943 ScTextWndBase::dispose();
947 ScInputBarGroup::InsertAccessibleTextData( ScAccessibleEditLineTextData
& rTextData
)
949 aMultiTextWnd
->InsertAccessibleTextData( rTextData
);
953 ScInputBarGroup::RemoveAccessibleTextData( ScAccessibleEditLineTextData
& rTextData
)
955 aMultiTextWnd
->RemoveAccessibleTextData( rTextData
);
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
);
977 OSL_FAIL("The parent window pointer pParent is null");
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();
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();
1019 aButton
->SetSymbol( SymbolType::SPIN_DOWN
);
1020 aButton
->SetQuickHelpText( ScResId( SCSTR_QHELP_EXPAND_FORMULA
) );
1024 aButton
->SetPosPixel(Point(aSize
.Width() - aButton
->GetSizePixel().Width(), 0));
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");
1085 if (aMultiTextWnd
->GetNumLines() > 1)
1087 aMultiTextWnd
->SetNumLines(1);
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();
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
1111 nVertOffset
= rParent
.GetItemPosRect( rParent
.GetItemCount() - 1 ).Top();
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
);
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
1146 // unlock relayouts the toolbars in the 4 quadrants
1147 xLayoutManager
->unlock();
1152 IMPL_LINK_NOARG(ScInputBarGroup
, Impl_ScrollHdl
)
1154 aMultiTextWnd
->DoScroll();
1158 void ScInputBarGroup::TextGrabFocus()
1160 aMultiTextWnd
->TextGrabFocus();
1163 ScMultiTextWnd::ScMultiTextWnd( ScInputBarGroup
* pParen
, ScTabViewShell
* pViewSh
)
1164 : ScTextWnd( pParen
, pViewSh
),
1165 mrGroupBar(* pParen
),
1167 mnLastExpandedLines( INPUTWIN_MULTILINES
),
1168 mbInvalidate( false )
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();
1186 pView
->Invalidate();
1187 mbInvalidate
= false;
1189 pEditView
->Paint(rRect
, &rRenderContext
);
1193 EditView
* ScMultiTextWnd::GetEditView()
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
)
1211 mnLastExpandedLines
= nLines
;
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
);
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
);
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();
1263 long ScMultiTextWnd::GetEditEngTxtHeight()
1265 return pEditView
? pEditView
->GetEditEngine()->GetTextHeight() : 0;
1268 void ScMultiTextWnd::SetScrollBarRange()
1272 ScrollBar
& rVBar
= mrGroupBar
.GetScrollBar();
1273 rVBar
.SetRange( Range( 0, GetEditEngTxtHeight() ) );
1274 long currentDocPos
= pEditView
->GetVisArea().TopLeft().Y();
1275 rVBar
.SetThumbPos( currentDocPos
);
1280 ScMultiTextWnd::DoScroll()
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() )
1300 if ( !pEditView
|| !pEditEngine
)
1305 SC_MOD()->SetInputMode( SC_INPUT_TOP
);
1307 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
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 );
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
;
1363 pDocSh
= pViewSh
->GetViewData().GetDocShell();
1364 ScDocument
* pDoc
= pViewSh
->GetViewData().GetDocument();
1365 pNew
= new ScFieldEditEngine(pDoc
, pDoc
->GetEnginePool(), pDoc
->GetEditPool());
1368 pNew
= new ScFieldEditEngine(NULL
, EditEngine::CreatePool(), NULL
, true);
1369 pNew
->SetExecuteURL( false );
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
) );
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
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
);
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
1430 ScDocument
& rDoc
= pDocSh
->GetDocument(); // any document
1431 SvtScriptType nScript
= rDoc
.GetStringScriptType( aString
);
1432 if ( nScript
& SvtScriptType::COMPLEX
)
1437 void ScMultiTextWnd::StopEditEngine( bool bAll
)
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();
1457 ScTextWnd::ScTextWnd( vcl::Window
* pParent
, ScTabViewShell
* pViewSh
)
1458 : ScTextWndBase(pParent
, WinBits(WB_HIDE
| WB_BORDER
)),
1459 DragSourceHelper(this),
1462 bIsInsertMode(true),
1463 bFormulaMode (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
);
1499 ScTextWnd::~ScTextWnd()
1504 void ScTextWnd::dispose()
1506 while (!maAccTextDatas
.empty()) {
1507 maAccTextDatas
.back()->Dispose();
1514 ScTextWndBase::dispose();
1517 void ScTextWnd::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& rRect
)
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
);
1529 Size aSize
= GetOutputSizePixel();
1532 long nDiff
= aSize
.Height() - rRenderContext
.LogicToPixel(Size(0, rRenderContext
.GetTextHeight())).Height();
1534 // if (nDiff<2) nDiff=2; // At least 1 pixel
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()
1554 void ScTextWnd::MouseMove( const MouseEvent
& rMEvt
)
1557 pEditView
->MouseMove( rMEvt
);
1560 void ScTextWnd::MouseButtonDown( const MouseEvent
& rMEvt
)
1565 if ( SC_MOD()->IsEditMode() )
1571 pEditView
->SetEditEngineUpdateMode( true );
1572 pEditView
->MouseButtonDown( rMEvt
);
1576 void ScTextWnd::MouseButtonUp( const MouseEvent
& rMEvt
)
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
);
1588 SC_MOD()->InputSelection( pEditView
);
1592 void ScTextWnd::Command( const CommandEvent
& rCEvt
)
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();
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
1650 SC_MOD()->InputChanged( pEditView
);
1653 Window::Command(rCEvt
); // Or else let the base class handle it...
1658 void ScTextWnd::StartDrag( sal_Int8
/* nAction */, const Point
& rPosPixel
)
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
)
1673 if (!SC_MOD()->InputKeyEvent( rKEvt
))
1676 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
1678 bUsed
= pViewSh
->SfxKeyInput(rKEvt
); // Only accelerators, no input
1680 Window::KeyInput( rKEvt
);
1685 void ScTextWnd::GetFocus()
1687 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
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
1700 return pEditEngine
->GetText();
1702 return GetTextString();
1705 void ScTextWnd::SetFormulaMode( bool bSet
)
1707 if ( bSet
!= bFormulaMode
)
1709 bFormulaMode
= bSet
;
1710 UpdateAutoCorrFlag();
1714 void ScTextWnd::UpdateAutoCorrFlag()
1718 EEControlBits nControl
= pEditEngine
->GetControlWord();
1719 EEControlBits nOld
= nControl
;
1721 nControl
&= ~EEControlBits::AUTOCORRECT
; // No AutoCorrect in Formulas
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() )
1737 if ( !pEditView
|| !pEditEngine
)
1739 ScFieldEditEngine
* pNew
;
1740 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
1743 ScDocument
* pDoc
= pViewSh
->GetViewData().GetDocument();
1744 pNew
= new ScFieldEditEngine(pDoc
, pDoc
->GetEnginePool(), pDoc
->GetEditPool());
1747 pNew
= new ScFieldEditEngine(NULL
, EditEngine::CreatePool(), NULL
, true);
1748 pNew
->SetExecuteURL( false );
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
) );
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
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
);
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
)
1816 SC_MOD()->SetInputMode( SC_INPUT_TOP
);
1818 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
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
1839 void ScTextWnd::StopEditEngine( bool bAll
)
1843 if (!maAccTextDatas
.empty())
1844 maAccTextDatas
.back()->EndEdit();
1846 ScModule
* pScMod
= SC_MOD();
1849 pScMod
->InputSelection( pEditView
);
1850 aString
= pEditEngine
->GetText();
1851 bIsInsertMode
= pEditView
->IsInsertMode();
1852 bool bSelection
= pEditView
->HasSelection();
1853 pEditEngine
->SetModifyHdl(Link
<>());
1855 DELETEZ(pEditEngine
);
1857 if ( pScMod
->IsEditMode() && !bAll
)
1858 pScMod
->SetInputMode(SC_INPUT_TABLE
);
1860 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
1862 pViewFrm
->GetBindings().Invalidate( SID_ATTR_INSERT
);
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();
1875 while ( i
< rStr1
.getLength() )
1877 // Abort on the first unmatching char
1878 if ( *pStr1
!= *pStr2
)
1888 void ScTextWnd::SetTextString( const OUString
& rNewString
)
1890 if ( rNewString
!= aString
)
1894 // Find position of the change, only paint the rest
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
);
1918 // if CTL is involved, the whole text has to be redrawn
1925 if (rNewString
.getLength() > aString
.getLength())
1926 nDifPos
= findFirstNonMatchingChar(rNewString
, aString
);
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
);
1935 nTextSize
= GetOutputSize().Width(); // Overflow
1937 Point aLogicStart
= PixelToLogic(Point(0,0));
1938 long nStartPos
= aLogicStart
.X();
1939 long nInvPos
= nStartPos
;
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
);
1952 pEditEngine
->SetText(rNewString
);
1955 aString
= rNewString
;
1957 if (!maAccTextDatas
.empty())
1958 maAccTextDatas
.back()->TextChanged();
1964 const OUString
& ScTextWnd::GetTextString() const
1969 bool ScTextWnd::IsInputActive()
1974 EditView
* ScTextWnd::GetEditView()
1979 void ScTextWnd::MakeDialogEditView()
1981 if ( pEditView
) return;
1983 ScFieldEditEngine
* pNew
;
1984 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
1987 ScDocument
* pDoc
= pViewSh
->GetViewData().GetDocument();
1988 pNew
= new ScFieldEditEngine(pDoc
, pDoc
->GetEnginePool(), pDoc
->GetEditPool());
1991 pNew
= new ScFieldEditEngine(NULL
, EditEngine::CreatePool(), NULL
, true);
1992 pNew
->SetExecuteURL( false );
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
);
2003 lcl_ModifyRTLDefaults( *pSet
);
2004 pEditEngine
->SetDefaults( pSet
);
2005 pEditEngine
->SetUpdateMode( true );
2007 pEditView
= new EditView( pEditEngine
, this );
2008 pEditEngine
->InsertView( pEditView
, EE_APPEND
);
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
);
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" );
2054 maAccTextDatas
.erase( aIt
);
2057 void ScTextWnd::DataChanged( const DataChangedEvent
& rDCEvt
)
2059 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
2060 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
2066 Window::DataChanged( rDCEvt
);
2069 void ScTextWnd::TextGrabFocus()
2076 ScPosWnd::ScPosWnd( vcl::Window
* pParent
) :
2077 ComboBox ( pParent
, WinBits(WB_HIDE
| WB_DROPDOWN
) ),
2080 bFormulaMode( false )
2082 Size
aSize( GetTextWidth( OUString("GW99999:GW99999") ),
2084 aSize
.Width() += 25; // FIXME: ??
2085 aSize
.Height() = CalcWindowSizePixel(11); // Functions: 10 MRU + "others..."
2086 SetSizePixel( aSize
);
2090 StartListening( *SfxGetpApp() ); // For Navigator rangename updates
2093 ScPosWnd::~ScPosWnd()
2098 void ScPosWnd::dispose()
2100 EndListening( *SfxGetpApp() );
2105 ComboBox::dispose();
2108 void ScPosWnd::SetFormulaMode( bool bSet
)
2110 if ( bSet
!= bFormulaMode
)
2112 bFormulaMode
= bSet
;
2123 void ScPosWnd::SetPos( const OUString
& rPosStr
)
2125 if ( aPosStr
!= rPosStr
)
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()
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
));
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
));
2186 for (std::set
<OUString
>::iterator itr
= aSet
.begin();
2187 itr
!= aSet
.end(); ++itr
)
2196 void ScPosWnd::FillFunctions()
2200 OUString aFirstName
;
2201 const ScAppOptions
& rOpt
= SC_MOD()->GetAppOptions();
2202 sal_uInt16 nMRUCount
= rOpt
.GetLRUFuncListCount();
2203 const sal_uInt16
* pMRUList
= rOpt
.GetLRUFuncList();
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
);
2241 sal_uLong nHintId
= pSimpleHint
->GetId();
2242 if ( nHintId
== SC_HINT_AREAS_CHANGED
|| nHintId
== SC_HINT_NAVIGATOR_UPDATEALL
)
2245 else if ( dynamic_cast<const SfxEventHint
*>(&rHint
) )
2247 sal_uLong nEventId
= static_cast<const SfxEventHint
*>(&rHint
)->GetEventId();
2248 if ( nEventId
== SFX_EVENT_ACTIVATEDOC
)
2254 void ScPosWnd::HideTip()
2258 Help::HideTip( nTipVisible
);
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();
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
2279 ScRangeUtil aRangeUtil
;
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
;
2303 eRet
= SC_NAME_INPUT_BAD_SELECTION
;
2306 eRet
= SC_NAME_INPUT_BAD_NAME
;
2312 void ScPosWnd::Modify()
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;
2326 case SC_NAME_INPUT_CELL
:
2327 nStrId
= STR_NAME_INPUT_CELL
;
2329 case SC_NAME_INPUT_RANGE
:
2330 case SC_NAME_INPUT_NAMEDRANGE
:
2331 nStrId
= STR_NAME_INPUT_RANGE
; // named range or range reference
2333 case SC_NAME_INPUT_DATABASE
:
2334 nStrId
= STR_NAME_INPUT_DBRANGE
;
2336 case SC_NAME_INPUT_ROW
:
2337 nStrId
= STR_NAME_INPUT_ROW
;
2339 case SC_NAME_INPUT_SHEET
:
2340 nStrId
= STR_NAME_INPUT_SHEET
;
2342 case SC_NAME_INPUT_DEFINE
:
2343 nStrId
= STR_NAME_INPUT_DEFINE
;
2346 // other cases (error): no tip help
2352 // show the help tip at the text cursor position
2354 vcl::Window
* pWin
= GetSubEdit();
2358 vcl::Cursor
* pCur
= pWin
->GetCursor();
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
2377 if (!IsTravelSelect())
2381 void ScPosWnd::DoEnter()
2383 OUString aText
= GetText();
2384 if ( !aText
.isEmpty() )
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
);
2402 ScTabViewShell
* pViewSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
2403 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( pViewSh
);
2405 pHdl
->InsertFunction( aText
);
2410 // depending on the input, select something or create a new named range
2412 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
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();
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 );
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 );
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() )
2498 // escape when the tip help is shown: only hide the tip
2505 ReleaseFocus_Impl();
2515 case MouseNotifyEvent::GETFOCUS
:
2517 // Select the whole text upon focus.
2518 OUString aStr
= GetText();
2519 SetSelection(Selection(0, aStr
.getLength()));
2522 case MouseNotifyEvent::LOSEFOCUS
:
2531 bHandled
= ComboBox::Notify(rNEvt
);
2536 void ScPosWnd::ReleaseFocus_Impl()
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();
2548 pInputWin
->TextGrabFocus();
2553 // Set focus to active View
2556 vcl::Window
* pShellWnd
= pCurSh
->GetWindow();
2559 pShellWnd
->GrabFocus();
2563 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */