include/vcl/jsdialog/executor.hxx | 24 +++++++ include/vcl/weld.hxx | 2 sc/inc/sc.hrc | 3 sc/sdi/cellsh.sdi | 2 sc/sdi/scalc.sdi | 37 +++++++++++ sc/source/ui/app/inputhdl.cxx | 44 +++++++++++++ sc/source/ui/app/inputwin.cxx | 115 ++++++++++++++++++++++------------- sc/source/ui/inc/inputhdl.hxx | 2 sc/source/ui/inc/inputwin.hxx | 1 sc/source/ui/view/cellsh1.cxx | 17 ++++- sc/source/ui/view/cellsh3.cxx | 17 +++++ vcl/inc/jsdialog/jsdialogbuilder.hxx | 30 +++++---- vcl/jsdialog/executor.cxx | 42 ++++++++++++ vcl/jsdialog/jsdialogbuilder.cxx | 19 +++-- 14 files changed, 293 insertions(+), 62 deletions(-)
New commits: commit 7df8334b0078b4e8f8fbf5c55d9fdc54398b57b7 Author: Szymon Kłos <[email protected]> AuthorDate: Thu Apr 14 12:09:38 2022 +0200 Commit: Szymon Kłos <[email protected]> CommitDate: Sun May 1 20:18:52 2022 +0200 jsdialog: handle formulabar as textinput mostly boilerplate code jsdialog changes: - added force parameter to sendAction - added support for key press/release and command events - moved ActionDataMap to jsdialog namespace for sharing formulabar changes: - added calls to send jsdialog messages with formula - added cursor moving support - on command event Change-Id: I714715133901941ba0758655e2d5907a3bae79f2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133010 Reviewed-by: Mert Tumer <[email protected]> Tested-by: Szymon Kłos <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133652 Tested-by: Jenkins Reviewed-by: Szymon Kłos <[email protected]> diff --git a/include/vcl/jsdialog/executor.hxx b/include/vcl/jsdialog/executor.hxx index 0f8fb821e2bd..6e388a6a3f79 100644 --- a/include/vcl/jsdialog/executor.hxx +++ b/include/vcl/jsdialog/executor.hxx @@ -12,6 +12,7 @@ #include <vcl/dllapi.h> #include <vcl/uitest/uiobject.hxx> #include <vcl/weld.hxx> +#include <unordered_map> class LOKTrigger { @@ -56,13 +57,36 @@ public: } static void trigger_closed(weld::Popover& rPopover) { rPopover.popdown(); } + + static void trigger_key_press(weld::Widget& rWidget, const KeyEvent& rEvent) + { + rWidget.m_aKeyPressHdl.Call(rEvent); + } + + static void trigger_key_release(weld::Widget& rWidget, const KeyEvent& rEvent) + { + rWidget.m_aKeyReleaseHdl.Call(rEvent); + } + + static void command(weld::DrawingArea& rArea, const CommandEvent& rCmd) + { + rArea.m_aCommandHdl.Call(rCmd); + } }; namespace jsdialog { +// type used to store key-value pairs to put in the generated messages +typedef std::unordered_map<std::string, OUString> ActionDataMap; + +/// execute action on a widget VCL_DLLPUBLIC bool ExecuteAction(const std::string& nWindowId, const OString& rWidget, StringMap& rData); +/// send full update message to the client VCL_DLLPUBLIC void SendFullUpdate(const std::string& nWindowId, const OString& rWidget); +/// send action message to the client +VCL_DLLPUBLIC void SendAction(const std::string& nWindowId, const OString& rWidget, + std::unique_ptr<ActionDataMap> pData); VCL_DLLPUBLIC StringMap jsonToStringMap(const char* pJSON); }; diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index 226e2cb6c21a..06cb4d037b3b 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -79,6 +79,8 @@ class DialogController; class VCL_DLLPUBLIC Widget { + friend class ::LOKTrigger; + protected: Link<Widget&, void> m_aFocusInHdl; Link<Widget&, void> m_aFocusOutHdl; diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index f7a41b13d084..a1b7afa38976 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -50,6 +50,7 @@ #include <unotools/localedatawrapper.hxx> #include <unotools/charclass.hxx> #include <vcl/help.hxx> +#include <vcl/jsdialog/executor.hxx> #include <vcl/commandevent.hxx> #include <vcl/cursor.hxx> #include <vcl/settings.hxx> @@ -1784,6 +1785,23 @@ void ScInputHandler::LOKPasteFunctionData(const OUString& rFunctionName) } } +void ScInputHandler::LOKSendFormulabarUpdate(const SfxViewShell* pActiveViewSh, + const OUString& rText, + const ESelection& rSelection) +{ + OUString aSelection = + OUString::number(rSelection.nStartPos) + ";" + OUString::number(rSelection.nEndPos); + + std::unique_ptr<jsdialog::ActionDataMap> pData = std::make_unique<jsdialog::ActionDataMap>(); + (*pData)["action_type"] = "setText"; + (*pData)["text"] = rText; + (*pData)["selection"] = aSelection; + + sal_uInt64 nCurrentShellId = reinterpret_cast<sal_uInt64>(pActiveViewSh); + std::string sWindowId = std::to_string(nCurrentShellId) + "formulabar"; + jsdialog::SendAction(sWindowId, "sc_input_window", std::move(pData)); +} + // Calculate selection and display as tip help static OUString lcl_Calculate( const OUString& rFormula, ScDocument& rDoc, const ScAddress &rPos ) { @@ -2710,7 +2728,10 @@ void ScInputHandler::DataChanged( bool bFromTopNotify, bool bSetModified ) if (comphelper::LibreOfficeKit::isActive()) { if (pActiveViewSh) + { + // TODO: deprecated? pActiveViewSh->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_FORMULA, aText.toUtf8().getStr()); + } } } @@ -2723,6 +2744,7 @@ void ScInputHandler::DataChanged( bool bFromTopNotify, bool bSetModified ) mpEditEngine->QuickFormatDoc(); EditView* pActiveView = pTopView ? pTopView : pTableView; + ESelection aSel; if (pActiveView && pActiveViewSh) { ScViewData& rViewData = pActiveViewSh->GetViewData(); @@ -2731,7 +2753,7 @@ void ScInputHandler::DataChanged( bool bFromTopNotify, bool bSetModified ) if (!bNeedGrow) { // Cursor before the end? - ESelection aSel = pActiveView->GetSelection(); + aSel = pActiveView->GetSelection(); aSel.Adjust(); bNeedGrow = ( aSel.nEndPos != mpEditEngine->GetTextLen(aSel.nEndPara) ); } @@ -2747,6 +2769,13 @@ void ScInputHandler::DataChanged( bool bFromTopNotify, bool bSetModified ) } } + if (comphelper::LibreOfficeKit::isActive() && pActiveViewSh && pInputWin) + { + ScInputHandler::LOKSendFormulabarUpdate(pActiveViewSh, + ScEditUtil::GetMultilineString(*mpEditEngine), + aSel); + } + UpdateFormulaMode(); bTextValid = false; // Changes only in the EditEngine bInOwnChange = false; @@ -4188,7 +4217,13 @@ void ScInputHandler::NotifyChange( const ScInputHdlState* pState, pInputWin->SetTextString(aString); if (comphelper::LibreOfficeKit::isActive() && pActiveViewSh) + { + EditView* pActiveView = pTopView ? pTopView : pTableView; + ESelection aSel = pActiveView ? pActiveView->GetSelection() : ESelection(); + ScInputHandler::LOKSendFormulabarUpdate(pActiveViewSh, aString, aSel); + // TODO: deprecated? pActiveViewSh->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_FORMULA, aString.toUtf8().getStr()); + } } if ( pInputWin || comphelper::LibreOfficeKit::isActive()) // Named range input @@ -4344,6 +4379,13 @@ void ScInputHandler::InputSelection( const EditView* pView ) // When the selection is changed manually, stop overwriting parentheses ResetAutoPar(); + + if (comphelper::LibreOfficeKit::isActive() && pActiveViewSh) + { + EditView* pActiveView = pTopView ? pTopView : pTableView; + ESelection aSel = pActiveView ? pActiveView->GetSelection() : ESelection(); + ScInputHandler::LOKSendFormulabarUpdate(pActiveViewSh, GetEditString(), aSel); + } } void ScInputHandler::InputChanged( const EditView* pView, bool bFromNotify ) diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx index 47c8c0fdb770..e50c682a1703 100644 --- a/sc/source/ui/app/inputwin.cxx +++ b/sc/source/ui/app/inputwin.cxx @@ -1115,6 +1115,8 @@ ScTextWndGroup::ScTextWndGroup(ScInputBarGroup& rParent, ScTabViewShell* pViewSh , mrParent(rParent) { mxScrollWin->connect_vadjustment_changed(LINK(this, ScTextWndGroup, Impl_ScrollHdl)); + if (comphelper::LibreOfficeKit::isActive()) + ScInputHandler::LOKSendFormulabarUpdate(SfxViewShell::Current(), "", ESelection()); } Point ScTextWndGroup::GetCursorScreenPixelPos(bool bBelow) @@ -1734,6 +1736,26 @@ bool ScTextWnd::Command( const CommandEvent& rCEvt ) SC_MOD()->InputChanged( m_xEditView.get() ); } + if ( comphelper::LibreOfficeKit::isActive() && nCommand == CommandEventId::CursorPos ) + { + // LOK uses this to setup caret position because drawingarea is replaced + // with text input field, it sends logical caret position (start, end) not pixels + + StartEditEngine(); + TextGrabFocus(); + + if (!m_xEditView) + return true; + + Point aSelectionStartEnd = rCEvt.GetMousePosPixel(); + m_xEditView->SetSelection(ESelection(0, aSelectionStartEnd.X(), + 0, aSelectionStartEnd.Y())); + + SC_MOD()->InputSelection( m_xEditView.get() ); + + bConsumed = true; + } + bInputMode = false; return bConsumed; @@ -1889,6 +1911,12 @@ static sal_Int32 findFirstNonMatchingChar(const OUString& rStr1, const OUString& void ScTextWnd::SetTextString( const OUString& rNewString ) { + if (comphelper::LibreOfficeKit::isActive()) + { + ESelection aSel = m_xEditView ? m_xEditView->GetSelection() : ESelection(); + ScInputHandler::LOKSendFormulabarUpdate(SfxViewShell::Current(), rNewString, aSel); + } + // Ideally it would be best to create on demand the EditEngine/EditView here, but... for // the initialisation scenario where a cell is first clicked on we end up with the text in the // inputbar window scrolled to the bottom if we do that here ( because the tableview and topview diff --git a/sc/source/ui/inc/inputhdl.hxx b/sc/source/ui/inc/inputhdl.hxx index 625d2f7ca1f8..7b06ee3320ed 100644 --- a/sc/source/ui/inc/inputhdl.hxx +++ b/sc/source/ui/inc/inputhdl.hxx @@ -294,6 +294,8 @@ public: tools::Long nTab, const Color& rColor ); void LOKPasteFunctionData(const OUString& rFunctionName); + static void LOKSendFormulabarUpdate(const SfxViewShell* pActiveViewSh, + const OUString& rText, const ESelection& rSelection); }; // ScInputHdlState diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx b/vcl/inc/jsdialog/jsdialogbuilder.hxx index 08b16124a7e2..0b0289240bf6 100644 --- a/vcl/inc/jsdialog/jsdialogbuilder.hxx +++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx @@ -28,7 +28,6 @@ #include <deque> #include <list> #include <mutex> -#include <unordered_map> #define ACTION_TYPE "action_type" #define PARENT_ID "parent_id" @@ -42,7 +41,6 @@ class SvTabListBox; class IconView; typedef std::map<OString, weld::Widget*> WidgetMap; -typedef std::unordered_map<std::string, OUString> ActionDataMap; namespace jsdialog { @@ -63,7 +61,7 @@ class JSDialogMessageInfo public: jsdialog::MessageType m_eType; VclPtr<vcl::Window> m_pWindow; - std::unique_ptr<ActionDataMap> m_pData; + std::unique_ptr<jsdialog::ActionDataMap> m_pData; private: void copy(const JSDialogMessageInfo& rInfo) @@ -72,14 +70,15 @@ private: this->m_pWindow = rInfo.m_pWindow; if (rInfo.m_pData) { - std::unique_ptr<ActionDataMap> pData(new ActionDataMap(*rInfo.m_pData)); + std::unique_ptr<jsdialog::ActionDataMap> pData( + new jsdialog::ActionDataMap(*rInfo.m_pData)); this->m_pData = std::move(pData); } } public: JSDialogMessageInfo(jsdialog::MessageType eType, VclPtr<vcl::Window> pWindow, - std::unique_ptr<ActionDataMap> pData) + std::unique_ptr<jsdialog::ActionDataMap> pData) : m_eType(eType) , m_pWindow(pWindow) , m_pData(std::move(pData)) @@ -120,7 +119,7 @@ public: void clearQueue(); void forceUpdate(); void sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Window> pWindow, - std::unique_ptr<ActionDataMap> pData = nullptr); + std::unique_ptr<jsdialog::ActionDataMap> pData = nullptr); private: void send(tools::JsonWriter& aJsonWriter); @@ -128,7 +127,8 @@ private: std::unique_ptr<tools::JsonWriter> generateWidgetUpdate(VclPtr<vcl::Window> pWindow) const; std::unique_ptr<tools::JsonWriter> generateCloseMessage() const; std::unique_ptr<tools::JsonWriter> - generateActionMessage(VclPtr<vcl::Window> pWindow, std::unique_ptr<ActionDataMap> pData) const; + generateActionMessage(VclPtr<vcl::Window> pWindow, + std::unique_ptr<jsdialog::ActionDataMap> pData) const; std::unique_ptr<tools::JsonWriter> generatePopupMessage(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId) const; std::unique_ptr<tools::JsonWriter> generateClosePopupMessage(OUString sWindowId) const; @@ -158,7 +158,8 @@ public: virtual void sendFullUpdate(bool bForce = false); void sendClose(); void sendUpdate(VclPtr<vcl::Window> pWindow, bool bForce = false); - virtual void sendAction(VclPtr<vcl::Window> pWindow, std::unique_ptr<ActionDataMap> pData); + virtual void sendAction(VclPtr<vcl::Window> pWindow, + std::unique_ptr<jsdialog::ActionDataMap> pData); virtual void sendPopup(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId); virtual void sendClosePopup(vcl::LOKWindowId nWindowId); void flush() { mpIdleNotify->Invoke(); } @@ -221,6 +222,9 @@ class JSInstanceBuilder final : public SalInstanceBuilder, public JSDialogSender const OString& rWidget, StringMap& rData); friend VCL_DLLPUBLIC void jsdialog::SendFullUpdate(const std::string& nWindowId, const OString& rWidget); + friend VCL_DLLPUBLIC void jsdialog::SendAction(const std::string& nWindowId, + const OString& rWidget, + std::unique_ptr<jsdialog::ActionDataMap> pData); static std::map<std::string, WidgetMap>& GetLOKWeldWidgetsMap(); static void InsertWindowToMap(const std::string& nWindowId); @@ -317,7 +321,7 @@ public: virtual void sendFullUpdate(bool bForce = false) = 0; - virtual void sendAction(std::unique_ptr<ActionDataMap> pData) = 0; + virtual void sendAction(std::unique_ptr<jsdialog::ActionDataMap> pData) = 0; virtual void sendPopup(vcl::Window* pPopup, OUString sParentId, OUString sCloseId) = 0; @@ -358,7 +362,8 @@ public: BaseInstanceClass::show(); if (!bWasVisible) { - std::unique_ptr<ActionDataMap> pMap = std::make_unique<ActionDataMap>(); + std::unique_ptr<jsdialog::ActionDataMap> pMap + = std::make_unique<jsdialog::ActionDataMap>(); (*pMap)[ACTION_TYPE] = "show"; sendAction(std::move(pMap)); } @@ -370,7 +375,8 @@ public: BaseInstanceClass::hide(); if (bWasVisible) { - std::unique_ptr<ActionDataMap> pMap = std::make_unique<ActionDataMap>(); + std::unique_ptr<jsdialog::ActionDataMap> pMap + = std::make_unique<jsdialog::ActionDataMap>(); (*pMap)[ACTION_TYPE] = "hide"; sendAction(std::move(pMap)); } @@ -424,7 +430,7 @@ public: m_pSender->sendFullUpdate(bForce); } - virtual void sendAction(std::unique_ptr<ActionDataMap> pData) override + virtual void sendAction(std::unique_ptr<jsdialog::ActionDataMap> pData) override { if (!m_bIsFreezed && m_pSender && pData) m_pSender->sendAction(BaseInstanceClass::m_xWidget, std::move(pData)); diff --git a/vcl/jsdialog/executor.cxx b/vcl/jsdialog/executor.cxx index 409c58ff2d49..4a75f2a99f71 100644 --- a/vcl/jsdialog/executor.cxx +++ b/vcl/jsdialog/executor.cxx @@ -41,6 +41,14 @@ void SendFullUpdate(const std::string& nWindowId, const OString& rWidget) pJSWidget->sendFullUpdate(); } +void SendAction(const std::string& nWindowId, const OString& rWidget, + std::unique_ptr<ActionDataMap> pData) +{ + weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget); + if (auto pJSWidget = dynamic_cast<BaseJSWidget*>(pWidget)) + pJSWidget->sendAction(std::move(pData)); +} + bool ExecuteAction(const std::string& nWindowId, const OString& rWidget, StringMap& rData) { weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget); @@ -192,6 +200,40 @@ bool ExecuteAction(const std::string& nWindowId, const OString& rWidget, StringM LOKTrigger::trigger_click(*pArea, Point(10, 10)); return true; } + else if (sAction == "keypress") + { + LOKTrigger::trigger_key_press( + *pArea, + KeyEvent(rData["data"].toUInt32(), vcl::KeyCode(rData["data"].toUInt32()))); + LOKTrigger::trigger_key_release( + *pArea, + KeyEvent(rData["data"].toUInt32(), vcl::KeyCode(rData["data"].toUInt32()))); + return true; + } + else if (sAction == "textselection") + { + // start;end + int nSeparatorPos = rData["data"].indexOf(';'); + if (nSeparatorPos <= 0) + return true; + + std::u16string_view aStartPos = rData["data"].subView(0, nSeparatorPos); + std::u16string_view aEndPos = rData["data"].subView(nSeparatorPos + 1); + + if (aStartPos.empty() || aEndPos.empty()) + return true; + + int nStart = std::atoi( + OUStringToOString(aStartPos.data(), RTL_TEXTENCODING_ASCII_US).getStr()); + int nEnd = std::atoi( + OUStringToOString(aEndPos.data(), RTL_TEXTENCODING_ASCII_US).getStr()); + + Point aPos(nStart, nEnd); + CommandEvent aCEvt(aPos, CommandEventId::CursorPos); + LOKTrigger::command(*pArea, aCEvt); + + return true; + } } } else if (sControlType == "spinfield") diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx index f89d0ca0fc13..b1ca111a07f7 100644 --- a/vcl/jsdialog/jsdialogbuilder.cxx +++ b/vcl/jsdialog/jsdialogbuilder.cxx @@ -88,7 +88,7 @@ void JSDialogNotifyIdle::send(tools::JsonWriter& aJsonWriter) namespace { -OUString extractActionType(const ActionDataMap& rData) +OUString extractActionType(const jsdialog::ActionDataMap& rData) { auto it = rData.find(ACTION_TYPE); if (it != rData.end()) @@ -98,7 +98,7 @@ OUString extractActionType(const ActionDataMap& rData) }; void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Window> pWindow, - std::unique_ptr<ActionDataMap> pData) + std::unique_ptr<jsdialog::ActionDataMap> pData) { std::scoped_lock aGuard(m_aQueueMutex); @@ -172,7 +172,7 @@ std::unique_ptr<tools::JsonWriter> JSDialogNotifyIdle::generateCloseMessage() co std::unique_ptr<tools::JsonWriter> JSDialogNotifyIdle::generateActionMessage(VclPtr<vcl::Window> pWindow, - std::unique_ptr<ActionDataMap> pData) const + std::unique_ptr<jsdialog::ActionDataMap> pData) const { std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter()); @@ -270,6 +270,9 @@ void JSDialogNotifyIdle::Invoke() { jsdialog::MessageType eType = rMessage.m_eType; + if (m_sTypeOfJSON == "formulabar" && eType != jsdialog::MessageType::Action) + continue; + switch (eType) { case jsdialog::MessageType::FullUpdate: @@ -344,7 +347,8 @@ void JSDialogSender::sendUpdate(VclPtr<vcl::Window> pWindow, bool bForce) mpIdleNotify->Start(); } -void JSDialogSender::sendAction(VclPtr<vcl::Window> pWindow, std::unique_ptr<ActionDataMap> pData) +void JSDialogSender::sendAction(VclPtr<vcl::Window> pWindow, + std::unique_ptr<jsdialog::ActionDataMap> pData) { if (!mpIdleNotify) return; @@ -358,7 +362,7 @@ void JSDialogSender::sendPopup(VclPtr<vcl::Window> pWindow, OUString sParentId, if (!mpIdleNotify) return; - std::unique_ptr<ActionDataMap> pData = std::make_unique<ActionDataMap>(); + std::unique_ptr<jsdialog::ActionDataMap> pData = std::make_unique<jsdialog::ActionDataMap>(); (*pData)[PARENT_ID] = sParentId; (*pData)[CLOSE_ID] = sCloseId; mpIdleNotify->sendMessage(jsdialog::MessageType::Popup, pWindow, std::move(pData)); @@ -370,7 +374,7 @@ void JSDialogSender::sendClosePopup(vcl::LOKWindowId nWindowId) if (!mpIdleNotify) return; - std::unique_ptr<ActionDataMap> pData = std::make_unique<ActionDataMap>(); + std::unique_ptr<jsdialog::ActionDataMap> pData = std::make_unique<jsdialog::ActionDataMap>(); (*pData)[WINDOW_ID] = OUString::number(nWindowId); mpIdleNotify->sendMessage(jsdialog::MessageType::PopupClose, nullptr, std::move(pData)); flush(); @@ -607,7 +611,6 @@ JSInstanceBuilder::JSInstanceBuilder(vcl::Window* pParent, const OUString& rUIRo } initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); - sendFullUpdate(); } std::unique_ptr<JSInstanceBuilder> JSInstanceBuilder::CreateDialogBuilder(weld::Widget* pParent, @@ -1666,7 +1669,7 @@ void JSIconView::select(int pos) { SalInstanceIconView::select(pos); - std::unique_ptr<ActionDataMap> pMap = std::make_unique<ActionDataMap>(); + std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>(); (*pMap)[ACTION_TYPE] = "select"; (*pMap)["position"] = OUString::number(pos); sendAction(std::move(pMap)); commit 3dd8b19b814e959d00235df8bc08f9892f45dd87 Author: Szymon Kłos <[email protected]> AuthorDate: Tue Apr 26 18:15:22 2022 +0200 Commit: Szymon Kłos <[email protected]> CommitDate: Sun May 1 20:18:40 2022 +0200 lok: Introduce uno commands for formulabar actions thanks to that we can reach them using LOK as formulabar is not fully welded yet Change-Id: Icc1963ab11c1e6e3c407222d76b2a87fdaffa652 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133496 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Mert Tumer <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133655 Tested-by: Jenkins Reviewed-by: Szymon Kłos <[email protected]> diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc index a02df6204ad5..fcf95122ad35 100644 --- a/sc/inc/sc.hrc +++ b/sc/inc/sc.hrc @@ -511,6 +511,9 @@ class SvxZoomSliderItem; #define SID_NEXT_TABLE_SEL (SID_KEYFUNC_START + 40) #define SID_PREV_TABLE_SEL (SID_KEYFUNC_START + 41) +#define SID_ACCEPT_FORMULA (SID_KEYFUNC_START + 42) +#define SID_START_FORMULA (SID_KEYFUNC_START + 43) + #define SID_KEYFUNC_END (SID_KEYFUNC_START + 50) #define SID_NEW_SLOTS (SID_KEYFUNC_END) diff --git a/sc/sdi/cellsh.sdi b/sc/sdi/cellsh.sdi index 38eb86cb27b9..d61f9cb863f8 100644 --- a/sc/sdi/cellsh.sdi +++ b/sc/sdi/cellsh.sdi @@ -209,6 +209,8 @@ interface CellSelection FID_INSERT_NAME [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] FID_USE_NAME [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] SID_CANCEL [ ExecMethod = Execute; ] + SID_ACCEPT_FORMULA [ ExecMethod = Execute; ] + SID_START_FORMULA [ ExecMethod = Execute; ] SID_TOGGLE_REL [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] SID_POPUP_CONDFRMT [] SID_COLUMN_OPERATIONS [ ExecMethod = ExecuteEdit; StateMethod = GetBlockState; ] diff --git a/sc/sdi/scalc.sdi b/sc/sdi/scalc.sdi index a84b7da1348b..edf0ebb7134d 100644 --- a/sc/sdi/scalc.sdi +++ b/sc/sdi/scalc.sdi @@ -483,6 +483,42 @@ SfxVoidItem Cancel SID_CANCEL GroupId = SfxGroupId::Edit; ] +SfxVoidItem AcceptFormula SID_ACCEPT_FORMULA +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = TRUE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + Asynchron; + + AccelConfig = TRUE, + MenuConfig = FALSE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::Edit; +] + +SfxVoidItem StartFormula SID_START_FORMULA +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = TRUE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + Asynchron; + + AccelConfig = TRUE, + MenuConfig = FALSE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::Edit; +] + SfxVoidItem ChangeChartData SID_CHART_SOURCE (SfxStringItem Name SID_CHART_NAME,SfxStringItem Range SID_CHART_SOURCE,SfxBoolItem ColHeaders FN_PARAM_1,SfxBoolItem RowHeaders FN_PARAM_2) @@ -6584,6 +6620,7 @@ SfxUInt16Item NumberFormatType SID_NUMBER_TYPE_FORMAT SfxVoidItem AutoSum SID_AUTO_SUM +(SfxStringItem Function SID_AUTO_SUM) [ AutoUpdate = FALSE, FastCall = FALSE, diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx index ff717e5acf44..47c8c0fdb770 100644 --- a/sc/source/ui/app/inputwin.cxx +++ b/sc/source/ui/app/inputwin.cxx @@ -363,55 +363,61 @@ void ScInputWindow::Select() mxTextWindow->Invalidate(); // Or else the Selection remains } else if (curItemId == SID_INPUT_EQUAL) + { + StartFormula(); + } +} + +void ScInputWindow::StartFormula() +{ + ScModule* pScMod = SC_MOD(); + mxTextWindow->StartEditEngine(); + if ( pScMod->IsEditMode() ) // Isn't if e.g. protected { mxTextWindow->StartEditEngine(); - if ( pScMod->IsEditMode() ) // Isn't if e.g. protected - { - mxTextWindow->StartEditEngine(); - sal_Int32 nStartPos = 1; - sal_Int32 nEndPos = 1; + sal_Int32 nStartPos = 1; + sal_Int32 nEndPos = 1; - ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() ); - if ( pViewSh ) - { - const OUString& rString = mxTextWindow->GetTextString(); - const sal_Int32 nLen = rString.getLength(); + ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() ); + if ( pViewSh ) + { + const OUString& rString = mxTextWindow->GetTextString(); + const sal_Int32 nLen = rString.getLength(); - ScDocument& rDoc = pViewSh->GetViewData().GetDocument(); - CellType eCellType = rDoc.GetCellType( pViewSh->GetViewData().GetCurPos() ); - switch ( eCellType ) + ScDocument& rDoc = pViewSh->GetViewData().GetDocument(); + CellType eCellType = rDoc.GetCellType( pViewSh->GetViewData().GetCurPos() ); + switch ( eCellType ) + { + case CELLTYPE_VALUE: { - case CELLTYPE_VALUE: - { - nEndPos = nLen + 1; - mxTextWindow->SetTextString("=" + rString); - break; - } - case CELLTYPE_STRING: - case CELLTYPE_EDIT: - nStartPos = 0; - nEndPos = nLen; - break; - case CELLTYPE_FORMULA: - nEndPos = nLen; - break; - default: - mxTextWindow->SetTextString("="); - break; + nEndPos = nLen + 1; + mxTextWindow->SetTextString("=" + rString); + break; } + case CELLTYPE_STRING: + case CELLTYPE_EDIT: + nStartPos = 0; + nEndPos = nLen; + break; + case CELLTYPE_FORMULA: + nEndPos = nLen; + break; + default: + mxTextWindow->SetTextString("="); + break; } + } - EditView* pView = mxTextWindow->GetEditView(); - if (pView) - { - if (comphelper::LibreOfficeKit::isActive()) - TextGrabFocus(); - pView->SetSelection( ESelection(0, nStartPos, 0, nEndPos) ); - pScMod->InputChanged(pView); - SetOkCancelMode(); - pView->SetEditEngineUpdateLayout(true); - } + EditView* pView = mxTextWindow->GetEditView(); + if (pView) + { + if (comphelper::LibreOfficeKit::isActive()) + TextGrabFocus(); + pView->SetSelection( ESelection(0, nStartPos, 0, nEndPos) ); + pScMod->InputChanged(pView); + SetOkCancelMode(); + pView->SetEditEngineUpdateLayout(true); } } } @@ -1014,6 +1020,7 @@ IMPL_LINK_NOARG(ScInputWindow, DropdownClickHdl, ToolBox *, void) { ToolBoxItemId nCurID = GetCurItemId(); EndSelection(); + if (nCurID == SID_INPUT_SUM) { tools::Rectangle aRect(GetItemRect(SID_INPUT_SUM)); diff --git a/sc/source/ui/inc/inputwin.hxx b/sc/source/ui/inc/inputwin.hxx index 507d91ce5c4a..6bd4c3152712 100644 --- a/sc/source/ui/inc/inputwin.hxx +++ b/sc/source/ui/inc/inputwin.hxx @@ -301,6 +301,7 @@ public: void SetSumAssignMode(); void EnableButtons( bool bEnable ); + void StartFormula(); void SetFormulaMode( bool bSet ); bool IsInputActive(); diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx index ca337a557cd1..9234191e008c 100644 --- a/sc/source/ui/view/cellsh1.cxx +++ b/sc/source/ui/view/cellsh1.cxx @@ -2817,9 +2817,24 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) case SID_AUTO_SUM: { + const SfxItemSet *pArgs = rReq.GetArgs(); + const OUString sFunction = pArgs ? + static_cast<const SfxStringItem&>( pArgs->Get( SID_AUTO_SUM ) ).GetValue() + : ""; + + OpCode eFunction = ocSum; + if (sFunction == "average") + eFunction = ocAverage; + else if (sFunction == "count") + eFunction = ocCount; + else if (sFunction == "min") + eFunction = ocMin; + if (sFunction == "max") + eFunction = ocMax; + bool bSubTotal = false; bool bRangeFinder = false; - const OUString aFormula = pTabViewShell->DoAutoSum( bRangeFinder, bSubTotal , ocSum ); + const OUString aFormula = pTabViewShell->DoAutoSum( bRangeFinder, bSubTotal , eFunction ); if ( !aFormula.isEmpty() ) { const sal_Int32 nPar = aFormula.indexOf( '(' ); diff --git a/sc/source/ui/view/cellsh3.cxx b/sc/source/ui/view/cellsh3.cxx index 57299cdaa45b..6a23b5ab9e43 100644 --- a/sc/source/ui/view/cellsh3.cxx +++ b/sc/source/ui/view/cellsh3.cxx @@ -47,6 +47,8 @@ #include <columnspanset.hxx> #include <comphelper/lok.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <inputhdl.hxx> +#include <inputwin.hxx> #include <memory> @@ -1014,6 +1016,21 @@ void ScCellShell::Execute( SfxRequest& rReq ) } break; + case SID_ACCEPT_FORMULA: + { + if (GetViewData().HasEditView(GetViewData().GetActivePart())) + pScMod->InputEnterHandler(); + } + break; + + case SID_START_FORMULA: + { + ScInputHandler* pInputHandler = pScMod->GetInputHdl(); + if (pInputHandler && pInputHandler->GetInputWindow()) + pInputHandler->GetInputWindow()->StartFormula(); + } + break; + case SID_DATA_SELECT: pTabViewShell->StartDataSelect(); break;
