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 <string_view>
24 #include <editeng/eeitem.hxx>
26 #include <sfx2/app.hxx>
27 #include <editeng/adjustitem.hxx>
28 #include <editeng/editview.hxx>
29 #include <editeng/editstat.hxx>
30 #include <editeng/lspcitem.hxx>
31 #include <editeng/fhgtitem.hxx>
32 #include <editeng/wghtitem.hxx>
33 #include <editeng/postitem.hxx>
34 #include <editeng/langitem.hxx>
35 #include <sfx2/bindings.hxx>
36 #include <sfx2/viewfrm.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/event.hxx>
39 #include <editeng/scriptspaceitem.hxx>
40 #include <vcl/commandevent.hxx>
41 #include <vcl/cursor.hxx>
42 #include <vcl/help.hxx>
43 #include <vcl/settings.hxx>
44 #include <svl/stritem.hxx>
45 #include <vcl/svapp.hxx>
46 #include <vcl/weldutils.hxx>
47 #include <unotools/charclass.hxx>
49 #include <inputwin.hxx>
52 #include <scresid.hxx>
53 #include <strings.hrc>
54 #include <globstr.hrc>
55 #include <bitmaps.hlst>
56 #include <reffact.hxx>
57 #include <editutil.hxx>
58 #include <inputhdl.hxx>
59 #include <tabvwsh.hxx>
60 #include <document.hxx>
62 #include <appoptio.hxx>
63 #include <rangenam.hxx>
64 #include <rangeutl.hxx>
65 #include <docfunc.hxx>
66 #include <funcdesc.hxx>
67 #include <editeng/fontitem.hxx>
68 #include <AccessibleEditObject.hxx>
69 #include <AccessibleText.hxx>
70 #include <comphelper/lok.hxx>
71 #include <comphelper/string.hxx>
72 #include <com/sun/star/frame/XLayoutManager.hpp>
76 namespace com::sun::star::accessibility
{ class XAccessible
; }
78 const tools::Long THESIZE
= 1000000; // Should be more than enough!
79 const tools::Long INPUTLINE_INSET_MARGIN
= 2; // Space between border and interior widgets of input line
80 const tools::Long LEFT_OFFSET
= 5; // Left offset of input line
81 //TODO const long BUTTON_OFFSET = 2; // Space between input line and button to expand/collapse
82 const tools::Long INPUTWIN_MULTILINES
= 6; // Initial number of lines within multiline dropdown
83 const tools::Long TOOLBOX_WINDOW_HEIGHT
= 22; // Height of toolbox window in pixels - TODO: The same on all systems?
84 const tools::Long POSITION_COMBOBOX_WIDTH
= 18; // Width of position combobox in characters
85 const int RESIZE_HOTSPOT_HEIGHT
= 4;
87 using com::sun::star::uno::Reference
;
88 using com::sun::star::uno::UNO_QUERY
;
90 using com::sun::star::frame::XLayoutManager
;
91 using com::sun::star::beans::XPropertySet
;
95 constexpr ToolBoxItemId
SID_INPUT_FUNCTION (SC_VIEW_START
+ 47);
96 constexpr ToolBoxItemId
SID_INPUT_SUM (SC_VIEW_START
+ 48);
97 constexpr ToolBoxItemId
SID_INPUT_EQUAL (SC_VIEW_START
+ 49);
98 constexpr ToolBoxItemId
SID_INPUT_CANCEL (SC_VIEW_START
+ 50);
99 constexpr ToolBoxItemId
SID_INPUT_OK (SC_VIEW_START
+ 51);
105 SC_NAME_INPUT_NAMEDRANGE_LOCAL
,
106 SC_NAME_INPUT_NAMEDRANGE_GLOBAL
,
107 SC_NAME_INPUT_DATABASE
,
110 SC_NAME_INPUT_DEFINE
,
111 SC_NAME_INPUT_BAD_NAME
,
112 SC_NAME_INPUT_BAD_SELECTION
,
118 SFX_IMPL_CHILDWINDOW_WITHID(ScInputWindowWrapper
,FID_INPUTLINE_STATUS
)
120 ScInputWindowWrapper::ScInputWindowWrapper( vcl::Window
* pParentP
,
122 SfxBindings
* pBindings
,
123 SfxChildWinInfo
* /* pInfo */ )
124 : SfxChildWindow( pParentP
, nId
)
126 VclPtr
<ScInputWindow
> pWin
= VclPtr
<ScInputWindow
>::Create( pParentP
, pBindings
);
131 pWin
->SetSizePixel( pWin
->CalcWindowSizePixel() );
133 SetAlignment(SfxChildAlignment::LOWESTTOP
);
134 pBindings
->Invalidate( FID_TOGGLEINPUTLINE
);
138 * GetInfo is disposed of if there's a SFX_IMPL_TOOLBOX!
140 SfxChildWinInfo
ScInputWindowWrapper::GetInfo() const
142 SfxChildWinInfo aInfo
= SfxChildWindow::GetInfo();
147 static VclPtr
<ScInputBarGroup
> lcl_chooseRuntimeImpl( vcl::Window
* pParent
, const SfxBindings
* pBind
)
149 ScTabViewShell
* pViewSh
= nullptr;
150 SfxDispatcher
* pDisp
= pBind
->GetDispatcher();
153 SfxViewFrame
* pViewFrm
= pDisp
->GetFrame();
155 pViewSh
= dynamic_cast<ScTabViewShell
*>( pViewFrm
->GetViewShell() );
158 return VclPtr
<ScInputBarGroup
>::Create( pParent
, pViewSh
);
161 ScInputWindow::ScInputWindow( vcl::Window
* pParent
, const SfxBindings
* pBind
) :
162 // With WB_CLIPCHILDREN otherwise we get flickering
163 ToolBox ( pParent
, WinBits(WB_CLIPCHILDREN
| WB_BORDER
| WB_NOSHADOW
) ),
164 aWndPos ( !comphelper::LibreOfficeKit::isActive() ? VclPtr
<ScPosWnd
>::Create(this) : nullptr ),
165 mxTextWindow ( lcl_chooseRuntimeImpl( this, pBind
) ),
166 pInputHdl ( nullptr ),
167 mpViewShell ( nullptr ),
169 mnStandardItemHeight(0),
170 bIsOkCancelMode ( false ),
173 // #i73615# don't rely on SfxViewShell::Current while constructing the input line
174 // (also for GetInputHdl below)
175 ScTabViewShell
* pViewSh
= nullptr;
176 SfxDispatcher
* pDisp
= pBind
->GetDispatcher();
179 SfxViewFrame
* pViewFrm
= pDisp
->GetFrame();
181 pViewSh
= dynamic_cast<ScTabViewShell
*>( pViewFrm
->GetViewShell() );
183 OSL_ENSURE( pViewSh
, "no view shell for input window" );
185 mpViewShell
= pViewSh
;
187 // Position window, 3 buttons, input window
188 if (!comphelper::LibreOfficeKit::isActive())
190 InsertWindow (ToolBoxItemId(1), aWndPos
.get(), ToolBoxItemBits::NONE
, 0);
192 InsertItem (SID_INPUT_FUNCTION
, Image(StockImage::Yes
, RID_BMP_INPUT_FUNCTION
), ToolBoxItemBits::NONE
, 2);
195 const bool bIsLOKMobilePhone
= mpViewShell
&& mpViewShell
->isLOKMobilePhone();
197 // sigma and equal buttons
198 if (!bIsLOKMobilePhone
)
200 InsertItem (SID_INPUT_SUM
, Image(StockImage::Yes
, RID_BMP_INPUT_SUM
), ToolBoxItemBits::DROPDOWN
, 3);
201 InsertItem (SID_INPUT_EQUAL
, Image(StockImage::Yes
, RID_BMP_INPUT_EQUAL
), ToolBoxItemBits::NONE
, 4);
202 InsertItem (SID_INPUT_CANCEL
, Image(StockImage::Yes
, RID_BMP_INPUT_CANCEL
), ToolBoxItemBits::NONE
, 5);
203 InsertItem (SID_INPUT_OK
, Image(StockImage::Yes
, RID_BMP_INPUT_OK
), ToolBoxItemBits::NONE
, 6);
206 InsertWindow (ToolBoxItemId(7), mxTextWindow
.get(), ToolBoxItemBits::NONE
, 7);
207 SetDropdownClickHdl( LINK( this, ScInputWindow
, DropdownClickHdl
));
209 if (!comphelper::LibreOfficeKit::isActive())
211 aWndPos
->SetQuickHelpText(ScResId(SCSTR_QHELP_POSWND
));
212 aWndPos
->SetHelpId (HID_INSWIN_POS
);
214 mxTextWindow
->SetQuickHelpText(ScResId(SCSTR_QHELP_INPUTWND
));
215 mxTextWindow
->SetHelpId (HID_INSWIN_INPUT
);
217 // No SetHelpText: the helptexts come from the Help
218 SetItemText (SID_INPUT_FUNCTION
, ScResId(SCSTR_QHELP_BTNCALC
));
219 SetHelpId (SID_INPUT_FUNCTION
, HID_INSWIN_CALC
);
222 // sigma and equal buttons
223 if (!bIsLOKMobilePhone
)
225 SetHelpId (SID_INPUT_SUM
, HID_INSWIN_SUMME
);
226 SetHelpId (SID_INPUT_EQUAL
, HID_INSWIN_FUNC
);
227 SetHelpId (SID_INPUT_CANCEL
, HID_INSWIN_CANCEL
);
228 SetHelpId (SID_INPUT_OK
, HID_INSWIN_OK
);
230 if (!comphelper::LibreOfficeKit::isActive())
232 SetItemText ( SID_INPUT_SUM
, ScResId( SCSTR_QHELP_BTNSUM
) );
233 SetItemText ( SID_INPUT_EQUAL
, ScResId( SCSTR_QHELP_BTNEQUAL
) );
234 SetItemText ( SID_INPUT_CANCEL
, ScResId( SCSTR_QHELP_BTNCANCEL
) );
235 SetItemText ( SID_INPUT_OK
, ScResId( SCSTR_QHELP_BTNOK
) );
238 EnableItem( SID_INPUT_CANCEL
, false );
239 EnableItem( SID_INPUT_OK
, false );
241 HideItem( SID_INPUT_CANCEL
);
242 HideItem( SID_INPUT_OK
);
244 mnStandardItemHeight
= GetItemRect(SID_INPUT_SUM
).GetHeight();
247 SetHelpId( HID_SC_INPUTWIN
); // For the whole input row
249 if (!comphelper::LibreOfficeKit::isActive())
251 mxTextWindow
->Show();
253 pInputHdl
= ScModule::get()->GetInputHdl( pViewSh
, false ); // use own handler even if ref-handler is set
255 pInputHdl
->SetInputWindow( this );
257 if (pInputHdl
&& !pInputHdl
->GetFormString().isEmpty())
259 // Switch over while the Function AutoPilot is active
260 // -> show content of the Function AutoPilot again
261 // Also show selection (remember at the InputHdl)
262 mxTextWindow
->SetTextString(pInputHdl
->GetFormString(), true);
264 else if (pInputHdl
&& pInputHdl
->IsInputMode())
266 // If the input row was hidden while editing (e.g. when editing a formula
267 // and then switching to another document or the help), display the text
268 // we just edited from the InputHandler
269 mxTextWindow
->SetTextString(pInputHdl
->GetEditString(), true); // Display text
270 if ( pInputHdl
->IsTopMode() )
271 pInputHdl
->SetMode( SC_INPUT_TABLE
); // Focus ends up at the bottom anyways
275 // Don't stop editing in LOK a remote user might be editing.
276 const bool bStopEditing
= !comphelper::LibreOfficeKit::isActive();
277 pViewSh
->UpdateInputHandler(true, bStopEditing
); // Absolutely necessary update
280 SetToolbarLayoutMode( ToolBoxLayoutMode::Locked
);
282 SetAccessibleName(ScResId(STR_ACC_TOOLBAR_FORMULA
));
285 ScInputWindow::~ScInputWindow()
290 void ScInputWindow::dispose()
292 bool bDown
= !ScGlobal::oSysLocale
; // after Clear?
294 // if any view's input handler has a pointer to this input window, reset it
295 // (may be several ones, #74522#)
296 // member pInputHdl is not used here
300 SfxViewShell
* pSh
= SfxViewShell::GetFirst( true, checkSfxViewShell
<ScTabViewShell
> );
303 ScInputHandler
* pHdl
= static_cast<ScTabViewShell
*>(pSh
)->GetInputHandler();
304 if ( pHdl
&& pHdl
->GetInputWindow() == this )
306 pHdl
->SetInputWindow( nullptr );
307 pHdl
->StopInputWinEngine( false ); // reset pTopView pointer
309 pSh
= SfxViewShell::GetNext( *pSh
, true, checkSfxViewShell
<ScTabViewShell
> );
313 if (comphelper::LibreOfficeKit::isActive())
315 if (GetLOKNotifier())
316 ReleaseLOKNotifier();
319 mxTextWindow
.disposeAndClear();
320 aWndPos
.disposeAndClear();
325 void ScInputWindow::SetInputHandler( ScInputHandler
* pNew
)
327 // Is called in the Activate of the View ...
328 if ( pNew
!= pInputHdl
)
330 // On Reload (last version) the pInputHdl is the InputHandler of the old, deleted
331 // ViewShell: so don't touch it here!
334 pInputHdl
->SetInputWindow( this );
338 void ScInputWindow::Select()
340 ScModule
* pScMod
= ScModule::get();
343 ToolBoxItemId curItemId
= GetCurItemId();
344 if (curItemId
== SID_INPUT_FUNCTION
)
346 //! new method at ScModule to query if function autopilot is open
347 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
348 if ( pViewFrm
&& ( comphelper::LibreOfficeKit::isActive() || !pViewFrm
->GetChildWindow( SID_OPENDLG_FUNCTION
) ) )
350 pViewFrm
->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION
,
351 SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
);
353 // The Toolbox will be disabled anyways, so we don't need to switch here,
354 // regardless whether it succeeded or not!
355 // SetOkCancelMode();
358 else if (curItemId
== SID_INPUT_CANCEL
)
360 pScMod
->InputCancelHandler();
363 else if (curItemId
== SID_INPUT_OK
)
365 pScMod
->InputEnterHandler();
367 mxTextWindow
->Invalidate(); // Or else the Selection remains
369 else if (curItemId
== SID_INPUT_SUM
)
371 bool bRangeFinder
= false;
372 bool bSubTotal
= false;
373 AutoSum(bRangeFinder
, bSubTotal
, ocSum
);
375 else if (curItemId
== SID_INPUT_EQUAL
)
381 void ScInputWindow::StartFormula()
383 ScModule
* pScMod
= ScModule::get();
384 mxTextWindow
->StartEditEngine();
385 if ( pScMod
->IsEditMode() ) // Isn't if e.g. protected
387 mxTextWindow
->StartEditEngine();
389 sal_Int32 nStartPos
= 1;
390 sal_Int32 nEndPos
= 1;
392 ScTabViewShell
* pViewSh
= dynamic_cast<ScTabViewShell
*>( SfxViewShell::Current() );
395 const OUString
& rString
= mxTextWindow
->GetTextString();
396 const sal_Int32 nLen
= rString
.getLength();
398 ScDocument
& rDoc
= pViewSh
->GetViewData().GetDocument();
399 CellType eCellType
= rDoc
.GetCellType( pViewSh
->GetViewData().GetCurPos() );
405 mxTextWindow
->SetTextString("=" + rString
, true);
408 case CELLTYPE_STRING
:
413 case CELLTYPE_FORMULA
:
417 mxTextWindow
->SetTextString(u
"="_ustr
, true);
422 EditView
* pView
= mxTextWindow
->GetEditView();
425 sal_Int32 nStartPara
= 0, nEndPara
= 0;
426 if (comphelper::LibreOfficeKit::isActive())
429 if (pViewSh
&& !pViewSh
->isLOKDesktop())
431 nStartPara
= nEndPara
= pView
->getEditEngine().GetParagraphCount() ?
432 (pView
->getEditEngine().GetParagraphCount() - 1) : 0;
433 nStartPos
= nEndPos
= pView
->getEditEngine().GetTextLen(nStartPara
);
436 pView
->SetSelection(ESelection(nStartPara
, nStartPos
, nEndPara
, nEndPos
));
437 pScMod
->InputChanged(pView
);
439 pView
->SetEditEngineUpdateLayout(true);
444 void ScInputWindow::PixelInvalidate(const tools::Rectangle
* pRectangle
)
446 if (comphelper::LibreOfficeKit::isDialogPainting() || !comphelper::LibreOfficeKit::isActive())
451 tools::Rectangle
aRect(*pRectangle
);
452 aRect
.Move(-GetOutOffXPixel(), -GetOutOffYPixel());
453 Window::PixelInvalidate(&aRect
);
457 Window::PixelInvalidate(nullptr);
461 void ScInputWindow::SetSizePixel( const Size
& rNewSize
)
463 const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier();
466 if (vcl::Window
* pFrameWindowImpl
= GetParent())
468 if (vcl::Window
* pWorkWindow
= pFrameWindowImpl
->GetParent())
470 if (vcl::Window
* pImplBorderWindow
= pWorkWindow
->GetParent())
472 Size aSize
= pImplBorderWindow
->GetSizePixel();
473 aSize
.setWidth(rNewSize
.getWidth());
474 pImplBorderWindow
->SetSizePixel(aSize
);
480 ToolBox::SetSizePixel(rNewSize
);
483 void ScInputWindow::Resize()
487 Size aStartSize
= GetSizePixel();
488 Size aSize
= aStartSize
;
490 auto nLines
= mxTextWindow
->GetNumLines();
491 //(-10) to allow margin between sidebar and formulabar
492 tools::Long margin
= (comphelper::LibreOfficeKit::isActive()) ? 10 : 0;
493 Size
aTextWindowSize(aSize
.Width() - mxTextWindow
->GetPosPixel().X() - LEFT_OFFSET
- margin
,
494 mxTextWindow
->GetPixelHeightForLines(nLines
));
495 mxTextWindow
->SetSizePixel(aTextWindowSize
);
500 // Initially there is 1 line and the edit is vertically centered in the toolbar
501 // Later, if expanded then the vertical position of the edit will remain at
502 // that initial position, so when calculating the overall size of the expanded
503 // toolbar we have to include that initial offset in order to not make
504 // the edit overlap the RESIZE_HOTSPOT_HEIGHT area so that dragging to resize
505 // is still possible.
506 int nNormalHeight
= mxTextWindow
->GetPixelHeightForLines(1);
507 int nInitialTopMargin
= (mnStandardItemHeight
- nNormalHeight
) / 2;
508 if (nInitialTopMargin
> 0)
509 nTopOffset
= nInitialTopMargin
;
512 // add empty space of RESIZE_HOTSPOT_HEIGHT so resize is possible when hovering there
513 aSize
.setHeight(CalcWindowSizePixel().Height() + RESIZE_HOTSPOT_HEIGHT
+ nTopOffset
);
515 if (aStartSize
!= aSize
)
521 void ScInputWindow::NotifyLOKClient()
523 if (comphelper::LibreOfficeKit::isActive() && !GetLOKNotifier() && mpViewShell
)
524 SetLOKNotifier(mpViewShell
);
527 void ScInputWindow::SetFuncString( const OUString
& rString
, bool bDoEdit
)
529 //! new method at ScModule to query if function autopilot is open
530 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
531 EnableButtons( pViewFrm
&& !pViewFrm
->GetChildWindow( SID_OPENDLG_FUNCTION
) );
532 mxTextWindow
->StartEditEngine();
534 ScModule
* pScMod
= ScModule::get();
535 if ( !pScMod
->IsEditMode() )
539 mxTextWindow
->TextGrabFocus();
540 mxTextWindow
->SetTextString(rString
, true);
541 EditView
* pView
= mxTextWindow
->GetEditView();
545 sal_Int32 nLen
= rString
.getLength();
550 pView
->SetSelection(ESelection(0, nLen
));
553 pScMod
->InputChanged(pView
);
555 SetOkCancelMode(); // Not the case if immediately followed by Enter/Cancel
557 pView
->SetEditEngineUpdateLayout(true);
560 void ScInputWindow::SetPosString( const OUString
& rStr
)
562 if (!comphelper::LibreOfficeKit::isActive())
563 aWndPos
->SetPos( rStr
);
566 void ScInputWindow::SetTextString( const OUString
& rString
, bool bKitUpdate
)
568 if (rString
.getLength() <= 32767)
569 mxTextWindow
->SetTextString(rString
, bKitUpdate
);
571 mxTextWindow
->SetTextString(rString
.copy(0, 32767), bKitUpdate
);
574 void ScInputWindow::SetOkCancelMode()
576 //! new method at ScModule to query if function autopilot is open
577 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
578 EnableButtons( pViewFrm
&& !pViewFrm
->GetChildWindow( SID_OPENDLG_FUNCTION
) );
583 EnableItem ( SID_INPUT_SUM
, false );
584 EnableItem ( SID_INPUT_EQUAL
, false );
585 HideItem ( SID_INPUT_SUM
);
586 HideItem ( SID_INPUT_EQUAL
);
588 ShowItem ( SID_INPUT_CANCEL
, true );
589 ShowItem ( SID_INPUT_OK
, true );
590 EnableItem ( SID_INPUT_CANCEL
, true );
591 EnableItem ( SID_INPUT_OK
, true );
593 bIsOkCancelMode
= true;
596 void ScInputWindow::SetSumAssignMode()
598 //! new method at ScModule to query if function autopilot is open
599 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
600 EnableButtons( pViewFrm
&& !pViewFrm
->GetChildWindow( SID_OPENDLG_FUNCTION
) );
602 if (!bIsOkCancelMode
)
605 EnableItem ( SID_INPUT_CANCEL
, false );
606 EnableItem ( SID_INPUT_OK
, false );
607 HideItem ( SID_INPUT_CANCEL
);
608 HideItem ( SID_INPUT_OK
);
610 ShowItem ( SID_INPUT_SUM
, true );
611 ShowItem ( SID_INPUT_EQUAL
, true );
612 EnableItem ( SID_INPUT_SUM
, true );
613 EnableItem ( SID_INPUT_EQUAL
, true );
615 bIsOkCancelMode
= false;
617 SetFormulaMode(false); // No editing -> no formula
620 void ScInputWindow::SetFormulaMode( bool bSet
)
622 if (!comphelper::LibreOfficeKit::isActive())
623 aWndPos
->SetFormulaMode(bSet
);
624 mxTextWindow
->SetFormulaMode(bSet
);
627 bool ScInputWindow::IsInputActive()
629 return mxTextWindow
->IsInputActive();
632 EditView
* ScInputWindow::GetEditView()
634 return mxTextWindow
->GetEditView();
637 vcl::Window
* ScInputWindow::GetEditWindow()
642 Point
ScInputWindow::GetCursorScreenPixelPos(bool bBelow
)
644 return mxTextWindow
->GetCursorScreenPixelPos(bBelow
);
647 void ScInputWindow::MakeDialogEditView()
649 mxTextWindow
->MakeDialogEditView();
652 void ScInputWindow::StopEditEngine( bool bAll
)
654 mxTextWindow
->StopEditEngine( bAll
);
657 void ScInputWindow::TextGrabFocus()
659 mxTextWindow
->TextGrabFocus();
662 void ScInputWindow::TextInvalidate()
664 mxTextWindow
->Invalidate();
667 void ScInputWindow::SwitchToTextWin()
669 // used for shift-ctrl-F2
671 mxTextWindow
->StartEditEngine();
672 if (ScModule::get()->IsEditMode())
674 mxTextWindow
->TextGrabFocus();
675 EditView
* pView
= mxTextWindow
->GetEditView();
678 pView
->SetSelection(ESelection::AtEnd()); // set cursor to end of text
683 void ScInputWindow::PosGrabFocus()
685 if (!comphelper::LibreOfficeKit::isActive())
686 aWndPos
->GrabFocus();
689 void ScInputWindow::EnableButtons( bool bEnable
)
691 // when enabling buttons, always also enable the input window itself
692 if ( bEnable
&& !IsEnabled() )
695 EnableItem( SID_INPUT_FUNCTION
, bEnable
);
696 EnableItem( bIsOkCancelMode
? SID_INPUT_CANCEL
: SID_INPUT_SUM
, bEnable
);
697 EnableItem( bIsOkCancelMode
? SID_INPUT_OK
: SID_INPUT_EQUAL
, bEnable
);
701 void ScInputWindow::NumLinesChanged()
703 mxTextWindow
->NumLinesChanged();
706 void ScInputWindow::StateChanged( StateChangedType nType
)
708 ToolBox::StateChanged( nType
);
710 if ( nType
== StateChangedType::InitShow
) Resize();
713 void ScInputWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
715 if ( rDCEvt
.GetType() == DataChangedEventType::SETTINGS
&& (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
717 // update item images
718 SetItemImage(SID_INPUT_FUNCTION
, Image(StockImage::Yes
, RID_BMP_INPUT_FUNCTION
));
719 if ( bIsOkCancelMode
)
721 SetItemImage(SID_INPUT_CANCEL
, Image(StockImage::Yes
, RID_BMP_INPUT_CANCEL
));
722 SetItemImage(SID_INPUT_OK
, Image(StockImage::Yes
, RID_BMP_INPUT_OK
));
726 SetItemImage(SID_INPUT_SUM
, Image(StockImage::Yes
, RID_BMP_INPUT_SUM
));
727 SetItemImage(SID_INPUT_EQUAL
, Image(StockImage::Yes
, RID_BMP_INPUT_EQUAL
));
731 ToolBox::DataChanged( rDCEvt
);
734 bool ScInputWindow::IsPointerAtResizePos()
736 return GetOutputSizePixel().Height() - GetPointerPosPixel().Y() <= RESIZE_HOTSPOT_HEIGHT
;
739 void ScInputWindow::MouseMove( const MouseEvent
& rMEvt
)
741 Point aPosPixel
= GetPointerPosPixel();
743 ScInputBarGroup
* pGroupBar
= mxTextWindow
.get();
745 if (bInResize
|| IsPointerAtResizePos())
746 SetPointer(PointerStyle::WindowSSize
);
748 SetPointer(PointerStyle::Arrow
);
753 tools::Long nResizeThreshold
= tools::Long(TOOLBOX_WINDOW_HEIGHT
* 0.7);
754 bool bResetPointerPos
= false;
756 // Detect attempt to expand toolbar too much
757 if (aPosPixel
.Y() >= mnMaxY
)
759 bResetPointerPos
= true;
760 aPosPixel
.setY( mnMaxY
);
761 } // or expanding down
762 else if (GetOutputSizePixel().Height() - aPosPixel
.Y() < -nResizeThreshold
)
764 pGroupBar
->IncrementVerticalSize();
765 bResetPointerPos
= true;
767 else if ((GetOutputSizePixel().Height() - aPosPixel
.Y()) > nResizeThreshold
)
769 bResetPointerPos
= true;
770 pGroupBar
->DecrementVerticalSize();
773 if (bResetPointerPos
)
775 aPosPixel
.setY( GetOutputSizePixel().Height() );
776 SetPointerPosPixel(aPosPixel
);
780 ToolBox::MouseMove(rMEvt
);
783 void ScInputWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
787 if (IsPointerAtResizePos())
789 // Don't leave the mouse pointer leave *this* window
793 // find the height of the gridwin, we don't want to be
794 // able to expand the toolbar too far so we need to
795 // calculate an upper limit
796 // I'd prefer to leave at least a single column header and a
797 // row but I don't know how to get that value in pixels.
798 // Use TOOLBOX_WINDOW_HEIGHT for the moment
799 if (ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell())
801 mnMaxY
= GetOutputSizePixel().Height() + (pViewSh
->GetGridHeight(SC_SPLIT_TOP
)
802 + pViewSh
->GetGridHeight(SC_SPLIT_BOTTOM
)) - TOOLBOX_WINDOW_HEIGHT
;
807 ToolBox::MouseButtonDown( rMEvt
);
809 void ScInputWindow::MouseButtonUp( const MouseEvent
& rMEvt
)
812 if ( rMEvt
.IsLeft() )
818 ToolBox::MouseButtonUp( rMEvt
);
821 void ScInputWindow::AutoSum( bool& bRangeFinder
, bool& bSubTotal
, OpCode eCode
)
823 ScModule
* pScMod
= ScModule::get();
824 ScTabViewShell
* pViewSh
= dynamic_cast<ScTabViewShell
*>( SfxViewShell::Current() );
828 const OUString aFormula
= pViewSh
->DoAutoSum(bRangeFinder
, bSubTotal
, eCode
);
829 if ( aFormula
.isEmpty() )
832 SetFuncString( aFormula
);
833 const sal_Int32 aOpen
= aFormula
.indexOf('(');
834 const sal_Int32 aLen
= aFormula
.getLength();
835 if (!(bRangeFinder
&& pScMod
->IsEditMode()))
838 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( pViewSh
);
842 pHdl
->InitRangeFinder( aFormula
);
844 //! SetSelection at the InputHandler?
846 if ( aOpen
!= -1 && aLen
> aOpen
)
848 ESelection
aSel( 0, aOpen
+ (bSubTotal
? 3 : 1), 0, aLen
-1 );
849 EditView
* pTableView
= pHdl
->GetTableView();
851 pTableView
->SetSelection( aSel
);
852 EditView
* pTopView
= pHdl
->GetTopView();
854 pTopView
->SetSelection( aSel
);
858 ScInputBarGroup::ScInputBarGroup(vcl::Window
* pParent
, ScTabViewShell
* pViewSh
)
859 : InterimItemWindow(pParent
, u
"modules/scalc/ui/inputbar.ui"_ustr
, u
"InputBar"_ustr
, true, reinterpret_cast<sal_uInt64
>(pViewSh
))
860 , mxBackground(m_xBuilder
->weld_container(u
"background"_ustr
))
861 , mxTextWndGroup(new ScTextWndGroup(*this, pViewSh
))
862 , mxButtonUp(m_xBuilder
->weld_button(u
"up"_ustr
))
863 , mxButtonDown(m_xBuilder
->weld_button(u
"down"_ustr
))
865 InitControlBase(m_xContainer
.get());
867 SetPaintTransparent(false);
870 mxButtonUp
->connect_clicked(LINK(this, ScInputBarGroup
, ClickHdl
));
871 mxButtonDown
->connect_clicked(LINK(this, ScInputBarGroup
, ClickHdl
));
873 if (!comphelper::LibreOfficeKit::isActive())
875 mxButtonUp
->set_tooltip_text(ScResId( SCSTR_QHELP_COLLAPSE_FORMULA
));
876 mxButtonDown
->set_tooltip_text(ScResId(SCSTR_QHELP_EXPAND_FORMULA
));
879 int nHeight
= mxTextWndGroup
->GetPixelHeightForLines(1);
880 mxButtonUp
->set_size_request(-1, nHeight
);
881 mxButtonDown
->set_size_request(-1, nHeight
);
883 // disable the multiline toggle on the mobile phones
884 const SfxViewShell
* pViewShell
= SfxViewShell::Current();
885 if (!comphelper::LibreOfficeKit::isActive() || !(pViewShell
&& pViewShell
->isLOKMobilePhone()))
886 mxButtonDown
->show();
888 // tdf#154042 Use an initial height of one row so the Toolbar positions
889 // this in the same place regardless of how many rows it eventually shows
890 Size
aSize(GetSizePixel().Width(), nHeight
);
894 void ScInputBarGroup::SetBackgrounds()
896 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
897 SetBackground(rStyleSettings
.GetFaceColor());
898 // match to bg used in ScTextWnd::SetDrawingArea to the margin area is drawn with the
900 mxBackground
->set_background(rStyleSettings
.GetFieldColor());
903 void ScInputBarGroup::DataChanged(const DataChangedEvent
& rDCEvt
)
905 InterimItemWindow::DataChanged(rDCEvt
);
906 if ((rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) && (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
))
913 Point
ScInputBarGroup::GetCursorScreenPixelPos(bool bBelow
)
915 return mxTextWndGroup
->GetCursorScreenPixelPos(bBelow
);
918 ScInputBarGroup::~ScInputBarGroup()
923 void ScInputBarGroup::dispose()
925 mxTextWndGroup
.reset();
927 mxButtonDown
.reset();
928 mxBackground
.reset();
929 InterimItemWindow::dispose();
932 void ScInputBarGroup::InsertAccessibleTextData( ScAccessibleEditLineTextData
& rTextData
)
934 mxTextWndGroup
->InsertAccessibleTextData(rTextData
);
937 void ScInputBarGroup::RemoveAccessibleTextData( ScAccessibleEditLineTextData
& rTextData
)
939 mxTextWndGroup
->RemoveAccessibleTextData(rTextData
);
942 const OUString
& ScInputBarGroup::GetTextString() const
944 return mxTextWndGroup
->GetTextString();
947 void ScInputBarGroup::SetTextString(const OUString
& rString
, bool bKitUpdate
)
949 mxTextWndGroup
->SetTextString(rString
, bKitUpdate
);
952 void ScInputBarGroup::Resize()
954 mxTextWndGroup
->SetScrollPolicy();
955 InterimItemWindow::Resize();
958 void ScInputBarGroup::StopEditEngine(bool bAll
)
960 mxTextWndGroup
->StopEditEngine(bAll
);
963 void ScInputBarGroup::StartEditEngine()
965 mxTextWndGroup
->StartEditEngine();
968 void ScInputBarGroup::MakeDialogEditView()
970 mxTextWndGroup
->MakeDialogEditView();
973 EditView
* ScInputBarGroup::GetEditView() const
975 return mxTextWndGroup
->GetEditView();
978 bool ScInputBarGroup::HasEditView() const
980 return mxTextWndGroup
->HasEditView();
983 bool ScInputBarGroup::IsInputActive()
985 return mxTextWndGroup
->IsInputActive();
988 void ScInputBarGroup::SetFormulaMode(bool bSet
)
990 mxTextWndGroup
->SetFormulaMode(bSet
);
993 void ScInputBarGroup::IncrementVerticalSize()
995 mxTextWndGroup
->SetNumLines(mxTextWndGroup
->GetNumLines() + 1);
996 TriggerToolboxLayout();
999 void ScInputBarGroup::DecrementVerticalSize()
1001 if (mxTextWndGroup
->GetNumLines() > 1)
1003 mxTextWndGroup
->SetNumLines(mxTextWndGroup
->GetNumLines() - 1);
1004 TriggerToolboxLayout();
1008 void ScInputWindow::MenuHdl(std::u16string_view command
)
1010 if (command
.empty())
1013 bool bSubTotal
= false;
1014 bool bRangeFinder
= false;
1015 OpCode eCode
= ocSum
;
1016 if ( command
== u
"sum" )
1020 else if ( command
== u
"average" )
1024 else if ( command
== u
"max" )
1028 else if ( command
== u
"min" )
1032 else if ( command
== u
"count" )
1036 else if ( command
== u
"counta" )
1040 else if ( command
== u
"product" )
1044 else if (command
== u
"stdev")
1048 else if (command
== u
"stdevp")
1052 else if (command
== u
"var")
1056 else if (command
== u
"varp")
1061 AutoSum( bRangeFinder
, bSubTotal
, eCode
);
1064 IMPL_LINK_NOARG(ScInputWindow
, DropdownClickHdl
, ToolBox
*, void)
1066 ToolBoxItemId nCurID
= GetCurItemId();
1069 if (nCurID
== SID_INPUT_SUM
)
1071 tools::Rectangle
aRect(GetItemRect(SID_INPUT_SUM
));
1072 weld::Window
* pPopupParent
= weld::GetPopupParent(*this, aRect
);
1073 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(pPopupParent
, u
"modules/scalc/ui/autosum.ui"_ustr
));
1074 std::unique_ptr
<weld::Menu
> xPopMenu(xBuilder
->weld_menu(u
"menu"_ustr
));
1075 MenuHdl(xPopMenu
->popup_at_rect(pPopupParent
, aRect
));
1079 IMPL_LINK_NOARG(ScInputBarGroup
, ClickHdl
, weld::Button
&, void)
1081 if (mxTextWndGroup
->GetNumLines() > 1)
1082 mxTextWndGroup
->SetNumLines(1);
1084 mxTextWndGroup
->SetNumLines(mxTextWndGroup
->GetLastNumExpandedLines());
1089 void ScInputBarGroup::NumLinesChanged()
1091 if (mxTextWndGroup
->GetNumLines() > 1)
1093 mxButtonDown
->hide();
1095 mxTextWndGroup
->SetLastNumExpandedLines(mxTextWndGroup
->GetNumLines());
1100 mxButtonDown
->show();
1102 TriggerToolboxLayout();
1104 // Restore focus to input line(s) if necessary
1105 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl();
1106 if ( pHdl
&& pHdl
->IsTopMode() )
1107 mxTextWndGroup
->TextGrabFocus();
1110 void ScInputBarGroup::TriggerToolboxLayout()
1112 // layout changes are expensive and un-necessary.
1113 if (comphelper::LibreOfficeKit::isActive())
1116 vcl::Window
*w
=GetParent();
1117 ScInputWindow
&rParent
= dynamic_cast<ScInputWindow
&>(*w
);
1118 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
1123 Reference
< css::beans::XPropertySet
> xPropSet( pViewFrm
->GetFrame().GetFrameInterface(), UNO_QUERY
);
1124 Reference
< css::frame::XLayoutManager
> xLayoutManager
;
1126 if ( xPropSet
.is() )
1128 css::uno::Any aValue
= xPropSet
->getPropertyValue(u
"LayoutManager"_ustr
);
1129 aValue
>>= xLayoutManager
;
1132 if ( !xLayoutManager
.is() )
1135 xLayoutManager
->lock();
1136 DataChangedEvent
aFakeUpdate( DataChangedEventType::SETTINGS
, nullptr, AllSettingsFlags::STYLE
);
1138 // this basically will trigger the repositioning of the
1139 // items in the toolbar from ImplFormat ( which is controlled by
1140 // mnWinHeight ) which in turn is updated in ImplCalcItem which is
1141 // controlled by mbCalc. Additionally the ImplFormat above is
1142 // controlled via mbFormat. It seems the easiest way to get these
1143 // booleans set is to send in the fake event below.
1144 rParent
.DataChanged( aFakeUpdate
);
1146 // highest item in toolbar will have been calculated via the
1147 // event above. Call resize on InputBar to pick up the height
1151 // unlock relayouts the toolbars in the 4 quadrants
1152 xLayoutManager
->unlock();
1155 void ScInputBarGroup::TextGrabFocus()
1157 mxTextWndGroup
->TextGrabFocus();
1160 constexpr tools::Long gnBorderWidth
= (INPUTLINE_INSET_MARGIN
+ 1) * 2;
1161 constexpr tools::Long gnBorderHeight
= INPUTLINE_INSET_MARGIN
+ 1;
1163 ScTextWndGroup::ScTextWndGroup(ScInputBarGroup
& rParent
, ScTabViewShell
* pViewSh
)
1164 : mxTextWnd(new ScTextWnd(*this, pViewSh
))
1165 , mxScrollWin(rParent
.GetBuilder().weld_scrolled_window(u
"scrolledwindow"_ustr
, true))
1166 , mxTextWndWin(new weld::CustomWeld(rParent
.GetBuilder(), u
"sc_input_window"_ustr
, *mxTextWnd
))
1169 mxScrollWin
->connect_vadjustment_changed(LINK(this, ScTextWndGroup
, Impl_ScrollHdl
));
1170 if (ScTabViewShell
* pActiveViewShell
= comphelper::LibreOfficeKit::isActive() ?
1171 dynamic_cast<ScTabViewShell
*>(SfxViewShell::Current()) : nullptr)
1173 pActiveViewShell
->LOKSendFormulabarUpdate(nullptr, u
""_ustr
, ESelection());
1177 Point
ScTextWndGroup::GetCursorScreenPixelPos(bool bBelow
)
1182 EditView
* pEditView
= GetEditView();
1183 vcl::Cursor
* pCur
= pEditView
->GetCursor();
1186 Point aLogicPos
= pCur
->GetPos();
1188 aLogicPos
.AdjustY(pCur
->GetHeight());
1189 aPos
= GetEditViewDevice().LogicToPixel(aLogicPos
);
1190 bool bRTL
= mrParent
.IsRTLEnabled();
1192 aPos
.setX(mxTextWnd
->GetOutputSizePixel().Width() - aPos
.X() + gnBorderWidth
);
1194 aPos
.AdjustX(gnBorderWidth
+ 1);
1196 return mrParent
.OutputToScreenPixel(aPos
);
1199 ScTextWndGroup::~ScTextWndGroup()
1203 void ScTextWndGroup::InsertAccessibleTextData(ScAccessibleEditLineTextData
& rTextData
)
1205 mxTextWnd
->InsertAccessibleTextData(rTextData
);
1208 EditView
* ScTextWndGroup::GetEditView() const
1210 return mxTextWnd
->GetEditView();
1213 const OutputDevice
& ScTextWndGroup::GetEditViewDevice() const
1215 return mxTextWnd
->GetEditViewDevice();
1218 tools::Long
ScTextWndGroup::GetLastNumExpandedLines() const
1220 return mxTextWnd
->GetLastNumExpandedLines();
1223 void ScTextWndGroup::SetLastNumExpandedLines(tools::Long nLastExpandedLines
)
1225 mxTextWnd
->SetLastNumExpandedLines(nLastExpandedLines
);
1228 tools::Long
ScTextWndGroup::GetNumLines() const
1230 return mxTextWnd
->GetNumLines();
1233 int ScTextWndGroup::GetPixelHeightForLines(tools::Long nLines
)
1235 return mxTextWnd
->GetPixelHeightForLines(nLines
) + 2 * gnBorderHeight
;
1238 weld::ScrolledWindow
& ScTextWndGroup::GetScrollWin()
1240 return *mxScrollWin
;
1243 const OUString
& ScTextWndGroup::GetTextString() const
1245 return mxTextWnd
->GetTextString();
1248 bool ScTextWndGroup::HasEditView() const
1250 return mxTextWnd
->HasEditView();
1253 bool ScTextWndGroup::IsInputActive()
1255 return mxTextWnd
->IsInputActive();
1258 void ScTextWndGroup::MakeDialogEditView()
1260 mxTextWnd
->MakeDialogEditView();
1263 void ScTextWndGroup::RemoveAccessibleTextData(ScAccessibleEditLineTextData
& rTextData
)
1265 mxTextWnd
->RemoveAccessibleTextData(rTextData
);
1268 void ScTextWndGroup::SetScrollPolicy()
1270 if (mxTextWnd
->GetNumLines() > 2)
1271 mxScrollWin
->set_vpolicy(VclPolicyType::ALWAYS
);
1273 mxScrollWin
->set_vpolicy(VclPolicyType::NEVER
);
1276 void ScTextWndGroup::SetNumLines(tools::Long nLines
)
1278 mxTextWnd
->SetNumLines(nLines
);
1281 void ScTextWndGroup::SetFormulaMode(bool bSet
)
1283 mxTextWnd
->SetFormulaMode(bSet
);
1286 void ScTextWndGroup::SetTextString(const OUString
& rString
, bool bKitUpdate
)
1288 mxTextWnd
->SetTextString(rString
, bKitUpdate
);
1291 void ScTextWndGroup::StartEditEngine()
1293 mxTextWnd
->StartEditEngine();
1296 void ScTextWndGroup::StopEditEngine(bool bAll
)
1298 mxTextWnd
->StopEditEngine( bAll
);
1301 void ScTextWndGroup::TextGrabFocus()
1303 mxTextWnd
->TextGrabFocus();
1306 IMPL_LINK_NOARG(ScTextWndGroup
, Impl_ScrollHdl
, weld::ScrolledWindow
&, void)
1308 mxTextWnd
->DoScroll();
1311 void ScTextWnd::Paint( vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
1313 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1314 Color aBgColor
= rStyleSettings
.GetFieldColor();
1315 rRenderContext
.SetBackground(aBgColor
);
1317 // tdf#137713 we rely on GetEditView creating it if it doesn't already exist so
1318 // GetEditView() must be called unconditionally
1319 if (EditView
* pView
= GetEditView())
1323 pView
->Invalidate();
1324 mbInvalidate
= false;
1328 if (comphelper::LibreOfficeKit::isActive() && m_xEditEngine
)
1330 // EditEngine/EditView works in twips logical coordinates, so set the device map-mode to twips before painting
1331 // and use twips version of the painting area 'rRect'.
1332 // Document zoom should not be included in this conversion.
1333 tools::Rectangle aLogicRect
= OutputDevice::LogicToLogic(rRect
, MapMode(MapUnit::MapPixel
), MapMode(MapUnit::MapTwip
));
1334 MapMode aOriginalMode
= rRenderContext
.GetMapMode();
1335 rRenderContext
.SetMapMode(MapMode(MapUnit::MapTwip
));
1336 WeldEditView::Paint(rRenderContext
, aLogicRect
);
1337 rRenderContext
.SetMapMode(aOriginalMode
);
1340 WeldEditView::Paint(rRenderContext
, rRect
);
1343 EditView
* ScTextWnd::GetEditView() const
1346 const_cast<ScTextWnd
&>(*this).InitEditEngine();
1347 return m_xEditView
.get();
1350 bool ScTextWnd::HasEditView() const { return m_xEditView
!= nullptr; }
1352 const OutputDevice
& ScTextWnd::GetEditViewDevice() const
1354 return EditViewOutputDevice();
1357 int ScTextWnd::GetPixelHeightForLines(tools::Long nLines
)
1359 OutputDevice
& rDevice
= GetDrawingArea()->get_ref_device();
1360 return rDevice
.LogicToPixel(Size(0, nLines
* rDevice
.GetTextHeight())).Height() + 1;
1363 tools::Long
ScTextWnd::GetNumLines() const
1365 ScViewData
& rViewData
= mpViewShell
->GetViewData();
1366 return rViewData
.GetFormulaBarLines();
1369 void ScTextWnd::SetNumLines(tools::Long nLines
)
1371 ScViewData
& rViewData
= mpViewShell
->GetViewData();
1372 rViewData
.SetFormulaBarLines(nLines
);
1375 // SetFormulaBarLines sanitizes the height, so get the sanitized value
1376 mnLastExpandedLines
= rViewData
.GetFormulaBarLines();
1381 void ScTextWnd::Resize()
1385 Size aOutputSize
= GetOutputSizePixel();
1386 OutputDevice
& rDevice
= GetDrawingArea()->get_ref_device();
1387 tools::Rectangle aOutputArea
= rDevice
.PixelToLogic( tools::Rectangle( Point(), aOutputSize
));
1388 m_xEditView
->SetOutputArea( aOutputArea
);
1390 // Don't leave an empty area at the bottom if we can move the text down.
1391 tools::Long nMaxVisAreaTop
= m_xEditEngine
->GetTextHeight() - aOutputArea
.GetHeight();
1392 if (m_xEditView
->GetVisArea().Top() > nMaxVisAreaTop
)
1394 m_xEditView
->Scroll(0, m_xEditView
->GetVisArea().Top() - nMaxVisAreaTop
);
1397 m_xEditEngine
->SetPaperSize( rDevice
.PixelToLogic( Size( aOutputSize
.Width(), 10000 ) ) );
1400 // skip WeldEditView's Resize();
1401 weld::CustomWidgetController::Resize();
1403 SetScrollBarRange();
1406 int ScTextWnd::GetEditEngTxtHeight() const
1408 return m_xEditView
? m_xEditView
->getEditEngine().GetTextHeight() : 0;
1411 void ScTextWnd::SetScrollBarRange()
1416 OutputDevice
& rDevice
= GetDrawingArea()->get_ref_device();
1417 Size aOutputSize
= rDevice
.GetOutputSize();
1419 int nUpper
= GetEditEngTxtHeight();
1420 int nCurrentDocPos
= m_xEditView
->GetVisArea().Top();
1421 int nStepIncrement
= GetTextHeight();
1422 int nPageIncrement
= aOutputSize
.Height();
1423 int nPageSize
= aOutputSize
.Height();
1425 /* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has
1428 lower = gtk_adjustment_get_lower
1429 upper = gtk_adjustment_get_upper - gtk_adjustment_get_page_size
1431 and requires that upper > lower or the deceleration animation never ends
1433 nPageSize
= std::min(nPageSize
, nUpper
);
1435 weld::ScrolledWindow
& rVBar
= mrGroupBar
.GetScrollWin();
1436 rVBar
.vadjustment_configure(nCurrentDocPos
, 0, nUpper
,
1437 nStepIncrement
, nPageIncrement
, nPageSize
);
1440 void ScTextWnd::DoScroll()
1444 weld::ScrolledWindow
& rVBar
= mrGroupBar
.GetScrollWin();
1445 auto currentDocPos
= m_xEditView
->GetVisArea().Top();
1446 auto nDiff
= currentDocPos
- rVBar
.vadjustment_get_value();
1447 // we expect SetScrollBarRange callback to be triggered by Scroll
1448 // to set where we ended up
1449 m_xEditView
->Scroll(0, nDiff
);
1453 void ScTextWnd::StartEditEngine()
1455 // Don't activate if we're a modal dialog ourselves (Doc-modal dialog)
1456 SfxObjectShell
* pObjSh
= SfxObjectShell::Current();
1457 if ( pObjSh
&& pObjSh
->IsInModalMode() )
1460 if ( !m_xEditView
|| !m_xEditEngine
)
1465 ScInputHandler
* pHdl
= mpViewShell
->GetInputHandler();
1467 pHdl
->SetMode(SC_INPUT_TOP
, nullptr, static_cast<ScEditEngineDefaulter
*>(m_xEditEngine
.get()));
1469 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
1471 pViewFrm
->GetBindings().Invalidate( SID_ATTR_INSERT
);
1474 static void lcl_ExtendEditFontAttribs( SfxItemSet
& rSet
)
1476 const SfxPoolItem
& rFontItem
= rSet
.Get( EE_CHAR_FONTINFO
);
1477 std::unique_ptr
<SfxPoolItem
> pNewItem(rFontItem
.Clone());
1478 pNewItem
->SetWhich(EE_CHAR_FONTINFO_CJK
);
1479 rSet
.Put( *pNewItem
);
1480 pNewItem
->SetWhich(EE_CHAR_FONTINFO_CTL
);
1481 rSet
.Put( *pNewItem
);
1482 const SfxPoolItem
& rHeightItem
= rSet
.Get( EE_CHAR_FONTHEIGHT
);
1483 pNewItem
.reset(rHeightItem
.Clone());
1484 pNewItem
->SetWhich(EE_CHAR_FONTHEIGHT_CJK
);
1485 rSet
.Put( *pNewItem
);
1486 pNewItem
->SetWhich(EE_CHAR_FONTHEIGHT_CTL
);
1487 rSet
.Put( *pNewItem
);
1488 const SfxPoolItem
& rWeightItem
= rSet
.Get( EE_CHAR_WEIGHT
);
1489 pNewItem
.reset(rWeightItem
.Clone());
1490 pNewItem
->SetWhich(EE_CHAR_WEIGHT_CJK
);
1491 rSet
.Put( *pNewItem
);
1492 pNewItem
->SetWhich(EE_CHAR_WEIGHT_CTL
);
1493 rSet
.Put( *pNewItem
);
1494 const SfxPoolItem
& rItalicItem
= rSet
.Get( EE_CHAR_ITALIC
);
1495 pNewItem
.reset(rItalicItem
.Clone());
1496 pNewItem
->SetWhich(EE_CHAR_ITALIC_CJK
);
1497 rSet
.Put( *pNewItem
);
1498 pNewItem
->SetWhich(EE_CHAR_ITALIC_CTL
);
1499 rSet
.Put( *pNewItem
);
1500 const SfxPoolItem
& rLangItem
= rSet
.Get( EE_CHAR_LANGUAGE
);
1501 pNewItem
.reset(rLangItem
.Clone());
1502 pNewItem
->SetWhich(EE_CHAR_LANGUAGE_CJK
);
1503 rSet
.Put( *pNewItem
);
1504 pNewItem
->SetWhich(EE_CHAR_LANGUAGE_CTL
);
1505 rSet
.Put( *pNewItem
);
1508 static void lcl_ModifyRTLDefaults( SfxItemSet
& rSet
)
1510 rSet
.Put( SvxAdjustItem( SvxAdjust::Right
, EE_PARA_JUST
) );
1512 // always using rtl writing direction would break formulas
1513 //rSet.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB, EE_PARA_WRITINGDIR ) );
1515 // PaperSize width is limited to USHRT_MAX in RTL mode (because of EditEngine's
1516 // sal_uInt16 values in EditLine), so the text may be wrapped and line spacing must be
1517 // increased to not see the beginning of the next line.
1518 SvxLineSpacingItem
aItem( LINE_SPACE_DEFAULT_HEIGHT
, EE_PARA_SBL
);
1519 aItem
.SetPropLineSpace( 200 );
1523 static void lcl_ModifyRTLVisArea( EditView
* pEditView
)
1525 tools::Rectangle aVisArea
= pEditView
->GetVisArea();
1526 Size aPaper
= pEditView
->getEditEngine().GetPaperSize();
1527 tools::Long nDiff
= aPaper
.Width() - aVisArea
.Right();
1528 aVisArea
.AdjustLeft(nDiff
);
1529 aVisArea
.AdjustRight(nDiff
);
1530 pEditView
->SetVisArea(aVisArea
);
1533 void ScTextWnd::InitEditEngine()
1535 std::unique_ptr
<ScFieldEditEngine
> pNew
;
1536 ScDocShell
* pDocSh
= nullptr;
1539 pDocSh
= mpViewShell
->GetViewData().GetDocShell();
1540 ScDocument
& rDoc
= mpViewShell
->GetViewData().GetDocument();
1541 pNew
= std::make_unique
<ScFieldEditEngine
>(&rDoc
, rDoc
.GetEnginePool(), rDoc
.GetEditPool());
1544 pNew
= std::make_unique
<ScFieldEditEngine
>(nullptr, EditEngine::CreatePool().get(), nullptr, true);
1545 pNew
->SetExecuteURL( false );
1546 m_xEditEngine
= std::move(pNew
);
1548 Size barSize
= GetOutputSizePixel();
1549 m_xEditEngine
->SetUpdateLayout( false );
1550 m_xEditEngine
->SetPaperSize( GetDrawingArea()->get_ref_device().PixelToLogic(Size(barSize
.Width(),10000)) );
1551 m_xEditEngine
->SetWordDelimiters(
1552 ScEditUtil::ModifyDelimiters( m_xEditEngine
->GetWordDelimiters() ) );
1553 m_xEditEngine
->SetReplaceLeadingSingleQuotationMark( false );
1555 UpdateAutoCorrFlag();
1558 auto pSet
= std::make_unique
<SfxItemSet
>( m_xEditEngine
->GetEmptyItemSet() );
1559 EditEngine::SetFontInfoInItemSet( *pSet
, aTextFont
);
1560 lcl_ExtendEditFontAttribs( *pSet
);
1561 // turn off script spacing to match DrawText output
1562 pSet
->Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING
) );
1564 lcl_ModifyRTLDefaults( *pSet
);
1565 static_cast<ScEditEngineDefaulter
*>(m_xEditEngine
.get())->SetDefaults( std::move(pSet
) );
1568 // If the Cell contains URLFields, they need to be taken over into the entry row,
1569 // or else the position is not correct anymore
1570 bool bFilled
= false;
1571 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl();
1572 if ( pHdl
) //! Test if it's the right InputHdl?
1573 bFilled
= pHdl
->GetTextAndFields(static_cast<ScEditEngineDefaulter
&>(*m_xEditEngine
));
1575 m_xEditEngine
->SetUpdateLayout( true );
1577 // aString is the truth ...
1578 if (bFilled
&& m_xEditEngine
->GetText() == aString
)
1579 Invalidate(); // Repaint for (filled) Field
1581 static_cast<ScEditEngineDefaulter
*>(m_xEditEngine
.get())->SetTextCurrentDefaults(aString
); // At least the right text then
1583 m_xEditView
= std::make_unique
<EditView
>(m_xEditEngine
.get(), nullptr);
1585 // we get cursor, selection etc. messages from the VCL/window layer
1586 // otherwise these are injected into the document causing confusion.
1587 m_xEditView
->SuppressLOKMessages(true);
1589 m_xEditView
->setEditViewCallbacks(this);
1590 m_xEditView
->SetInsertMode(bIsInsertMode
);
1592 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1593 Color aBgColor
= rStyleSettings
.GetFieldColor();
1594 m_xEditView
->SetBackgroundColor(aBgColor
);
1598 pAcc
->InitAcc(nullptr, m_xEditView
.get(),
1599 ScResId(STR_ACC_EDITLINE_NAME
),
1600 ScResId(STR_ACC_EDITLINE_DESCR
));
1603 if (comphelper::LibreOfficeKit::isActive())
1604 m_xEditView
->RegisterViewShell(mpViewShell
);
1606 // Text from Clipboard is taken over as ASCII in a single row
1607 EVControlBits n
= m_xEditView
->GetControlWord();
1608 m_xEditView
->SetControlWord( n
| EVControlBits::SINGLELINEPASTE
);
1610 m_xEditEngine
->InsertView( m_xEditView
.get(), EE_APPEND
);
1615 lcl_ModifyRTLVisArea( m_xEditView
.get() );
1617 m_xEditEngine
->SetModifyHdl(LINK(this, ScTextWnd
, ModifyHdl
));
1618 m_xEditEngine
->SetStatusEventHdl(LINK(this, ScTextWnd
, EditStatusHdl
));
1620 if (!maAccTextDatas
.empty())
1621 maAccTextDatas
.back()->StartEdit();
1623 // as long as EditEngine and DrawText sometimes differ for CTL text,
1624 // repaint now to have the EditEngine's version visible
1627 ScDocument
& rDoc
= pDocSh
->GetDocument(); // any document
1628 SvtScriptType nScript
= rDoc
.GetStringScriptType( aString
);
1629 if ( nScript
& SvtScriptType::COMPLEX
)
1634 ScTextWnd::ScTextWnd(ScTextWndGroup
& rParent
, ScTabViewShell
* pViewSh
) :
1635 bIsRTL(AllSettings::GetLayoutRTL()),
1636 bIsInsertMode(true),
1637 bFormulaMode (false),
1639 mpViewShell(pViewSh
),
1640 mrGroupBar(rParent
),
1641 mnLastExpandedLines(INPUTWIN_MULTILINES
),
1646 ScTextWnd::~ScTextWnd()
1648 while (!maAccTextDatas
.empty()) {
1649 maAccTextDatas
.back()->Dispose();
1653 bool ScTextWnd::MouseMove( const MouseEvent
& rMEvt
)
1655 return m_xEditView
&& m_xEditView
->MouseMove(rMEvt
);
1658 bool ScTextWnd::CanFocus() const
1660 return ScModule::get()->IsEditMode();
1663 void ScTextWnd::UpdateFocus()
1673 bool ScTextWnd::MouseButtonDown( const MouseEvent
& rMEvt
)
1677 bool bClickOnSelection
= false;
1680 m_xEditView
->SetEditEngineUpdateLayout( true );
1681 bClickOnSelection
= m_xEditView
->IsSelectionAtPoint(rMEvt
.GetPosPixel());
1683 if (!bClickOnSelection
)
1685 rtl::Reference
<TransferDataContainer
> xTransferable(new TransferDataContainer
);
1686 GetDrawingArea()->enable_drag_source(xTransferable
, DND_ACTION_NONE
);
1690 rtl::Reference
<TransferDataContainer
> xTransferable(m_xHelper
);
1691 GetDrawingArea()->enable_drag_source(xTransferable
, DND_ACTION_COPY
);
1693 return WeldEditView::MouseButtonDown(rMEvt
);
1696 bool ScTextWnd::MouseButtonUp( const MouseEvent
& rMEvt
)
1698 bool bRet
= WeldEditView::MouseButtonUp(rMEvt
);
1701 if ( rMEvt
.IsMiddle() &&
1702 Application::GetSettings().GetMouseSettings().GetMiddleButtonAction() == MouseMiddleButtonAction::PasteSelection
)
1704 // EditView may have pasted from selection
1705 ScModule::get()->InputChanged(m_xEditView
.get());
1708 ScModule::get()->InputSelection(m_xEditView
.get());
1713 bool ScTextWnd::Command( const CommandEvent
& rCEvt
)
1715 bool bConsumed
= false;
1718 CommandEventId nCommand
= rCEvt
.GetCommand();
1721 ScModule
* pScMod
= ScModule::get();
1722 ScTabViewShell
* pStartViewSh
= ScTabViewShell::GetActiveViewShell();
1724 // don't modify the font defaults here - the right defaults are
1725 // already set in StartEditEngine when the EditEngine is created
1727 // Prevent that the EditView is lost when switching between Views
1728 pScMod
->SetInEditCommand( true );
1729 m_xEditView
->Command( rCEvt
);
1730 pScMod
->SetInEditCommand( false );
1732 // CommandEventId::StartDrag does not mean by far that the content was actually changed,
1733 // so don't trigger an InputChanged.
1734 //! Detect if dragged with Move or forbid Drag&Move somehow
1736 if ( nCommand
== CommandEventId::StartDrag
)
1738 // Is dragged onto another View?
1739 ScTabViewShell
* pEndViewSh
= ScTabViewShell::GetActiveViewShell();
1740 if ( pEndViewSh
!= pStartViewSh
&& pStartViewSh
!= nullptr )
1742 ScViewData
& rViewData
= pStartViewSh
->GetViewData();
1743 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( pStartViewSh
);
1744 if ( pHdl
&& rViewData
.HasEditView( rViewData
.GetActivePart() ) )
1746 pHdl
->CancelHandler();
1747 rViewData
.GetView()->ShowCursor(); // Missing for KillEditView, due to being inactive
1751 else if ( nCommand
== CommandEventId::EndExtTextInput
)
1753 ScModule
* mod
= ScModule::get();
1756 ScInputHandler
* pHdl
= mod
->GetInputHdl();
1758 pHdl
->InputCommand(rCEvt
);
1760 mod
->InputChanged(m_xEditView
.get());
1762 else if ( nCommand
== CommandEventId::CursorPos
)
1764 // don't call InputChanged for CommandEventId::CursorPos
1766 else if ( nCommand
== CommandEventId::InputLanguageChange
)
1768 // #i55929# Font and font size state depends on input language if nothing is selected,
1769 // so the slots have to be invalidated when the input language is changed.
1771 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
1774 SfxBindings
& rBindings
= pViewFrm
->GetBindings();
1775 rBindings
.Invalidate( SID_ATTR_CHAR_FONT
);
1776 rBindings
.Invalidate( SID_ATTR_CHAR_FONTHEIGHT
);
1779 else if ( nCommand
== CommandEventId::ContextMenu
)
1782 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
1785 Point aPos
= rCEvt
.GetMousePosPixel();
1786 if (!rCEvt
.IsMouseEvent())
1788 Size aSize
= GetOutputSizePixel();
1789 aPos
= Point(aSize
.Width() / 2, aSize
.Height() / 2);
1791 if (IsMouseCaptured())
1794 pViewFrm
->GetDispatcher()->ExecutePopup(u
"formulabar"_ustr
, &mrGroupBar
.GetVclParent(), &aPos
);
1797 else if ( nCommand
== CommandEventId::Wheel
)
1799 //don't call InputChanged for CommandEventId::Wheel
1801 else if ( nCommand
== CommandEventId::GestureSwipe
)
1803 //don't call InputChanged for CommandEventId::GestureSwipe
1805 else if ( nCommand
== CommandEventId::GestureLongPress
)
1807 //don't call InputChanged for CommandEventId::GestureLongPress
1809 else if ( nCommand
== CommandEventId::ModKeyChange
)
1811 //pass alt press/release to parent impl
1814 ScModule::get()->InputChanged(m_xEditView
.get());
1817 if ( comphelper::LibreOfficeKit::isActive() && nCommand
== CommandEventId::CursorPos
)
1819 // LOK uses this to setup caret position because drawingarea is replaced
1820 // with text input field, it sends logical caret position (start, end) not pixels
1828 ScModule
* mod
= ScModule::get();
1829 // if we focus input after "Accept Formula" command, we need to notify to get it working
1830 mod
->InputChanged(m_xEditView
.get());
1832 // information about paragraph is in additional data
1833 // information about position in a paragraph in a Mouse Pos
1834 // see vcl/jsdialog/executor.cxx "textselection" event
1835 const Point
* pParaPoint
= static_cast<const Point
*>(rCEvt
.GetEventData());
1836 Point aSelectionStartEnd
= rCEvt
.GetMousePosPixel();
1838 sal_Int32 nParaStart
, nParaEnd
, nPosStart
, nPosEnd
;
1840 nParaStart
= pParaPoint
? pParaPoint
->X() : 0;
1841 nParaEnd
= pParaPoint
? pParaPoint
->Y() : 0;
1842 nPosStart
= m_xEditView
->GetPosNoField(nParaStart
, aSelectionStartEnd
.X());
1843 nPosEnd
= m_xEditView
->GetPosNoField(nParaEnd
, aSelectionStartEnd
.Y());
1845 m_xEditView
->SetSelection(ESelection(nParaStart
, nPosStart
, nParaEnd
, nPosEnd
));
1846 mod
->InputSelection(m_xEditView
.get());
1856 bool ScTextWnd::StartDrag()
1858 // tdf#145248 don't start a drag if actively selecting
1859 if (m_xEditView
&& !m_xEditEngine
->IsInSelectionMode())
1861 OUString sSelection
= m_xEditView
->GetSelected();
1862 m_xHelper
->SetData(sSelection
);
1863 return sSelection
.isEmpty();
1868 bool ScTextWnd::KeyInput(const KeyEvent
& rKEvt
)
1872 if (!ScModule::get()->InputKeyEvent(rKEvt
))
1875 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
1877 bUsed
= pViewSh
->SfxKeyInput(rKEvt
); // Only accelerators, no input
1883 void ScTextWnd::GetFocus()
1885 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
1887 pViewSh
->SetFormShellAtTop( false ); // focus in input line -> FormShell no longer on top
1888 WeldEditView::GetFocus();
1891 void ScTextWnd::SetFormulaMode( bool bSet
)
1893 if ( bSet
!= bFormulaMode
)
1895 bFormulaMode
= bSet
;
1896 UpdateAutoCorrFlag();
1900 void ScTextWnd::UpdateAutoCorrFlag()
1904 EEControlBits nControl
= m_xEditEngine
->GetControlWord();
1905 EEControlBits nOld
= nControl
;
1907 nControl
&= ~EEControlBits::AUTOCORRECT
; // No AutoCorrect in Formulas
1909 nControl
|= EEControlBits::AUTOCORRECT
; // Else do enable it
1911 if ( nControl
!= nOld
)
1912 m_xEditEngine
->SetControlWord( nControl
);
1916 void ScTextWnd::EditViewScrollStateChange()
1918 // editengine height has changed or editview scroll pos has changed
1919 SetScrollBarRange();
1922 IMPL_LINK_NOARG(ScTextWnd
, ModifyHdl
, LinkParamNone
*, void)
1924 if (m_xEditView
&& !bInputMode
)
1926 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl();
1928 // Use the InputHandler's InOwnChange flag to prevent calling InputChanged
1929 // while an InputHandler method is modifying the EditEngine content
1931 if ( pHdl
&& !pHdl
->IsInOwnChange() )
1932 pHdl
->InputChanged( m_xEditView
.get(), true ); // #i20282# InputChanged must know if called from modify handler
1936 IMPL_LINK_NOARG(ScTextWnd
, EditStatusHdl
, EditStatus
&, void)
1938 SetScrollBarRange();
1943 void ScTextWnd::StopEditEngine( bool bAll
)
1950 if (!maAccTextDatas
.empty())
1951 maAccTextDatas
.back()->EndEdit();
1953 ScModule
* pScMod
= ScModule::get();
1956 pScMod
->InputSelection( m_xEditView
.get() );
1957 aString
= m_xEditEngine
->GetText();
1958 bIsInsertMode
= m_xEditView
->IsInsertMode();
1959 bool bSelection
= m_xEditView
->HasSelection();
1960 m_xEditEngine
->SetStatusEventHdl(Link
<EditStatus
&, void>());
1961 m_xEditEngine
->SetModifyHdl(Link
<LinkParamNone
*,void>());
1962 m_xEditView
.reset();
1963 m_xEditEngine
.reset();
1965 ScInputHandler
* pHdl
= mpViewShell
->GetInputHandler();
1967 if (pHdl
&& pHdl
->IsEditMode() && !bAll
)
1968 pHdl
->SetMode(SC_INPUT_TABLE
);
1970 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
1972 pViewFrm
->GetBindings().Invalidate( SID_ATTR_INSERT
);
1975 Invalidate(); // So that the Selection is not left there
1978 if (comphelper::LibreOfficeKit::isActive())
1981 std::vector
<ReferenceMark
> aReferenceMarks
;
1982 ScInputHandler::SendReferenceMarks( mpViewShell
, aReferenceMarks
);
1986 static sal_Int32
findFirstNonMatchingChar(const OUString
& rStr1
, const OUString
& rStr2
)
1988 // Search the string for unmatching chars
1989 const sal_Unicode
* pStr1
= rStr1
.getStr();
1990 const sal_Unicode
* pStr2
= rStr2
.getStr();
1992 while ( i
< rStr1
.getLength() )
1994 // Abort on the first unmatching char
1995 if ( *pStr1
!= *pStr2
)
2005 void ScTextWnd::SetTextString( const OUString
& rNewString
, bool bKitUpdate
)
2007 // Ideally it would be best to create on demand the EditEngine/EditView here, but... for
2008 // the initialisation scenario where a cell is first clicked on we end up with the text in the
2009 // inputbar window scrolled to the bottom if we do that here ( because the tableview and topview
2010 // are synced I guess ).
2011 // should fix that I suppose :-/ need to look a bit further into that
2012 mbInvalidate
= true; // ensure next Paint ( that uses editengine ) call will call Invalidate first
2014 if ( rNewString
!= aString
)
2018 // Find position of the change, only paint the rest
2021 bool bPaintAll
= GetNumLines() > 1 || bIsRTL
;
2024 // test if CTL script type is involved
2025 SvtScriptType nOldScript
= SvtScriptType::NONE
;
2026 SvtScriptType nNewScript
= SvtScriptType::NONE
;
2027 SfxObjectShell
* pObjSh
= SfxObjectShell::Current();
2028 if ( auto pDocShell
= dynamic_cast<ScDocShell
*>( pObjSh
) )
2030 // any document can be used (used only for its break iterator)
2031 ScDocument
& rDoc
= pDocShell
->GetDocument();
2032 nOldScript
= rDoc
.GetStringScriptType( aString
);
2033 nNewScript
= rDoc
.GetStringScriptType( rNewString
);
2035 bPaintAll
= ( nOldScript
& SvtScriptType::COMPLEX
) || ( nNewScript
& SvtScriptType::COMPLEX
);
2040 // In multiline mode, or if CTL is involved, the whole text has to be redrawn
2045 tools::Long nTextSize
= 0;
2047 if (rNewString
.getLength() > aString
.getLength())
2048 nDifPos
= findFirstNonMatchingChar(rNewString
, aString
);
2050 nDifPos
= findFirstNonMatchingChar(aString
, rNewString
);
2052 tools::Long nSize1
= GetTextWidth(aString
);
2053 tools::Long nSize2
= GetTextWidth(rNewString
);
2054 if ( nSize1
>0 && nSize2
>0 )
2055 nTextSize
= std::max( nSize1
, nSize2
);
2057 nTextSize
= GetOutputSizePixel().Width(); // Overflow
2059 Point aLogicStart
= GetDrawingArea()->get_ref_device().PixelToLogic(Point(0,0));
2060 tools::Long nStartPos
= aLogicStart
.X();
2061 tools::Long nInvPos
= nStartPos
;
2063 nInvPos
+= GetTextWidth(aString
.copy(0,nDifPos
));
2065 Invalidate(tools::Rectangle(nInvPos
, 0, nStartPos
+nTextSize
, GetOutputSizePixel().Height() - 1));
2070 static_cast<ScEditEngineDefaulter
*>(m_xEditEngine
.get())->SetTextCurrentDefaults(rNewString
);
2073 aString
= rNewString
;
2075 if (!maAccTextDatas
.empty())
2076 maAccTextDatas
.back()->TextChanged();
2081 if (ScTabViewShell
* pActiveViewShell
= bKitUpdate
&& comphelper::LibreOfficeKit::isActive() ?
2082 dynamic_cast<ScTabViewShell
*>(SfxViewShell::Current()) : nullptr)
2084 ESelection aSel
= m_xEditView
? m_xEditView
->GetSelection() : ESelection();
2085 pActiveViewShell
->LOKSendFormulabarUpdate(m_xEditView
.get(), rNewString
, aSel
);
2088 SetScrollBarRange();
2092 const OUString
& ScTextWnd::GetTextString() const
2097 bool ScTextWnd::IsInputActive()
2102 void ScTextWnd::MakeDialogEditView()
2104 if ( m_xEditView
) return;
2106 std::unique_ptr
<ScFieldEditEngine
> pNew
;
2107 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
2110 ScDocument
& rDoc
= pViewSh
->GetViewData().GetDocument();
2111 pNew
= std::make_unique
<ScFieldEditEngine
>(&rDoc
, rDoc
.GetEnginePool(), rDoc
.GetEditPool());
2114 pNew
= std::make_unique
<ScFieldEditEngine
>(nullptr, EditEngine::CreatePool().get(), nullptr, true);
2115 pNew
->SetExecuteURL( false );
2116 m_xEditEngine
= std::move(pNew
);
2118 const bool bPrevUpdateLayout
= m_xEditEngine
->SetUpdateLayout( false );
2119 m_xEditEngine
->SetWordDelimiters( m_xEditEngine
->GetWordDelimiters() + "=" );
2120 m_xEditEngine
->SetPaperSize( Size( bIsRTL
? USHRT_MAX
: THESIZE
, 300 ) );
2122 auto pSet
= std::make_unique
<SfxItemSet
>( m_xEditEngine
->GetEmptyItemSet() );
2123 EditEngine::SetFontInfoInItemSet( *pSet
, aTextFont
);
2124 lcl_ExtendEditFontAttribs( *pSet
);
2126 lcl_ModifyRTLDefaults( *pSet
);
2127 static_cast<ScEditEngineDefaulter
*>(m_xEditEngine
.get())->SetDefaults( std::move(pSet
) );
2128 m_xEditEngine
->SetUpdateLayout( bPrevUpdateLayout
);
2130 m_xEditView
= std::make_unique
<EditView
>(m_xEditEngine
.get(), nullptr);
2131 m_xEditView
->setEditViewCallbacks(this);
2133 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2134 Color aBgColor
= rStyleSettings
.GetFieldColor();
2135 m_xEditView
->SetBackgroundColor(aBgColor
);
2139 pAcc
->InitAcc(nullptr, m_xEditView
.get(),
2140 ScResId(STR_ACC_EDITLINE_NAME
),
2141 ScResId(STR_ACC_EDITLINE_DESCR
));
2144 if (comphelper::LibreOfficeKit::isActive())
2145 m_xEditView
->RegisterViewShell(mpViewShell
);
2146 m_xEditEngine
->InsertView( m_xEditView
.get(), EE_APPEND
);
2151 lcl_ModifyRTLVisArea( m_xEditView
.get() );
2153 if (!maAccTextDatas
.empty())
2154 maAccTextDatas
.back()->StartEdit();
2157 void ScTextWnd::ImplInitSettings()
2159 bIsRTL
= AllSettings::GetLayoutRTL();
2161 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2163 Color aBgColor
= rStyleSettings
.GetFieldColor();
2164 Color aTxtColor
= rStyleSettings
.GetWindowTextColor();
2166 aTextFont
.SetFillColor ( aBgColor
);
2167 aTextFont
.SetColor (aTxtColor
);
2171 void ScTextWnd::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
2173 // bypass WeldEditView::SetDrawingArea
2174 weld::CustomWidgetController::SetDrawingArea(pDrawingArea
);
2177 pDrawingArea
->set_cursor(PointerStyle::Text
);
2179 // initialize dnd, deliberately just a simple string so
2180 // we don't transfer the happenstance formatting in
2182 m_xHelper
.set(new svt::OStringTransferable(OUString()));
2183 rtl::Reference
<TransferDataContainer
> xHelper(m_xHelper
);
2184 SetDragDataTransferable(xHelper
, DND_ACTION_COPY
);
2186 OutputDevice
& rDevice
= pDrawingArea
->get_ref_device();
2187 pDrawingArea
->set_margin_start(gnBorderWidth
);
2188 pDrawingArea
->set_margin_end(gnBorderWidth
);
2189 // leave 1 for the width of the scrolledwindow border
2190 pDrawingArea
->set_margin_top(gnBorderHeight
- 1);
2191 pDrawingArea
->set_margin_bottom(gnBorderHeight
- 1);
2193 // always use application font, so a font with cjk chars can be installed
2194 vcl::Font aAppFont
= Application::GetSettings().GetStyleSettings().GetAppFont();
2195 weld::SetPointFont(rDevice
, aAppFont
);
2197 aTextFont
= rDevice
.GetFont();
2198 Size aFontSize
= aTextFont
.GetFontSize();
2199 aTextFont
.SetFontSize(rDevice
.PixelToLogic(aFontSize
, MapMode(MapUnit::MapTwip
)));
2201 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2203 Color aBgColor
= rStyleSettings
.GetFieldColor();
2204 Color aTxtColor
= rStyleSettings
.GetWindowTextColor();
2206 aTextFont
.SetTransparent(true);
2207 aTextFont
.SetFillColor(aBgColor
);
2208 aTextFont
.SetColor(aTxtColor
);
2209 aTextFont
.SetWeight(WEIGHT_NORMAL
);
2211 Size
aSize(1, GetPixelHeightForLines(1));
2212 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
2214 rDevice
.SetBackground(aBgColor
);
2215 rDevice
.SetLineColor(COL_BLACK
);
2216 rDevice
.SetMapMode(MapMode(MapUnit::MapTwip
));
2217 rDevice
.SetFont(aTextFont
);
2219 EnableRTL(false); // EditEngine can't be used with VCL EnableRTL
2222 css::uno::Reference
< css::accessibility::XAccessible
> ScTextWnd::CreateAccessible()
2224 pAcc
= new ScAccessibleEditLineObject(this);
2228 void ScTextWnd::InsertAccessibleTextData( ScAccessibleEditLineTextData
& rTextData
)
2230 OSL_ENSURE( ::std::find( maAccTextDatas
.begin(), maAccTextDatas
.end(), &rTextData
) == maAccTextDatas
.end(),
2231 "ScTextWnd::InsertAccessibleTextData - passed object already registered" );
2232 maAccTextDatas
.push_back( &rTextData
);
2235 void ScTextWnd::RemoveAccessibleTextData( ScAccessibleEditLineTextData
& rTextData
)
2237 AccTextDataVector::iterator aEnd
= maAccTextDatas
.end();
2238 AccTextDataVector::iterator aIt
= ::std::find( maAccTextDatas
.begin(), aEnd
, &rTextData
);
2239 OSL_ENSURE( aIt
!= aEnd
, "ScTextWnd::RemoveAccessibleTextData - passed object not registered" );
2241 maAccTextDatas
.erase( aIt
);
2244 void ScTextWnd::StyleUpdated()
2247 CustomWidgetController::Invalidate();
2250 void ScTextWnd::TextGrabFocus()
2256 ScPosWnd::ScPosWnd(vcl::Window
* pParent
)
2257 : InterimItemWindow(pParent
, u
"modules/scalc/ui/posbox.ui"_ustr
, u
"PosBox"_ustr
)
2258 , m_xWidget(m_xBuilder
->weld_combo_box(u
"pos_window"_ustr
))
2259 , m_nAsyncGetFocusId(nullptr)
2260 , nTipVisible(nullptr)
2261 , bFormulaMode(false)
2263 InitControlBase(m_xWidget
.get());
2265 // Use calculation according to tdf#132338 to align combobox width to width of fontname combobox within formatting toolbar;
2266 // formatting toolbar is placed above formulabar when using multiple toolbars typically
2268 m_xWidget
->set_entry_width_chars(1);
2269 Size
aSize(LogicToPixel(Size(POSITION_COMBOBOX_WIDTH
* 4, 0), MapMode(MapUnit::MapAppFont
)));
2270 m_xWidget
->set_size_request(aSize
.Width(), -1);
2271 SetSizePixel(m_xContainer
->get_preferred_size());
2275 StartListening( *SfxGetpApp() ); // For Navigator rangename updates
2277 m_xWidget
->connect_key_press(LINK(this, ScPosWnd
, KeyInputHdl
));
2278 m_xWidget
->connect_entry_activate(LINK(this, ScPosWnd
, ActivateHdl
));
2279 m_xWidget
->connect_changed(LINK(this, ScPosWnd
, ModifyHdl
));
2280 m_xWidget
->connect_focus_in(LINK(this, ScPosWnd
, FocusInHdl
));
2281 m_xWidget
->connect_focus_out(LINK(this, ScPosWnd
, FocusOutHdl
));
2284 ScPosWnd::~ScPosWnd()
2289 void ScPosWnd::dispose()
2291 EndListening( *SfxGetpApp() );
2295 if (m_nAsyncGetFocusId
)
2297 Application::RemoveUserEvent(m_nAsyncGetFocusId
);
2298 m_nAsyncGetFocusId
= nullptr;
2302 InterimItemWindow::dispose();
2305 void ScPosWnd::SetFormulaMode( bool bSet
)
2307 if ( bSet
!= bFormulaMode
)
2309 bFormulaMode
= bSet
;
2320 void ScPosWnd::SetPos( const OUString
& rPosStr
)
2322 if ( aPosStr
!= rPosStr
)
2325 m_xWidget
->set_entry_text(aPosStr
);
2330 OUString
ScPosWnd::createLocalRangeName(std::u16string_view rName
, std::u16string_view rTableName
)
2332 return OUString::Concat(rName
) + " (" + rTableName
+ ")";
2335 void ScPosWnd::FillRangeNames()
2338 m_xWidget
->freeze();
2340 SfxObjectShell
* pObjSh
= SfxObjectShell::Current();
2341 if ( auto pDocShell
= dynamic_cast<ScDocShell
*>( pObjSh
) )
2343 ScDocument
& rDoc
= pDocShell
->GetDocument();
2345 m_xWidget
->append_text(ScResId(STR_MANAGE_NAMES
));
2346 m_xWidget
->append_separator(u
"separator"_ustr
);
2349 std::set
<OUString
> aSet
;
2350 ScRangeName
* pRangeNames
= rDoc
.GetRangeName();
2351 for (const auto& rEntry
: *pRangeNames
)
2353 if (rEntry
.second
->IsValidReference(aDummy
))
2354 aSet
.insert(rEntry
.second
->GetName());
2356 for (SCTAB i
= 0; i
< rDoc
.GetTableCount(); ++i
)
2358 ScRangeName
* pLocalRangeName
= rDoc
.GetRangeName(i
);
2359 if (pLocalRangeName
&& !pLocalRangeName
->empty())
2361 OUString aTableName
;
2362 rDoc
.GetName(i
, aTableName
);
2363 for (const auto& rEntry
: *pLocalRangeName
)
2365 if (rEntry
.second
->IsValidReference(aDummy
))
2366 aSet
.insert(createLocalRangeName(rEntry
.second
->GetName(), aTableName
));
2371 for (const auto& rItem
: aSet
)
2373 m_xWidget
->append_text(rItem
);
2377 m_xWidget
->set_entry_text(aPosStr
);
2380 void ScPosWnd::FillFunctions()
2383 m_xWidget
->freeze();
2385 OUString aFirstName
;
2386 const ScAppOptions
& rOpt
= ScModule::get()->GetAppOptions();
2387 sal_uInt16 nMRUCount
= rOpt
.GetLRUFuncListCount();
2388 const sal_uInt16
* pMRUList
= rOpt
.GetLRUFuncList();
2391 const ScFunctionList
* pFuncList
= ScGlobal::GetStarCalcFunctionList();
2392 sal_uInt32 nListCount
= pFuncList
->GetCount();
2393 for (sal_uInt16 i
=0; i
<nMRUCount
; i
++)
2395 sal_uInt16 nId
= pMRUList
[i
];
2396 for (sal_uInt32 j
=0; j
<nListCount
; j
++)
2398 const ScFuncDesc
* pDesc
= pFuncList
->GetFunction( j
);
2399 if ( pDesc
->nFIndex
== nId
&& pDesc
->mxFuncName
)
2401 m_xWidget
->append_text(*pDesc
->mxFuncName
);
2402 if (aFirstName
.isEmpty())
2403 aFirstName
= *pDesc
->mxFuncName
;
2404 break; // Stop searching
2410 //! Re-add entry "Other..." for Function AutoPilot if it can work with text that
2411 // has been entered so far
2413 // m_xWidget->append_text(ScResId(STR_FUNCTIONLIST_MORE));
2416 m_xWidget
->set_entry_text(aFirstName
);
2419 void ScPosWnd::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
2424 const SfxHintId nHintId
= rHint
.GetId();
2425 // Does the list of range names need updating?
2426 if (nHintId
== SfxHintId::ThisIsAnSfxEventHint
)
2428 SfxEventHintId nEventId
= static_cast<const SfxEventHint
&>(rHint
).GetEventId();
2429 if ( nEventId
== SfxEventHintId::ActivateDoc
)
2434 if (nHintId
== SfxHintId::ScAreasChanged
|| nHintId
== SfxHintId::ScNavigatorUpdateAll
)
2439 void ScPosWnd::HideTip()
2443 Help::HidePopover(this, nTipVisible
);
2444 nTipVisible
= nullptr;
2448 static ScNameInputType
lcl_GetInputType( const OUString
& rText
)
2450 ScNameInputType eRet
= SC_NAME_INPUT_BAD_NAME
; // the more general error
2452 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
2455 ScViewData
& rViewData
= pViewSh
->GetViewData();
2456 ScDocument
& rDoc
= rViewData
.GetDocument();
2457 SCTAB nTab
= rViewData
.GetTabNo();
2458 ScAddress::Details
aDetails( rDoc
.GetAddressConvention());
2460 // test in same order as in SID_CURRENTCELL execute
2467 // From the context we know that when testing for a range name
2468 // sheet-local scope names have " (sheetname)" appended and global
2469 // names don't and can't contain ')', so we can force one or the other.
2470 const RutlNameScope eNameScope
=
2471 ((!rText
.isEmpty() && rText
[rText
.getLength()-1] == ')') ? RUTL_NAMES_LOCAL
: RUTL_NAMES_GLOBAL
);
2473 if (rText
== ScResId(STR_MANAGE_NAMES
))
2474 eRet
= SC_MANAGE_NAMES
;
2475 else if ( aRange
.Parse( rText
, rDoc
, aDetails
) & ScRefFlags::VALID
)
2476 eRet
= SC_NAME_INPUT_RANGE
;
2477 else if ( aAddress
.Parse( rText
, rDoc
, aDetails
) & ScRefFlags::VALID
)
2478 eRet
= SC_NAME_INPUT_CELL
;
2479 else if ( ScRangeUtil::MakeRangeFromName( rText
, rDoc
, nTab
, aRange
, eNameScope
, aDetails
) )
2481 eRet
= ((eNameScope
== RUTL_NAMES_LOCAL
) ? SC_NAME_INPUT_NAMEDRANGE_LOCAL
:
2482 SC_NAME_INPUT_NAMEDRANGE_GLOBAL
);
2484 else if ( ScRangeUtil::MakeRangeFromName( rText
, rDoc
, nTab
, aRange
, RUTL_DBASE
, aDetails
) )
2485 eRet
= SC_NAME_INPUT_DATABASE
;
2486 else if ( comphelper::string::isdigitAsciiString( rText
) &&
2487 ( nNumeric
= rText
.toInt32() ) > 0 && nNumeric
<= rDoc
.MaxRow()+1 )
2488 eRet
= SC_NAME_INPUT_ROW
;
2489 else if ( rDoc
.GetTable( rText
, nNameTab
) )
2490 eRet
= SC_NAME_INPUT_SHEET
;
2491 else if (ScRangeData::IsNameValid(rText
, rDoc
)
2492 == ScRangeData::IsNameValidType::NAME_VALID
) // nothing found, create new range?
2494 if ( rViewData
.GetSimpleArea( aRange
) == SC_MARK_SIMPLE
)
2495 eRet
= SC_NAME_INPUT_DEFINE
;
2497 eRet
= SC_NAME_INPUT_BAD_SELECTION
;
2500 eRet
= SC_NAME_INPUT_BAD_NAME
;
2506 IMPL_LINK_NOARG(ScPosWnd
, ModifyHdl
, weld::ComboBox
&, void)
2510 if (m_xWidget
->changed_by_direct_pick())
2519 // determine the action that would be taken for the current input
2521 ScNameInputType eType
= lcl_GetInputType(m_xWidget
->get_active_text()); // uses current view
2525 case SC_NAME_INPUT_CELL
:
2526 pStrId
= STR_NAME_INPUT_CELL
;
2528 case SC_NAME_INPUT_RANGE
:
2529 case SC_NAME_INPUT_NAMEDRANGE_LOCAL
:
2530 case SC_NAME_INPUT_NAMEDRANGE_GLOBAL
:
2531 pStrId
= STR_NAME_INPUT_RANGE
; // named range or range reference
2533 case SC_NAME_INPUT_DATABASE
:
2534 pStrId
= STR_NAME_INPUT_DBRANGE
;
2536 case SC_NAME_INPUT_ROW
:
2537 pStrId
= STR_NAME_INPUT_ROW
;
2539 case SC_NAME_INPUT_SHEET
:
2540 pStrId
= STR_NAME_INPUT_SHEET
;
2542 case SC_NAME_INPUT_DEFINE
:
2543 pStrId
= STR_NAME_INPUT_DEFINE
;
2546 // other cases (error): no tip help
2553 // show the help tip at the text cursor position
2555 vcl::Cursor
* pCur
= GetCursor();
2557 aPos
= LogicToPixel( pCur
->GetPos() );
2558 aPos
= OutputToScreenPixel( aPos
);
2559 tools::Rectangle
aRect( aPos
, aPos
);
2561 OUString aText
= ScResId(pStrId
);
2562 QuickHelpFlags
const nAlign
= QuickHelpFlags::Left
|QuickHelpFlags::Bottom
;
2563 nTipVisible
= Help::ShowPopover(this, aRect
, aText
, nAlign
);
2566 void ScPosWnd::DoEnter()
2568 bool bOpenManageNamesDialog
= false;
2569 OUString aText
= m_xWidget
->get_active_text();
2570 if ( !aText
.isEmpty() )
2574 ScModule
* pScMod
= ScModule::get();
2575 if ( aText
== ScResId(STR_FUNCTIONLIST_MORE
) )
2577 // Function AutoPilot
2578 //! Continue working with the text entered so far
2580 //! new method at ScModule to query if function autopilot is open
2581 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
2582 if ( pViewFrm
&& !pViewFrm
->GetChildWindow( SID_OPENDLG_FUNCTION
) )
2583 pViewFrm
->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION
,
2584 SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
);
2588 ScTabViewShell
* pViewSh
= dynamic_cast<ScTabViewShell
*>( SfxViewShell::Current() );
2589 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( pViewSh
);
2591 pHdl
->InsertFunction( aText
);
2596 // depending on the input, select something or create a new named range
2598 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
2601 ScViewData
& rViewData
= pViewSh
->GetViewData();
2602 ScDocShell
* pDocShell
= rViewData
.GetDocShell();
2603 ScDocument
& rDoc
= pDocShell
->GetDocument();
2605 ScNameInputType eType
= lcl_GetInputType( aText
);
2606 if ( eType
== SC_NAME_INPUT_BAD_NAME
|| eType
== SC_NAME_INPUT_BAD_SELECTION
)
2608 TranslateId pId
= (eType
== SC_NAME_INPUT_BAD_NAME
) ? STR_NAME_ERROR_NAME
: STR_NAME_ERROR_SELECTION
;
2609 pViewSh
->ErrorMessage(pId
);
2611 else if ( eType
== SC_NAME_INPUT_DEFINE
)
2613 ScRangeName
* pNames
= rDoc
.GetRangeName();
2615 if ( pNames
&& !pNames
->findByUpperName(ScGlobal::getCharClass().uppercase(aText
)) &&
2616 (rViewData
.GetSimpleArea( aSelection
) == SC_MARK_SIMPLE
) )
2618 ScRangeName
aNewRanges( *pNames
);
2619 ScAddress
aCursor( rViewData
.GetCurX(), rViewData
.GetCurY(), rViewData
.GetTabNo() );
2620 OUString
aContent(aSelection
.Format(rDoc
, ScRefFlags::RANGE_ABS_3D
, rDoc
.GetAddressConvention()));
2621 ScRangeData
* pNew
= new ScRangeData( rDoc
, aText
, aContent
, aCursor
);
2622 if ( aNewRanges
.insert(pNew
) )
2624 pDocShell
->GetDocFunc().ModifyRangeNames( aNewRanges
);
2625 pViewSh
->UpdateInputHandler(true);
2629 else if (eType
== SC_MANAGE_NAMES
)
2631 // dialog is only set below after calling 'ReleaseFocus_Impl' to ensure it gets focus
2632 bOpenManageNamesDialog
= true;
2636 bool bForceGlobalName
= false;
2637 // for all selection types, execute the SID_CURRENTCELL slot.
2638 if (eType
== SC_NAME_INPUT_CELL
|| eType
== SC_NAME_INPUT_RANGE
)
2640 // Note that SID_CURRENTCELL always expects address to
2641 // be in Calc A1 format. Convert the text.
2642 ScRange
aRange(0,0, rViewData
.GetTabNo());
2643 aRange
.ParseAny(aText
, rDoc
, rDoc
.GetAddressConvention());
2644 aText
= aRange
.Format(rDoc
, ScRefFlags::RANGE_ABS_3D
, ::formula::FormulaGrammar::CONV_OOO
);
2646 else if (eType
== SC_NAME_INPUT_NAMEDRANGE_GLOBAL
)
2648 bForceGlobalName
= true;
2651 SfxStringItem
aPosItem( SID_CURRENTCELL
, aText
);
2652 SfxBoolItem
aUnmarkItem( FN_PARAM_1
, true ); // remove existing selection
2653 // FN_PARAM_2 reserved for AlignToCursor
2654 SfxBoolItem
aForceGlobalName( FN_PARAM_3
, bForceGlobalName
);
2656 pViewSh
->GetViewData().GetDispatcher().ExecuteList( SID_CURRENTCELL
,
2657 SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
,
2658 { &aPosItem
, &aUnmarkItem
, &aForceGlobalName
});
2664 m_xWidget
->set_entry_text(aPosStr
);
2666 ReleaseFocus_Impl();
2668 if (bOpenManageNamesDialog
)
2670 const sal_uInt16 nId
= ScNameDlgWrapper::GetChildWindowId();
2671 if (ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell())
2673 SfxViewFrame
& rViewFrm
= pViewSh
->GetViewFrame();
2674 SfxChildWindow
* pWnd
= rViewFrm
.GetChildWindow( nId
);
2675 ScModule::get()->SetRefDialog(nId
, pWnd
== nullptr);
2680 IMPL_LINK_NOARG(ScPosWnd
, ActivateHdl
, weld::ComboBox
&, bool)
2686 IMPL_LINK(ScPosWnd
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
2688 bool bHandled
= true;
2690 switch (rKEvt
.GetKeyCode().GetCode())
2693 bHandled
= ActivateHdl(*m_xWidget
);
2698 // escape when the tip help is shown: only hide the tip
2704 m_xWidget
->set_entry_text(aPosStr
);
2705 ReleaseFocus_Impl();
2713 return bHandled
|| ChildKeyInput(rKEvt
);
2716 IMPL_LINK_NOARG(ScPosWnd
, OnAsyncGetFocus
, void*, void)
2718 m_nAsyncGetFocusId
= nullptr;
2719 m_xWidget
->select_entry_region(0, -1);
2722 IMPL_LINK_NOARG(ScPosWnd
, FocusInHdl
, weld::Widget
&, void)
2724 if (m_nAsyncGetFocusId
)
2726 // do it async to defeat entry in combobox having its own ideas about the focus
2727 m_nAsyncGetFocusId
= Application::PostUserEvent(LINK(this, ScPosWnd
, OnAsyncGetFocus
));
2730 IMPL_LINK_NOARG(ScPosWnd
, FocusOutHdl
, weld::Widget
&, void)
2732 if (m_nAsyncGetFocusId
)
2734 Application::RemoveUserEvent(m_nAsyncGetFocusId
);
2735 m_nAsyncGetFocusId
= nullptr;
2741 void ScPosWnd::ReleaseFocus_Impl()
2745 SfxViewShell
* pCurSh
= SfxViewShell::Current();
2746 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl(dynamic_cast<ScTabViewShell
*>(pCurSh
));
2747 if ( pHdl
&& pHdl
->IsTopMode() )
2749 // Focus back in input row?
2750 ScInputWindow
* pInputWin
= pHdl
->GetInputWindow();
2753 pInputWin
->TextGrabFocus();
2758 // Set focus to active View
2761 vcl::Window
* pShellWnd
= pCurSh
->GetWindow();
2764 pShellWnd
->GrabFocus();
2768 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */