Files
ElyOffice/patches/libreoffice/0045-lok-command-states.patch
T
ZacharyZhang-NYandClaude Opus 5.5 87886c8a8d R5.5: ElyTable right-click menus, Excel-style; three rounds used, last fixes tested
Grid and header menus share ely_office::menu with ElyDoc. Each item's
availability is the kernel's state for the exact command it runs
(patch 0045). Patch 0046 lets a header select its row or column while
a shape is selected or its text is edited: the view shell ends the
drawing edit, keeps the typed text, leaves drawing mode, then marks.
Ely no longer sends Esc first.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 13:02:10 -04:00

87 lines
3.5 KiB
Diff

LOK: read whether listed commands may run now
LOK pushes enable states only for a fixed list, and only after
idle bindings update. A menu opened right after a selection needs
the answer now, for commands outside that list (hide rows, column
width, clear contents). getCommandValues(".uno:CommandStates?
commands=.uno:A,.uno:B") flushes the dispatcher and asks it for
each slot, as the menu bar would: true unless disabled or unknown
to the current shells. A name that is no slot fails the read.
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -152,6 +152,7 @@
#include <sfx2/docfile.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/viewfrm.hxx>
+#include <sfx2/msg.hxx>
#include <sfx2/msgpool.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/lokcomponenthelpers.hxx>
@@ -6672,6 +6673,45 @@ enum class UndoOrRedo
}
+/// Whether each listed command may run now.
+static char* getCommandStates(std::string_view aList)
+{
+ SfxViewShell* pViewShell = SfxViewShell::Current();
+ if (!pViewShell)
+ {
+ SetLastExceptionMsg(u"CommandStates: no current view"_ustr);
+ return nullptr;
+ }
+ SfxViewFrame& rFrame = pViewShell->GetViewFrame();
+ SfxDispatcher* pDispatcher = rFrame.GetBindings().GetDispatcher();
+ pDispatcher->Flush();
+ const SfxSlotPool& rPool = SfxSlotPool::GetSlotPool(&rFrame);
+ tools::JsonWriter aJson;
+ {
+ auto aStates = aJson.startNode("commandStates");
+ sal_Int32 nIndex = 0;
+ do
+ {
+ std::string_view aCommand = o3tl::getToken(aList, 0, ',', nIndex);
+ if (!aCommand.starts_with(".uno:"))
+ {
+ SetLastExceptionMsg(u"CommandStates: not a .uno: command"_ustr);
+ return nullptr;
+ }
+ const SfxSlot* pSlot = rPool.GetUnoSlot(OUString::fromUtf8(aCommand.substr(5)));
+ if (!pSlot)
+ {
+ SetLastExceptionMsg(OUString::fromUtf8(aCommand) + u" : unknown command"_ustr);
+ return nullptr;
+ }
+ SfxPoolItemHolder aState;
+ const SfxItemState eState = pDispatcher->QueryState(pSlot->GetSlotId(), aState);
+ aJson.put(aCommand, eState != SfxItemState::DISABLED && eState != SfxItemState::UNKNOWN);
+ } while (nIndex >= 0);
+ }
+ return convertOString(aJson.finishAndGetAsOString());
+}
+
/// Returns the JSON representation of either an undo or a redo stack.
static char* getUndoOrRedo(LibreOfficeKitDocument* pThis, UndoOrRedo eCommand)
{
@@ -6808,6 +6848,7 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
static constexpr std::string_view aViewRowColumnHeaders(".uno:ViewRowColumnHeaders");
static constexpr std::string_view aSheetGeometryData(".uno:SheetGeometryData");
static constexpr std::string_view aFontSubset(".uno:FontSubset&name=");
+ static constexpr std::string_view aCommandStates(".uno:CommandStates?commands=");
ITiledRenderable* pDoc = getTiledRenderable(pThis);
if (!pDoc)
@@ -6983,6 +7024,10 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
pDoc->getCellCursor(aJsonWriter);
return convertOString(aJsonWriter.finishAndGetAsOString());
}
+ else if (aCommand.starts_with(aCommandStates))
+ {
+ return getCommandStates(aCommand.substr(aCommandStates.size()));
+ }
else if (aCommand.starts_with(aFontSubset))
{
return getFontSubset(aCommand.substr(aFontSubset.size()));