diff options
author | Heiko Tietze <tietze.heiko@gmail.com> | 2024-11-19 18:04:04 +0100 |
---|---|---|
committer | Heiko Tietze <heiko.tietze@documentfoundation.org> | 2024-11-26 13:56:48 +0100 |
commit | f395e6599facba41392eac3d646a0d505868e6fa (patch) | |
tree | c31862731252a08babbc7c9525e7af84d3f749d0 /starmath/source | |
parent | f81af8f7a5e8f86d4214bc328c44632841fbec2b (diff) |
Resolves tdf#163685 - Save user-defined formula
Change-Id: I88a1c40d3e97d77c289c8b670b52dca50dea126f
Co-authored-by: Rafael Lima <rafael.palma.lima@gmail.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176788
Reviewed-by: Rafael Lima <rafael.palma.lima@gmail.com>
Tested-by: Jenkins
Diffstat (limited to 'starmath/source')
-rw-r--r-- | starmath/source/ElementsDockingWindow.cxx | 87 | ||||
-rw-r--r-- | starmath/source/SmElementsPanel.cxx | 22 | ||||
-rw-r--r-- | starmath/source/SmElementsPanel.hxx | 6 | ||||
-rw-r--r-- | starmath/source/cfgitem.cxx | 44 | ||||
-rw-r--r-- | starmath/source/view.cxx | 38 |
5 files changed, 172 insertions, 25 deletions
diff --git a/starmath/source/ElementsDockingWindow.cxx b/starmath/source/ElementsDockingWindow.cxx index 351e4773b6bc..f202d1bd74e0 100644 --- a/starmath/source/ElementsDockingWindow.cxx +++ b/starmath/source/ElementsDockingWindow.cxx @@ -460,6 +460,7 @@ const std::vector<TranslateId> s_a5Categories{ RID_CATEGORY_FORMATS, RID_CATEGORY_OTHERS, RID_CATEGORY_EXAMPLES, + RID_CATEGORY_USERDEFINED, }; template <size_t N> @@ -493,24 +494,30 @@ struct ElementData { OUString maElementSource; OUString maHelpText; - ElementData(const OUString& aElementSource, const OUString& aHelpText) + int maPos; + ElementData(const OUString& aElementSource, const OUString& aHelpText, const int& aPos) : maElementSource(aElementSource) , maHelpText(aHelpText) + , maPos(aPos) { } }; -SmElementsControl::SmElementsControl(std::unique_ptr<weld::IconView> pIconView) +SmElementsControl::SmElementsControl(std::unique_ptr<weld::IconView> pIconView, + std::unique_ptr<weld::Menu> pMenu) : mpDocShell(new SmDocShell(SfxModelFlags::EMBEDDED_OBJECT)) , mnCurrentSetIndex(-1) , m_nSmSyntaxVersion(SmModule::get()->GetConfig()->GetDefaultSmSyntaxVersion()) + , m_bAllowDelete(false) , mpIconView(std::move(pIconView)) + , mxPopup(std::move(pMenu)) { maParser.reset(starmathdatabase::GetVersionSmParser(m_nSmSyntaxVersion)); maParser->SetImportSymbolNames(true); mpIconView->connect_query_tooltip(LINK(this, SmElementsControl, QueryTooltipHandler)); mpIconView->connect_item_activated(LINK(this, SmElementsControl, ElementActivatedHandler)); + mpIconView->connect_mouse_press(LINK(this, SmElementsControl, MousePressHdl)); } SmElementsControl::~SmElementsControl() @@ -585,7 +592,7 @@ void SmElementsControl::addElement(const OUString& aElementVisual, const OUStrin pDevice->SetOutputSizePixel(aSize); SmDrawingVisitor(*pDevice, pDevice->PixelToLogic(Point(5, 0)), pNode.get(), maFormat); - maItemDatas.push_back(std::make_unique<ElementData>(aElementSource, aHelpText)); + maItemDatas.push_back(std::make_unique<ElementData>(aElementSource, aHelpText, maItemDatas.size())); const OUString aId(weld::toId(maItemDatas.back().get())); mpIconView->insert(-1, nullptr, &aId, pDevice, nullptr); if (mpIconView->get_item_width() < aSize.Width()) @@ -602,9 +609,14 @@ OUString SmElementsControl::GetElementHelpText(const OUString& itemId) return weld::fromId<ElementData*>(itemId)->maHelpText; } -void SmElementsControl::setElementSetIndex(int nSetIndex) +int SmElementsControl::GetElementPos(const OUString& itemId) { - if (mnCurrentSetIndex == nSetIndex) + return weld::fromId<ElementData*>(itemId)->maPos; +} + +void SmElementsControl::setElementSetIndex(int nSetIndex, bool bForceBuild) +{ + if (!bForceBuild && mnCurrentSetIndex == nSetIndex) return; mnCurrentSetIndex = nSetIndex; build(); @@ -617,25 +629,36 @@ void SmElementsControl::addElements(int nCategory) mpIconView->set_item_width(0); maItemDatas.clear(); - assert(nCategory >= 0 && o3tl::make_unsigned(nCategory) < s_a5CategoryDescriptions.size()); - - const auto& [aElementsArray, aElementsArraySize] = s_a5CategoryDescriptions[nCategory]; - - for (size_t i = 0; i < aElementsArraySize; i++) + if (o3tl::make_unsigned(nCategory) < s_a5CategoryDescriptions.size()) { - const auto& [element, elementHelp, elementVisual, visualTranslatable] = aElementsArray[i]; - if (element.empty()) + const auto& [aElementsArray, aElementsArraySize] = s_a5CategoryDescriptions[nCategory]; + + for (size_t i = 0; i < aElementsArraySize; i++) { - mpIconView->append_separator({}); + const auto& [element, elementHelp, elementVisual, visualTranslatable] = aElementsArray[i]; + if (element.empty()) + { + mpIconView->append_separator({}); + } + else + { + OUString aElement(element); + OUString aVisual(elementVisual.empty() ? aElement : OUString(elementVisual)); + if (visualTranslatable) + aVisual = aVisual.replaceFirst("$1", SmResId(visualTranslatable)); + OUString aHelp(elementHelp ? SmResId(elementHelp) : OUString()); + addElement(aVisual, aElement, aHelp); + } } - else + } + else + { + css::uno::Sequence<OUString> sNames = SmModule::get()->GetConfig()->LoadUserDefinedNames(); + OUString sFormula; + for (int i = 0; i < sNames.getLength(); i++) { - OUString aElement(element); - OUString aVisual(elementVisual.empty() ? aElement : OUString(elementVisual)); - if (visualTranslatable) - aVisual = aVisual.replaceFirst("$1", SmResId(visualTranslatable)); - OUString aHelp(elementHelp ? SmResId(elementHelp) : OUString()); - addElement(aVisual, aElement, aHelp); + SmModule::get()->GetConfig()->GetUserDefinedFormula(sNames[i], sFormula); + addElement(sFormula, sFormula, sNames[i]); } } @@ -649,6 +672,7 @@ void SmElementsControl::build() { case 5: addElements(mnCurrentSetIndex); + m_sHoveredItem = "nil"; // if list is empty we must not use the previously hovered item break; case 6: default: @@ -671,7 +695,10 @@ void SmElementsControl::setSmSyntaxVersion(sal_Int16 nSmSyntaxVersion) IMPL_LINK(SmElementsControl, QueryTooltipHandler, const weld::TreeIter&, iter, OUString) { if (const OUString id = mpIconView->get_id(iter); !id.isEmpty()) + { + m_sHoveredItem = id; return GetElementHelpText(id); + } return {}; } @@ -684,4 +711,24 @@ IMPL_LINK_NOARG(SmElementsControl, ElementActivatedHandler, weld::IconView&, boo return true; } +IMPL_LINK(SmElementsControl, MousePressHdl, const MouseEvent&, rEvt, bool) +{ + if (rEvt.IsRight() && m_bAllowDelete && (m_sHoveredItem != "nil")) + { + mpIconView->select( GetElementPos(m_sHoveredItem) ); + OUString sElementId = mpIconView->get_selected_id(); + if (!sElementId.isEmpty()) + { + OUString sResponse = mxPopup->popup_at_rect( + mpIconView.get(), tools::Rectangle(rEvt.GetPosPixel(), Size(1, 1))); + if (sResponse == "delete") + { + SmModule::get()->GetConfig()->DeleteUserDefinedFormula( GetElementHelpText(m_sHoveredItem) ); + build(); //refresh view + } + mpIconView->unselect_all(); + } + } + return true; +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/SmElementsPanel.cxx b/starmath/source/SmElementsPanel.cxx index ad0fb7089890..afe27a80fc50 100644 --- a/starmath/source/SmElementsPanel.cxx +++ b/starmath/source/SmElementsPanel.cxx @@ -24,6 +24,7 @@ #include <sfx2/lokcomponenthelpers.hxx> #include <svl/stritem.hxx> #include <svl/itemset.hxx> +#include <svl/hint.hxx> #include "SmElementsPanel.hxx" #include <starmath.hrc> @@ -45,8 +46,8 @@ SmElementsPanel::SmElementsPanel(weld::Widget& rParent, const SfxBindings& rBind u"modules/smath/ui/sidebarelements_math.ui"_ustr) , mrBindings(rBindings) , mxCategoryList(m_xBuilder->weld_combo_box(u"categorylist"_ustr)) - , mxElementsControl( - std::make_unique<SmElementsControl>(m_xBuilder->weld_icon_view(u"elements"_ustr))) + , mxElementsControl(std::make_unique<SmElementsControl>( + m_xBuilder->weld_icon_view(u"elements"_ustr), m_xBuilder->weld_menu("deletemenu"))) { for (const auto& rCategoryId : SmElementsControl::categories()) mxCategoryList->append_text(SmResId(rCategoryId)); @@ -58,6 +59,8 @@ SmElementsPanel::SmElementsPanel(weld::Widget& rParent, const SfxBindings& rBind mxElementsControl->setElementSetIndex(0); mxElementsControl->SetSelectHdl(LINK(this, SmElementsPanel, ElementClickHandler)); + + StartListening(*GetView()); } SmElementsPanel::~SmElementsPanel() @@ -66,6 +69,15 @@ SmElementsPanel::~SmElementsPanel() mxCategoryList.reset(); } +void SmElementsPanel::Notify(SfxBroadcaster&, const SfxHint& rHint) +{ + if (rHint.GetId() == SfxHintId::SmNewUserFormula) + { + mxCategoryList->set_active_text(SmResId(RID_CATEGORY_USERDEFINED)); + mxElementsControl->setElementSetIndex(mxCategoryList->get_active(), true); + } +} + IMPL_LINK(SmElementsPanel, CategorySelectedHandle, weld::ComboBox&, rList, void) { const int nActive = rList.get_active(); @@ -74,6 +86,12 @@ IMPL_LINK(SmElementsPanel, CategorySelectedHandle, weld::ComboBox&, rList, void) mxElementsControl->setElementSetIndex(nActive); if (SmViewShell* pViewSh = GetView()) mxElementsControl->setSmSyntaxVersion(pViewSh->GetDoc()->GetSmSyntaxVersion()); + + // If the "User-defined" category is selected, allow deletion + if (mxCategoryList->get_active_text() == SmResId(RID_CATEGORY_USERDEFINED)) + mxElementsControl->SetAllowDelete(true); + else + mxElementsControl->SetAllowDelete(false); } IMPL_LINK(SmElementsPanel, ElementClickHandler, const OUString&, ElementSource, void) diff --git a/starmath/source/SmElementsPanel.hxx b/starmath/source/SmElementsPanel.hxx index c3dde01c6724..c1f4b2ab31f3 100644 --- a/starmath/source/SmElementsPanel.hxx +++ b/starmath/source/SmElementsPanel.hxx @@ -21,6 +21,7 @@ #include <sal/config.h> +#include <svl/lstner.hxx> #include <sfx2/bindings.hxx> #include <sfx2/sidebar/PanelLayout.hxx> #include <vcl/customweld.hxx> @@ -32,10 +33,13 @@ namespace sm::sidebar { -class SmElementsPanel : public PanelLayout +class SmElementsPanel : public PanelLayout, public SfxListener { public: static std::unique_ptr<PanelLayout> Create(weld::Widget& rParent, const SfxBindings& rBindings); + + void Notify(SfxBroadcaster& rBC, const SfxHint& rHint); + SmElementsPanel(weld::Widget& rParent, const SfxBindings& rBindings); ~SmElementsPanel(); diff --git a/starmath/source/cfgitem.cxx b/starmath/source/cfgitem.cxx index 78cdbc97e131..6f0134047d07 100644 --- a/starmath/source/cfgitem.cxx +++ b/starmath/source/cfgitem.cxx @@ -44,6 +44,7 @@ using namespace com::sun::star::beans; constexpr OUString SYMBOL_LIST = u"SymbolList"_ustr; constexpr OUString FONT_FORMAT_LIST = u"FontFormatList"_ustr; +constexpr OUString USER_DEFINED_LIST = u"User-Defined"_ustr; static Sequence< OUString > lcl_GetFontPropertyNames() { @@ -575,7 +576,6 @@ void SmMathConfig::SetSymbols( const std::vector< SmSym > &rNewSymbols ) StripFontFormatList( rNewSymbols ); } - SmFontFormatList & SmMathConfig::GetFontFormatList() { if (!pFontFormatList) @@ -585,7 +585,6 @@ SmFontFormatList & SmMathConfig::GetFontFormatList() return *pFontFormatList; } - void SmMathConfig::LoadFontFormatList() { if (!pFontFormatList) @@ -661,6 +660,47 @@ void SmMathConfig::ReadFontFormat( SmFontFormat &rFontFormat, OSL_ENSURE( bOK, "read FontFormat failed" ); } +css::uno::Sequence<OUString> SmMathConfig::LoadUserDefinedNames() +{ + m_sUserDefinedNames = GetNodeNames(USER_DEFINED_LIST); + return m_sUserDefinedNames; +} + +void SmMathConfig::GetUserDefinedFormula(std::u16string_view sName, OUString &sFormula) +{ + css::uno::Sequence<OUString> aNames(1); + OUString* pName = aNames.getArray(); + pName[0] = USER_DEFINED_LIST + "/" + sName + "/FormulaText"; + const Sequence<Any> aValues(GetProperties(aNames)); + const Any* pValues = aValues.getConstArray(); + const Any* pVal = pValues; + *pVal >>= sFormula; +} + +bool SmMathConfig::HasUserDefinedFormula(std::u16string_view sName) +{ + for (int i = 0; i < m_sUserDefinedNames.getLength(); i++) + if (m_sUserDefinedNames[i] == sName) + return true; + return false; +} + +void SmMathConfig::SaveUserDefinedFormula(std::u16string_view sName, const OUString& sElement) +{ + Sequence<PropertyValue> pValues(1); + auto pArgs = pValues.getArray(); + + pArgs[0].Name = USER_DEFINED_LIST + "/" + sName + "/FormulaText"; + pArgs[0].Value <<= sElement; + + SetSetProperties( USER_DEFINED_LIST, pValues ); +} + +void SmMathConfig::DeleteUserDefinedFormula(std::u16string_view sName) +{ + Sequence<OUString> aElements { OUString(sName) }; + ClearNodeElements(USER_DEFINED_LIST, aElements); +} void SmMathConfig::SaveFontFormatList() { diff --git a/starmath/source/view.cxx b/starmath/source/view.cxx index f1130e5701de..da074984964d 100644 --- a/starmath/source/view.cxx +++ b/starmath/source/view.cxx @@ -89,6 +89,7 @@ #include <mathmlimport.hxx> #include <cursor.hxx> #include "accessibility.hxx" +#include <svl/hint.hxx> #include <ElementsDockingWindow.hxx> #include <helpids.h> @@ -1840,6 +1841,39 @@ void SmViewShell::Execute(SfxRequest& rReq) GetViewFrame().GetBindings().Invalidate(bRTL ? SID_ATTR_PARA_LEFT_TO_RIGHT : SID_ATTR_PARA_RIGHT_TO_LEFT); } break; + case SID_SAVE_FORMULA: + { + OUString aName = "My Formula 1"; + OUString aDesc(SmResId(STR_USER_DEFINED_FORMULA)); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg( + pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + if (pDlg->Execute() == RET_OK) + { + aName = pDlg->GetName(); + if (SmModule::get()->GetConfig()->HasUserDefinedFormula(aName)) + { + std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog( + GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo, + SmResId(STR_USER_DEFINED_FORMULA_EXISTS).replaceAll("%1", aName))); + if (xQuery->run() == RET_NO) + break; + } + SmEditWindow* pEditWin = GetEditWindow(); + SmModule::get()->GetConfig()->SaveUserDefinedFormula(aName, pEditWin->GetText()); + + // Show the Elements sidebar with the "User-defined" entry selected + GetViewFrame().ShowChildWindow(SID_SIDEBAR); + sfx2::sidebar::Sidebar::ShowPanel(u"MathElementsPanel", + GetViewFrame().GetFrame().GetFrameInterface()); + GetViewFrame().GetBindings().Invalidate( SID_ELEMENTSDOCKINGWINDOW ); + Broadcast(SfxHint(SfxHintId::SmNewUserFormula)); + rReq.Ignore (); + } + pDlg.disposeAndClear(); + } + break; } rReq.Done(); } @@ -1949,6 +1983,10 @@ void SmViewShell::GetState(SfxItemSet &rSet) case SID_ATTR_PARA_RIGHT_TO_LEFT: rSet.Put(SfxBoolItem(nWh, GetDoc()->GetFormat().IsRightToLeft())); break; + case SID_SAVE_FORMULA: + if (!pEditWin || pEditWin->IsEmpty()) + rSet.DisableItem(nWh); + break; } } } |