basctl/Library_basctl.mk | 1 basctl/UIConfig_basicide.mk | 1 basctl/inc/strings.hrc | 3 basctl/sdi/baside.sdi | 6 basctl/source/basicide/baside2.cxx | 12 basctl/source/basicide/baside2.hxx | 7 basctl/source/basicide/baside3.cxx | 9 basctl/source/basicide/basides1.cxx | 26 basctl/source/basicide/basides2.cxx | 2 basctl/source/basicide/basides3.cxx | 2 basctl/source/basicide/basidesh.cxx | 20 basctl/source/basicide/basobj3.cxx | 3 basctl/source/basicide/idedataprovider.cxx | 8 basctl/source/basicide/objectbrowser.cxx | 207 ++++ basctl/source/basicide/objectbrowsersearch.cxx | 63 + basctl/source/inc/baside3.hxx | 9 basctl/source/inc/basidesh.hxx | 6 basctl/source/inc/idedataprovider.hxx | 11 basctl/source/inc/objectbrowser.hxx | 88 +- basctl/source/inc/objectbrowsersearch.hxx | 39 basctl/uiconfig/basicide/menubar/menubar.xml | 1 basctl/uiconfig/basicide/ui/objectbrowser.ui | 423 ++++++++++ include/sfx2/sfxsids.hrc | 1 officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu | 5 officecfg/registry/schema/org/openoffice/Office/BasicIDE.xcs | 6 sfx2/sdi/sfx.sdi | 19 26 files changed, 957 insertions(+), 21 deletions(-)
New commits: commit 87a7d94cc35253451e26e789e6243f2c5fd3ac77 Author: Devansh Varshney <[email protected]> AuthorDate: Fri Sep 19 20:59:13 2025 +0530 Commit: Jonathan Clark <[email protected]> CommitDate: Fri Sep 26 21:46:24 2025 +0200 tdf#165785: basctl: Integrate blank UI shell for Object Browser This patch integrates the user interface for the new Object Browser. It introduces the UI definition file and the C++ logic to create, display, and manage the window's lifecycle within the IDE. (GSoC 2025 - Object Browser: UI Shell Integration) Change-Id: I9a2d7c319a7590e44eafe3d575eb3b0aeffb7e86 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191206 Reviewed-by: Jonathan Clark <[email protected]> Tested-by: Jenkins diff --git a/basctl/Library_basctl.mk b/basctl/Library_basctl.mk index 37c94edd089a..c9f2bb88bda6 100644 --- a/basctl/Library_basctl.mk +++ b/basctl/Library_basctl.mk @@ -108,6 +108,7 @@ $(eval $(call gb_Library_add_exception_objects,basctl,\ basctl/source/basicide/BasicColorConfig \ basctl/source/basicide/ColorSchemeDialog \ basctl/source/basicide/objectbrowser \ + basctl/source/basicide/objectbrowsersearch \ basctl/source/basicide/ObjectCatalog \ basctl/source/basicide/sbxitem \ basctl/source/basicide/scriptdocument \ diff --git a/basctl/UIConfig_basicide.mk b/basctl/UIConfig_basicide.mk index 217ea6c01708..9609c5e2571e 100644 --- a/basctl/UIConfig_basicide.mk +++ b/basctl/UIConfig_basicide.mk @@ -53,6 +53,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/BasicIDE,\ basctl/uiconfig/basicide/ui/managelanguages \ basctl/uiconfig/basicide/ui/modulepage \ basctl/uiconfig/basicide/ui/newlibdialog \ + basctl/uiconfig/basicide/ui/objectbrowser \ basctl/uiconfig/basicide/ui/organizedialog \ basctl/uiconfig/basicide/ui/sortmenu \ )) diff --git a/basctl/inc/strings.hrc b/basctl/inc/strings.hrc index 60cf263b9ac8..72abed45361d 100644 --- a/basctl/inc/strings.hrc +++ b/basctl/inc/strings.hrc @@ -102,6 +102,9 @@ #define RID_STR_CHOOSE NC_("RID_STR_CHOOSE", "Choose") #define RID_STR_RUN NC_("RID_STR_RUN", "Run") #define RID_STR_RECORD NC_("RID_STR_RECORD", "~Save") +#define RID_STR_OBJECT_BROWSER NC_("RID_STR_OBJECT_BROWSER", "Object Browser") +#define RID_STR_OB_SCOPE_ALL NC_("RID_STR_OB_SCOPE_ALL", "All Libraries") +#define RID_STR_OB_SCOPE_CURRENT NC_("RID_STR_OB_SCOPE_CURRENT", "Current Document") #define RID_BASICIDE_OBJCAT NC_("RID_BASICIDE_OBJCAT", "Object Catalog") // Property Browser Headline ---------------------------------------------------------------- #define RID_STR_BRWTITLE_PROPERTIES NC_("RID_STR_BRWTITLE_PROPERTIES", "Properties: ") diff --git a/basctl/sdi/baside.sdi b/basctl/sdi/baside.sdi index 34f34a6362e2..3818296cb434 100644 --- a/basctl/sdi/baside.sdi +++ b/basctl/sdi/baside.sdi @@ -242,6 +242,12 @@ shell basctl_Shell StateMethod = GetState; ] + SID_BASICIDE_OBJECT_BROWSER + [ + ExecMethod = ExecuteGlobal; + StateMethod = GetState; + ] + SID_BASICIDE_OBJCAT [ ExecMethod = ExecuteGlobal; diff --git a/basctl/source/basicide/baside2.cxx b/basctl/source/basicide/baside2.cxx index 5276895999d7..3bf17508e46a 100644 --- a/basctl/source/basicide/baside2.cxx +++ b/basctl/source/basicide/baside2.cxx @@ -22,6 +22,7 @@ #include <basobj.hxx> #include <basidesh.hxx> #include "brkdlg.hxx" +#include "idetimer.hxx" #include <iderdll.hxx> #include <iderid.hxx> #include "moduldlg.hxx" @@ -1464,11 +1465,12 @@ void ModulWindow::SetEditorColorScheme(const OUString& rColorScheme) rEditWindow.UpdateSyntaxHighlighting(); } -ModulWindowLayout::ModulWindowLayout (vcl::Window* pParent, ObjectCatalog& rObjectCatalog_) : +ModulWindowLayout::ModulWindowLayout (vcl::Window* pParent, ObjectBrowser& rObjectBrowser_, ObjectCatalog& rObjectCatalog_) : Layout(pParent), pChild(nullptr), aWatchWindow(VclPtr<WatchWindow>::Create(this)), aStackWindow(VclPtr<StackWindow>::Create(this)), + rObjectBrowser(rObjectBrowser_), rObjectCatalog(rObjectCatalog_) { // Get active color scheme from the registry @@ -1516,6 +1518,10 @@ void ModulWindowLayout::Activating (BaseWindow& rChild) pChild = &static_cast<ModulWindow&>(rChild); aWatchWindow->Show(); aStackWindow->Show(); + IdeTimer aTimer(u"Shell::BASIDE2::ModulWindowLayout::Activating::ShowObjectBrowser "_ustr); + rObjectBrowser.Show(); + rObjectBrowser.SetLayoutWindow(this); + rObjectBrowser.RefreshUI(); rObjectCatalog.Show(); rObjectCatalog.SetLayoutWindow(this); rObjectCatalog.UpdateEntries(); @@ -1530,6 +1536,7 @@ void ModulWindowLayout::Deactivating () Layout::Deactivating(); aWatchWindow->Hide(); aStackWindow->Hide(); + rObjectBrowser.Hide(); rObjectCatalog.Hide(); pChild = nullptr; } @@ -1572,7 +1579,8 @@ void ModulWindowLayout::ShowStackWindow(bool bVisible) void ModulWindowLayout::OnFirstSize (tools::Long const nWidth, tools::Long const nHeight) { - AddToLeft(&rObjectCatalog, Size(nWidth * 0.20, nHeight * 0.75)); + AddToLeft(&rObjectBrowser, Size(nWidth * 0.25, nHeight * 0.375)); + AddToLeft(&rObjectCatalog, Size(nWidth * 0.20, nHeight * 0.375)); AddToBottom(aWatchWindow.get(), Size(nWidth * 0.67, nHeight * 0.25)); AddToBottom(aStackWindow.get(), Size(nWidth * 0.33, nHeight * 0.25)); } diff --git a/basctl/source/basicide/baside2.hxx b/basctl/source/basicide/baside2.hxx index 1dd5d167207a..4cada87fec78 100644 --- a/basctl/source/basicide/baside2.hxx +++ b/basctl/source/basicide/baside2.hxx @@ -51,6 +51,7 @@ namespace com::sun::star::beans { class XMultiPropertySet; } namespace basctl { +class ObjectBrowser; class ObjectCatalog; class CodeCompleteWindow; class ModulWindowLayout; @@ -406,9 +407,12 @@ public: class ModulWindowLayout: public Layout { public: - ModulWindowLayout (vcl::Window* pParent, ObjectCatalog&); + ModulWindowLayout (vcl::Window* pParent, ObjectBrowser&, ObjectCatalog&); virtual ~ModulWindowLayout() override; virtual void dispose() override; + + ModulWindowLayout(const ModulWindowLayout&) = delete; + ModulWindowLayout& operator=(const ModulWindowLayout&) = delete; public: // Layout: virtual void Activating (BaseWindow&) override; @@ -440,6 +444,7 @@ private: // dockable windows VclPtr<WatchWindow> aWatchWindow; VclPtr<StackWindow> aStackWindow; + ObjectBrowser& rObjectBrowser; ObjectCatalog& rObjectCatalog; // Active color scheme ID OUString m_sColorSchemeId; diff --git a/basctl/source/basicide/baside3.cxx b/basctl/source/basicide/baside3.cxx index 037bd3197a7e..5c7bfa4fec7b 100644 --- a/basctl/source/basicide/baside3.cxx +++ b/basctl/source/basicide/baside3.cxx @@ -1200,8 +1200,9 @@ SbxItemType DialogWindow::GetSbxType () const // DialogWindowLayout -DialogWindowLayout::DialogWindowLayout (vcl::Window* pParent, ObjectCatalog& rObjectCatalog_) : +DialogWindowLayout::DialogWindowLayout (vcl::Window* pParent, ObjectBrowser& rObjectBrowser_, ObjectCatalog& rObjectCatalog_) : Layout(pParent), + rObjectBrowser(rObjectBrowser_), rObjectCatalog(rObjectCatalog_), pPropertyBrowser(nullptr) { @@ -1260,6 +1261,10 @@ void DialogWindowLayout::UpdatePropertyBrowser () void DialogWindowLayout::Activating (BaseWindow& rChild) { assert(dynamic_cast<DialogWindow*>(&rChild)); + rObjectBrowser.Show(); + rObjectBrowser.SetLayoutWindow(this); + rObjectBrowser.RefreshUI(); + rObjectCatalog.SetLayoutWindow(this); rObjectCatalog.UpdateEntries(); rObjectCatalog.Show(); @@ -1271,6 +1276,7 @@ void DialogWindowLayout::Activating (BaseWindow& rChild) void DialogWindowLayout::Deactivating () { Layout::Deactivating(); + rObjectBrowser.Hide(); rObjectCatalog.Hide(); if (pPropertyBrowser) pPropertyBrowser->Hide(); @@ -1310,6 +1316,7 @@ void DialogWindowLayout::GetState (SfxItemSet& rSet, unsigned nWhich) void DialogWindowLayout::OnFirstSize (tools::Long const nWidth, tools::Long const nHeight) { + AddToLeft(&rObjectBrowser, Size(nWidth * 0.25, nHeight * 0.35)); AddToLeft(&rObjectCatalog, Size(nWidth * 0.25, nHeight * 0.35)); if (pPropertyBrowser) AddPropertyBrowser(); diff --git a/basctl/source/basicide/basides1.cxx b/basctl/source/basicide/basides1.cxx index 626362473e0e..8cc67c9c1b08 100644 --- a/basctl/source/basicide/basides1.cxx +++ b/basctl/source/basicide/basides1.cxx @@ -422,6 +422,23 @@ void Shell::ExecuteGlobal( SfxRequest& rReq ) } break; + case SID_BASICIDE_OBJECT_BROWSER: + { + bool bIsNowVisible = !aObjectBrowser->IsVisible(); + aObjectBrowser->Show(bIsNowVisible); + + if (pLayout) + pLayout->ArrangeWindows(); + + if (SfxBindings* pBindings = GetBindingsPtr()) + pBindings->Invalidate(SID_BASICIDE_OBJECT_BROWSER); + + auto pChanges = comphelper::ConfigurationChanges::create(); + officecfg::Office::BasicIDE::EditorSettings::ObjectBrowser::set(bIsNowVisible, pChanges); + pChanges->commit(); + } + break; + case SID_BASICIDE_OBJCAT: { // Toggle the visibility of the object catalog @@ -959,6 +976,15 @@ void Shell::GetState(SfxItemSet &rSet) } break; + case SID_BASICIDE_OBJECT_BROWSER: + { + if (pLayout) + rSet.Put(SfxBoolItem(nWh, aObjectBrowser->IsVisible())); + else + rSet.Put(SfxVisibilityItem(nWh, false)); + } + break; + case SID_BASICIDE_OBJCAT: { if (pLayout) diff --git a/basctl/source/basicide/basides2.cxx b/basctl/source/basicide/basides2.cxx index 249b3e6f43c7..92dee60a4386 100644 --- a/basctl/source/basicide/basides2.cxx +++ b/basctl/source/basicide/basides2.cxx @@ -165,7 +165,7 @@ VclPtr<ModulWindow> Shell::CreateBasWin( const ScriptDocument& rDocument, const { // new module window if (!pModulLayout) - pModulLayout.reset(VclPtr<ModulWindowLayout>::Create(&GetViewFrame().GetWindow(), *aObjectCatalog)); + pModulLayout.reset(VclPtr<ModulWindowLayout>::Create(&GetViewFrame().GetWindow(), *aObjectBrowser, *aObjectCatalog)); pWin = VclPtr<ModulWindow>::Create(pModulLayout.get(), rDocument, aLibName, aModName, aModule); nKey = InsertWindowInTable( pWin ); } diff --git a/basctl/source/basicide/basides3.cxx b/basctl/source/basicide/basides3.cxx index 2c9ba2bc1099..37c4b2fe13da 100644 --- a/basctl/source/basicide/basides3.cxx +++ b/basctl/source/basicide/basides3.cxx @@ -81,7 +81,7 @@ VclPtr<DialogWindow> Shell::CreateDlgWin( const ScriptDocument& rDocument, const // new dialog window if (!pDialogLayout) - pDialogLayout.reset(VclPtr<DialogWindowLayout>::Create(&GetViewFrame().GetWindow(), *aObjectCatalog)); + pDialogLayout.reset(VclPtr<DialogWindowLayout>::Create(&GetViewFrame().GetWindow(), *aObjectBrowser, *aObjectCatalog)); pWin = VclPtr<DialogWindow>::Create(pDialogLayout.get(), rDocument, aLibName, aDlgName, xDialogModel); nKey = InsertWindowInTable( pWin ); } diff --git a/basctl/source/basicide/basidesh.cxx b/basctl/source/basicide/basidesh.cxx index ef3e89a78f8f..06f58a9b97fa 100644 --- a/basctl/source/basicide/basidesh.cxx +++ b/basctl/source/basicide/basidesh.cxx @@ -170,6 +170,7 @@ Shell::Shell( SfxViewFrame& rFrame_, SfxViewShell* /* pOldShell */ ) : aHScrollBar( VclPtr<ScrollAdaptor>::Create(&GetViewFrame().GetWindow(), true) ), aVScrollBar( VclPtr<ScrollAdaptor>::Create(&GetViewFrame().GetWindow(), false) ), pLayout(nullptr), + aObjectBrowser(VclPtr<ObjectBrowser>::Create(*this, &GetViewFrame().GetWindow())), aObjectCatalog(VclPtr<ObjectCatalog>::Create(&GetViewFrame().GetWindow())), m_bAppBasicModified( false ), m_aNotifier( *this ) @@ -214,6 +215,11 @@ void Shell::Init() InitTabBar(); InitZoomLevel(); + // Initialize the visibility of the Object Browser + bool bObjBrowserVisible = ::officecfg::Office::BasicIDE::EditorSettings::ObjectBrowser::get(); + if (!bObjBrowserVisible) + aObjectBrowser->Show(bObjBrowserVisible); + // Initialize the visibility of the Object Catalog bool bObjCatVisible = ::officecfg::Office::BasicIDE::EditorSettings::ObjectCatalog::get(); if (!bObjCatVisible) @@ -248,6 +254,7 @@ Shell::~Shell() SetWindow( nullptr ); SetCurWindow( nullptr ); + aObjectBrowser.disposeAndClear(); aObjectCatalog.disposeAndClear(); aVScrollBar.disposeAndClear(); aHScrollBar.disposeAndClear(); @@ -529,6 +536,10 @@ void Shell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) if (rHint.GetId() == SfxHintId::Dying) { EndListening( rBC, true /* log off all */ ); + + if (aObjectBrowser) + aObjectBrowser->RefreshUI(/*bForceKeepUno=*/true); + aObjectCatalog->UpdateEntries(); } @@ -862,6 +873,7 @@ void Shell::InvalidateBasicIDESlots() pBindings->Invalidate( SID_SIGNATURE ); pBindings->Invalidate( SID_BASICIDE_CHOOSEMACRO ); pBindings->Invalidate( SID_BASICIDE_MODULEDLG ); + pBindings->Invalidate( SID_BASICIDE_OBJECT_BROWSER ); pBindings->Invalidate( SID_BASICIDE_OBJCAT ); pBindings->Invalidate( SID_BASICSTOP ); pBindings->Invalidate( SID_BASICRUN ); @@ -983,6 +995,14 @@ void Shell::SetCurLibForLocalization( const ScriptDocument& rDocument, const OUS m_pCurLocalizationMgr->handleTranslationbar(); } +void Shell::UpdateObjectBrowser() +{ + if (aObjectBrowser) + { + aObjectBrowser->RefreshUI(); + } +} + } // namespace basctl /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/basicide/basobj3.cxx b/basctl/source/basicide/basobj3.cxx index b5cdbf364ebb..6b0d241e7e45 100644 --- a/basctl/source/basicide/basobj3.cxx +++ b/basctl/source/basicide/basobj3.cxx @@ -260,6 +260,9 @@ void MarkDocumentModified( const ScriptDocument& rDocument ) rDocument.setDocumentModified(); } + if (pShell) + pShell->UpdateObjectBrowser(); + // tdf#130161 in all cases call UpdateObjectCatalog if (pShell) pShell->UpdateObjectCatalog(); diff --git a/basctl/source/basicide/idedataprovider.cxx b/basctl/source/basicide/idedataprovider.cxx index 3c094c751426..7cd4458ba6e8 100644 --- a/basctl/source/basicide/idedataprovider.cxx +++ b/basctl/source/basicide/idedataprovider.cxx @@ -8,6 +8,7 @@ */ #include <idedataprovider.hxx> +#include <vcl/svapp.hxx> namespace basctl { @@ -15,6 +16,13 @@ IdeDataProvider::IdeDataProvider() {} IdeDataProvider::~IdeDataProvider() = default; +void IdeDataProvider::AsyncInitialize(const Link<void*, void>& rFinishCallback) +{ + Application::PostUserEvent(rFinishCallback); +} + +bool IdeDataProvider::IsInitialized() const { return m_bInitialized; } + } // namespace basctl /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basctl/source/basicide/objectbrowser.cxx b/basctl/source/basicide/objectbrowser.cxx index ec4d8a811394..8b7c9f411ed9 100644 --- a/basctl/source/basicide/objectbrowser.cxx +++ b/basctl/source/basicide/objectbrowser.cxx @@ -7,30 +7,223 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <iderid.hxx> -#include "idetimer.hxx" +#include <basidesh.hxx> #include <objectbrowser.hxx> - +#include <objectbrowsersearch.hxx> +#include <idedataprovider.hxx> +#include <iderid.hxx> #include <strings.hrc> +#include <vcl/svapp.hxx> +#include <vcl/taskpanelist.hxx> +#include <sal/log.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/viewfrm.hxx> + namespace basctl { -ObjectBrowser::ObjectBrowser(vcl::Window* pParent) - : basctl::DockingWindow(pParent, u""_ustr, u"ObjectBrowser"_ustr) +ObjectBrowser::ObjectBrowser(Shell& rShell, vcl::Window* pParent) + : basctl::DockingWindow(pParent, u"modules/BasicIDE/ui/objectbrowser.ui"_ustr, + u"ObjectBrowser"_ustr) + , m_pShell(&rShell) , m_pDataProvider(std::make_unique<IdeDataProvider>()) + , m_bDisposed(false) + , m_bUIInitialized(false) + , m_pDocNotifier(std::make_unique<DocumentEventNotifier>(*this)) { + SetText(IDEResId(RID_STR_OBJECT_BROWSER)); + SetBackground(GetSettings().GetStyleSettings().GetWindowColor()); + EnableInput(true, true); + + Initialize(); } -ObjectBrowser::~ObjectBrowser() {} +ObjectBrowser::~ObjectBrowser() { disposeOnce(); } + +void ObjectBrowser::Initialize() +{ + if (m_eInitState != ObjectBrowserInitState::NotInitialized) + return; + + // Set state to initializing + m_eInitState = ObjectBrowserInitState::Initializing; + + // Handles to all our widgets + m_xScopeSelector = m_xBuilder->weld_combo_box(u"ScopeSelector"_ustr); + m_pFilterBox = m_xBuilder->weld_entry(u"FilterBox"_ustr); + m_xLeftTreeView = m_xBuilder->weld_tree_view(u"LeftTreeView"_ustr); + m_xRightMembersView = m_xBuilder->weld_tree_view(u"RightMembersView"_ustr); + m_xDetailPane = m_xBuilder->weld_text_view(u"DetailPane"_ustr); + m_xStatusLabel = m_xBuilder->weld_label(u"StatusLabel"_ustr); + m_xRightPaneHeaderLabel = m_xBuilder->weld_label(u"RightPaneHeaderLabel"_ustr); + m_xBackButton = m_xBuilder->weld_button(u"BackButton"_ustr); + m_xForwardButton = m_xBuilder->weld_button(u"ForwardButton"_ustr); + m_xClearSearchButton = m_xBuilder->weld_button(u"ClearSearchButton"_ustr); + + m_pSearchHandler = std::make_unique<ObjectBrowserSearch>(*this); + m_pSearchHandler->Initialize(); + + if (m_xScopeSelector) + { + m_xScopeSelector->append(IDEResId(RID_STR_OB_SCOPE_ALL), u"ALL_LIBRARIES"_ustr); + m_xScopeSelector->append(IDEResId(RID_STR_OB_SCOPE_CURRENT), u"CURRENT_DOCUMENT"_ustr); + m_xScopeSelector->set_active(0); + m_xScopeSelector->connect_changed(LINK(this, ObjectBrowser, OnScopeChanged)); + } + + if (m_xLeftTreeView) + { + m_xLeftTreeView->connect_selection_changed(LINK(this, ObjectBrowser, OnLeftTreeSelect)); + m_xLeftTreeView->connect_expanding(LINK(this, ObjectBrowser, OnNodeExpand)); + } + if (m_xRightMembersView) + { + m_xRightMembersView->connect_selection_changed( + LINK(this, ObjectBrowser, OnRightTreeSelect)); + } -void ObjectBrowser::Initialize() { m_pDataProvider = std::make_unique<IdeDataProvider>(); } + if (m_xBackButton) + m_xBackButton->set_sensitive(false); + if (m_xForwardButton) + m_xForwardButton->set_sensitive(false); + + if (GetParent() && GetParent()->GetSystemWindow()) + { + GetParent()->GetSystemWindow()->GetTaskPaneList()->AddWindow(this); + } + + m_bUIInitialized = true; + m_eInitState = ObjectBrowserInitState::Initialized; +} void ObjectBrowser::dispose() { + if (m_bDisposed) + { + return; + } + + m_eInitState = ObjectBrowserInitState::Disposed; + + if (GetParent() && GetParent()->GetSystemWindow()) + { + if (auto* pTaskPaneList = GetParent()->GetSystemWindow()->GetTaskPaneList()) + pTaskPaneList->RemoveWindow(this); + } + + // Disconnect all signals + if (m_xScopeSelector) + m_xScopeSelector->connect_changed(Link<weld::ComboBox&, void>()); + if (m_xLeftTreeView) + { + m_xLeftTreeView->connect_selection_changed(Link<weld::TreeView&, void>()); + m_xLeftTreeView->connect_expanding(Link<const weld::TreeIter&, bool>()); + } + if (m_xRightMembersView) + m_xRightMembersView->connect_selection_changed(Link<weld::TreeView&, void>()); + + if (m_pDocNotifier) + { + m_pDocNotifier->dispose(); + m_pDocNotifier.reset(); + } + + if (m_pSearchHandler) + { + m_pSearchHandler.reset(); + } + m_pDataProvider.reset(); + + // Destroy widgets + m_xScopeSelector.reset(); + m_pFilterBox.reset(); + m_xLeftTreeView.reset(); + m_xRightMembersView.reset(); + m_xDetailPane.reset(); + m_xStatusLabel.reset(); + m_xRightPaneHeaderLabel.reset(); + m_xBackButton.reset(); + m_xForwardButton.reset(); + m_xClearSearchButton.reset(); + DockingWindow::dispose(); } +bool ObjectBrowser::Close() +{ + Show(false); + + SfxBindings& rBindings = m_pShell->GetViewFrame().GetBindings(); + rBindings.Invalidate(SID_BASICIDE_OBJECT_BROWSER); + + return false; +} + +void ObjectBrowser::Show(bool bVisible) +{ + DockingWindow::Show(bVisible); + + if (bVisible) + { + if (m_eInitState == ObjectBrowserInitState::NotInitialized) + { + Initialize(); + } + + if (!m_pDataProvider->IsInitialized()) + { + ShowLoadingState(); + m_pDataProvider->AsyncInitialize(LINK(this, ObjectBrowser, OnDataProviderInitialized)); + } + } +} + +void ObjectBrowser::RefreshUI(bool /*bForceKeepUno*/) +{ + if (!m_pDataProvider->IsInitialized()) + { + ShowLoadingState(); + } +} + +void ObjectBrowser::ShowLoadingState() +{ + if (m_xLeftTreeView) + { + m_xLeftTreeView->freeze(); + ClearTreeView(*m_xLeftTreeView, m_aLeftTreeSymbolStore); + m_xLeftTreeView->thaw(); + } +} + +void ObjectBrowser::ClearTreeView(weld::TreeView& rTree, + std::vector<std::shared_ptr<basctl::IdeSymbolInfo>>& rStore) +{ + rTree.clear(); + rStore.clear(); +} + +void ObjectBrowser::onDocumentCreated(const ScriptDocument&) { /* STUB */} +void ObjectBrowser::onDocumentOpened(const ScriptDocument&) { /* STUB */} +void ObjectBrowser::onDocumentSave(const ScriptDocument&) { /* STUB */} +void ObjectBrowser::onDocumentSaveDone(const ScriptDocument&) { /* STUB */} +void ObjectBrowser::onDocumentSaveAs(const ScriptDocument&) { /* STUB */} +void ObjectBrowser::onDocumentSaveAsDone(const ScriptDocument&) { /* STUB */} +void ObjectBrowser::onDocumentClosed(const ScriptDocument&) { /* STUB */} +void ObjectBrowser::onDocumentTitleChanged(const ScriptDocument&) { /* STUB */} +void ObjectBrowser::onDocumentModeChanged(const ScriptDocument&) { /* STUB */} + +IMPL_STATIC_LINK(ObjectBrowser, OnDataProviderInitialized, void*, /*p*/, void) { /* STUB */} +IMPL_STATIC_LINK(ObjectBrowser, OnLeftTreeSelect, weld::TreeView&, /*rTree*/, void) { /* STUB */} +IMPL_STATIC_LINK(ObjectBrowser, OnRightTreeSelect, weld::TreeView&, /*rTree*/, void) { /* STUB */} +IMPL_STATIC_LINK(ObjectBrowser, OnNodeExpand, const weld::TreeIter&, /*rParentIter*/, bool) +{ + return false; +} +IMPL_STATIC_LINK(ObjectBrowser, OnScopeChanged, weld::ComboBox&, /*rComboBox*/, void) { /* STUB */} + } // namespace basctl /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basctl/source/basicide/objectbrowsersearch.cxx b/basctl/source/basicide/objectbrowsersearch.cxx new file mode 100644 index 000000000000..6efb2df034da --- /dev/null +++ b/basctl/source/basicide/objectbrowsersearch.cxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL.2.0/. + */ + +#include <objectbrowser.hxx> +#include <objectbrowsersearch.hxx> +#include <sal/log.hxx> + +namespace basctl +{ +ObjectBrowserSearch::ObjectBrowserSearch(ObjectBrowser& rBrowser) + : m_aDebounceTimer("ObjectBrowserSearchDebounce") + , m_rBrowser(rBrowser) +{ + m_aDebounceTimer.SetInvokeHandler(LINK(this, ObjectBrowserSearch, DebounceTimerHandler)); + m_aDebounceTimer.SetTimeout(350); +} + +ObjectBrowserSearch::~ObjectBrowserSearch() {} + +void ObjectBrowserSearch::Initialize() +{ + SAL_INFO("basctl", "ObjectBrowserSearch::Initialize: Starting initialization"); + + if (m_rBrowser.GetFilterBox()) + { + m_rBrowser.GetFilterBox()->connect_changed( + LINK(this, ObjectBrowserSearch, OnFilterChanged)); + SAL_INFO("basctl", "ObjectBrowserSearch::Initialize: Connected to filter box"); + } + + if (m_rBrowser.GetClearSearchButton()) + { + m_rBrowser.GetClearSearchButton()->connect_clicked( + LINK(this, ObjectBrowserSearch, OnClearSearchClicked)); + SAL_INFO("basctl", "ObjectBrowserSearch::Initialize: Connected to clear button"); + } +} + +IMPL_STATIC_LINK(basctl::ObjectBrowserSearch, OnFilterChanged, weld::Entry&, /*rBox*/, void) +{ + // STUB +} + +IMPL_STATIC_LINK(basctl::ObjectBrowserSearch, OnClearSearchClicked, weld::Button&, /*rButton*/, + void) +{ + // STUB +} + +IMPL_STATIC_LINK(basctl::ObjectBrowserSearch, DebounceTimerHandler, Timer*, /*pTimer*/, void) +{ + // STUB +} + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basctl/source/inc/baside3.hxx b/basctl/source/inc/baside3.hxx index 7e68e2636960..6a805863901f 100644 --- a/basctl/source/inc/baside3.hxx +++ b/basctl/source/inc/baside3.hxx @@ -36,6 +36,7 @@ class DlgEdPage; class DlgEdView; class DialogWindowLayout; +class ObjectBrowser; class ObjectCatalog; bool implImportDialog(weld::Window* pWin, const ScriptDocument& rDocument, const OUString& rLibName); @@ -112,9 +113,12 @@ public: class DialogWindowLayout : public Layout { public: - DialogWindowLayout (vcl::Window* pParent, ObjectCatalog&); + DialogWindowLayout (vcl::Window* pParent, ObjectBrowser&, ObjectCatalog&); virtual ~DialogWindowLayout() override; virtual void dispose() override; + + DialogWindowLayout(const DialogWindowLayout&) = delete; + DialogWindowLayout& operator=(const DialogWindowLayout&) = delete; public: void ShowPropertyBrowser (); void UpdatePropertyBrowser (); @@ -132,7 +136,8 @@ protected: private: // dockable windows: - // object catalog (owned by Shell) + // object browser & catalog (owned by Shell) + ObjectBrowser& rObjectBrowser; ObjectCatalog& rObjectCatalog; // property browser (created by this, deleted by toolkit) VclPtr<PropBrw> pPropertyBrowser; diff --git a/basctl/source/inc/basidesh.hxx b/basctl/source/inc/basidesh.hxx index 6502558f81c5..427d0636d879 100644 --- a/basctl/source/inc/basidesh.hxx +++ b/basctl/source/inc/basidesh.hxx @@ -20,6 +20,7 @@ #include "doceventnotifier.hxx" #include <basctl/sbxitem.hxx> +#include "objectbrowser.hxx" #include "ObjectCatalog.hxx" #include <sfx2/viewsh.hxx> @@ -85,7 +86,8 @@ private: VclPtr<ModulWindowLayout> pModulLayout; VclPtr<DialogWindowLayout> pDialogLayout; VclPtr<Layout> pLayout; // the active layout window - // common object catalog window + // common object browser & catalog window + VclPtr<ObjectBrowser> aObjectBrowser; VclPtr<ObjectCatalog> aObjectCatalog; bool m_bAppBasicModified; @@ -217,6 +219,8 @@ public: virtual css::uno::Reference< css::frame::XModel > GetCurrentDocument() const override; + void UpdateObjectBrowser(); + void UpdateObjectCatalog () { aObjectCatalog->UpdateEntries(); } void RemoveWindow (BaseWindow* pWindow, bool bDestroy, bool bAllowChangeCurWindow = true); diff --git a/basctl/source/inc/idedataprovider.hxx b/basctl/source/inc/idedataprovider.hxx index 21294f2015bc..73d46badf140 100644 --- a/basctl/source/inc/idedataprovider.hxx +++ b/basctl/source/inc/idedataprovider.hxx @@ -9,15 +9,19 @@ #pragma once -#include <memory> #include <basctl/idecodecompletiontypes.hxx> +#include <memory> +#include <tools/link.hxx> + namespace basctl { class IdeDataProviderInterface { public: virtual ~IdeDataProviderInterface() = default; + virtual void AsyncInitialize(const Link<void*, void>& rFinishCallback) = 0; + virtual bool IsInitialized() const = 0; }; class IdeDataProvider : public IdeDataProviderInterface @@ -25,6 +29,11 @@ class IdeDataProvider : public IdeDataProviderInterface public: IdeDataProvider(); ~IdeDataProvider() override; + void AsyncInitialize(const Link<void*, void>& rFinishCallback) override; + bool IsInitialized() const override; + +private: + bool m_bInitialized = false; }; } // namespace basctl diff --git a/basctl/source/inc/objectbrowser.hxx b/basctl/source/inc/objectbrowser.hxx index b5c01e2833e2..d280b395b524 100644 --- a/basctl/source/inc/objectbrowser.hxx +++ b/basctl/source/inc/objectbrowser.hxx @@ -10,28 +10,108 @@ #pragma once #include "bastypes.hxx" +#include "doceventnotifier.hxx" #include "idedataprovider.hxx" #include <basctl/idecodecompletiontypes.hxx> + +#include <atomic> #include <memory> +#include <set> +#include <vector> + +#include <vcl/status.hxx> +#include <vcl/weld.hxx> namespace basctl { class Shell; class IdeDataProviderInterface; +class ObjectBrowserSearch; +class ObjectBrowserNavigation; + +enum class ObjectBrowserInitState +{ + NotInitialized, + Initializing, + Initialized, + Failed, + Disposed +}; -class ObjectBrowser : public basctl::DockingWindow +class ObjectBrowser : public basctl::DockingWindow, public basctl::DocumentEventListener { public: - ObjectBrowser(vcl::Window* pParent); + ObjectBrowser(Shell& rShell, vcl::Window* pParent); ~ObjectBrowser() override; - void Initialize(); - void dispose() override; + virtual void dispose() override; + virtual bool Close() override; + + void Show(bool bVisible = true); + void RefreshUI(bool bForceKeepUno = false); + + void onDocumentCreated(const ScriptDocument& _rDocument) override; + void onDocumentOpened(const ScriptDocument& _rDocument) override; + void onDocumentSave(const ScriptDocument& _rDocument) override; + void onDocumentSaveDone(const ScriptDocument& _rDocument) override; + void onDocumentSaveAs(const ScriptDocument& _rDocument) override; + void onDocumentSaveAsDone(const ScriptDocument& _rDocument) override; + void onDocumentClosed(const ScriptDocument& _rDocument) override; + void onDocumentTitleChanged(const ScriptDocument& _rDocument) override; + void onDocumentModeChanged(const ScriptDocument& _rDocument) override; + + weld::Entry* GetFilterBox() { return m_pFilterBox.get(); } + weld::Button* GetClearSearchButton() { return m_xClearSearchButton.get(); } private: + void Initialize(); + + // Core tree management methods + static void ClearTreeView(weld::TreeView& rTree, + std::vector<std::shared_ptr<basctl::IdeSymbolInfo>>& rStore); + void ShowLoadingState(); + + // Core References + Shell* m_pShell; + // Data Provider std::unique_ptr<IdeDataProviderInterface> m_pDataProvider; + + // State Management + bool m_bDisposed = false; + ObjectBrowserInitState m_eInitState = ObjectBrowserInitState::NotInitialized; + bool m_bUIInitialized = false; + + // UI Widgets + std::unique_ptr<weld::ComboBox> m_xScopeSelector; + std::unique_ptr<weld::Entry> m_pFilterBox; + std::unique_ptr<weld::TreeView> m_xLeftTreeView; + std::unique_ptr<weld::TreeView> m_xRightMembersView; + std::unique_ptr<weld::TextView> m_xDetailPane; + std::unique_ptr<weld::Label> m_xStatusLabel; + std::unique_ptr<weld::Label> m_xRightPaneHeaderLabel; + std::unique_ptr<weld::Button> m_xBackButton; + std::unique_ptr<weld::Button> m_xForwardButton; + std::unique_ptr<weld::Button> m_xClearSearchButton; + + // Data Storage + std::vector<std::shared_ptr<basctl::IdeSymbolInfo>> m_aLeftTreeSymbolStore; + std::vector<std::shared_ptr<basctl::IdeSymbolInfo>> m_aRightTreeSymbolStore; + std::map<OUString, size_t> m_aNextChunk; // For lazy-loading nodes + + // Search Handler + std::unique_ptr<ObjectBrowserSearch> m_pSearchHandler; + + // Event Handling + std::unique_ptr<basctl::DocumentEventNotifier> m_pDocNotifier; + + // Event Handlers + DECL_STATIC_LINK(ObjectBrowser, OnDataProviderInitialized, void*, void); + DECL_STATIC_LINK(ObjectBrowser, OnLeftTreeSelect, weld::TreeView&, void); + DECL_STATIC_LINK(ObjectBrowser, OnRightTreeSelect, weld::TreeView&, void); + DECL_STATIC_LINK(ObjectBrowser, OnNodeExpand, const weld::TreeIter&, bool); + DECL_STATIC_LINK(ObjectBrowser, OnScopeChanged, weld::ComboBox&, void); }; } // namespace basctl diff --git a/basctl/source/inc/objectbrowsersearch.hxx b/basctl/source/inc/objectbrowsersearch.hxx new file mode 100644 index 000000000000..30d1d6d5dc96 --- /dev/null +++ b/basctl/source/inc/objectbrowsersearch.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL.2.0/. + */ + +#pragma once + +#include <vcl/timer.hxx> +#include <vcl/weld.hxx> + +namespace basctl +{ +class ObjectBrowser; + +class ObjectBrowserSearch +{ +public: + explicit ObjectBrowserSearch(ObjectBrowser& rBrowser); + ~ObjectBrowserSearch(); + + void Initialize(); + +private: + // Event handlers for the UI widgets + DECL_STATIC_LINK(ObjectBrowserSearch, OnFilterChanged, weld::Entry&, void); + DECL_STATIC_LINK(ObjectBrowserSearch, OnClearSearchClicked, weld::Button&, void); + DECL_STATIC_LINK(ObjectBrowserSearch, DebounceTimerHandler, Timer*, void); + + Timer m_aDebounceTimer; + ObjectBrowser& m_rBrowser; +}; + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basctl/uiconfig/basicide/menubar/menubar.xml b/basctl/uiconfig/basicide/menubar/menubar.xml index bf41ce562bec..8e2fba9947fc 100644 --- a/basctl/uiconfig/basicide/menubar/menubar.xml +++ b/basctl/uiconfig/basicide/menubar/menubar.xml @@ -70,6 +70,7 @@ <menu:menuseparator/> <menu:menuitem menu:id=".uno:ShowLines"/> <menu:menuitem menu:id=".uno:ShowPropBrowser"/> + <menu:menuitem menu:id=".uno:ObjectBrowser"/> <menu:menuitem menu:id=".uno:ObjectCatalog"/> <menu:menuitem menu:id=".uno:WatchWindow"/> <menu:menuitem menu:id=".uno:StackWindow"/> diff --git a/basctl/uiconfig/basicide/ui/objectbrowser.ui b/basctl/uiconfig/basicide/ui/objectbrowser.ui new file mode 100644 index 000000000000..9ea9c21e5189 --- /dev/null +++ b/basctl/uiconfig/basicide/ui/objectbrowser.ui @@ -0,0 +1,423 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.40.0 --> +<interface domain="basctl"> + <requires lib="gtk+" version="3.20"/><!--actual version="3.24"--> + <object class="GtkTreeStore" id="LeftTreeStore"> + <columns> + <column type="gchararray"/> + <column type="gchararray"/> + <column type="gchararray"/> + <column type="gchararray"/> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkTreeStore" id="RightMembersStore"> + <columns> + <column type="gchararray"/> + <column type="gchararray"/> + <column type="gchararray"/> + <column type="gchararray"/> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkBox" id="ObjectBrowser"> + <property name="name">ObjectBrowser</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <!-- Search Bar Container --> + <child> + <object class="GtkBox" id="SearchBoxContainer"> + <property name="name">SearchBoxContainer</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">horizontal</property> + <property name="spacing">6</property> + <!-- Search Entry --> + <child> + <object class="GtkEntry" id="FilterBox"> + <property name="name">FilterBox</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="hexpand">True</property> + <property name="placeholder-text" translatable="yes" context="objectbrowser|FilterBox">Search objects and members...</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <!-- Clear Button --> + <child> + <object class="GtkButton" id="ClearSearchButton"> + <property name="label" translatable="yes" context="objectbrowser|ClearSearchButton">✕</property> + <property name="name">ClearSearchButton</property> + <property name="visible">False</property> <!-- Initially hidden --> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes" context="objectbrowser|ClearSearchButton">Clear Search</property> + <style> + <class name="flat"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <!-- Controls Row --> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="spacing">6</property> + <!-- Label --> + <child> + <object class="GtkLabel" id="ScopeSelectorLabel"> + <property name="name">ScopeSelectorLabel</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes" context="objectbrowser|ScopeSelectorLabel">Scope:</property> + <accessibility> + <relation type="label-for" target="ScopeSelector"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <!-- ComboBox --> + <child> + <object class="GtkComboBoxText" id="ScopeSelector"> + <property name="name">ScopeSelector</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <accessibility> + <relation type="labelled-by" target="ScopeSelectorLabel"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <!-- Spacer to push buttons to the right --> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <!-- Back Button --> + <child> + <object class="GtkButton" id="BackButton"> + <property name="label" translatable="yes" context="objectbrowser|BackButton">◀</property> + <property name="name">BackButton</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes" context="objectbrowser|BackButtonTip">Back in Navigation History</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <!-- Forward Button --> + <child> + <object class="GtkButton" id="ForwardButton"> + <property name="label" translatable="yes" context="objectbrowser|ForwardButton">▶</property> + <property name="name">ForwardButton</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes" context="objectbrowser|ForwardButtonTip">Forward in Navigation History</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <!-- Main Content Area --> + <child> + <object class="GtkPaned" id="MainVerticalSplitter"> + <property name="name">MainVerticalSplitter</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="vexpand">True</property> + <property name="orientation">vertical</property> + <property name="position">400</property> + <property name="position-set">True</property> + <child> + <object class="GtkPaned" id="MainHorizontalSplitter"> + <property name="name">MainHorizontalSplitter</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="hexpand">True</property> + <property name="position">320</property> + <property name="position-set">True</property> + <child> + <object class="GtkBox" id="LeftPaneContainer"> + <property name="name">LeftPaneContainer</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="vexpand">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="LeftPaneLabel"> + <property name="name">LeftPaneLabel</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes" context="objectbrowser|LeftPaneLabel">Objects</property> + <accessibility> + <relation type="label-for" target="LeftTreeView"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="LeftScroller"> + <property name="name">LeftTreeWindow</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="vexpand">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkTreeView" id="LeftTreeView"> + <property name="name">LeftTreeView</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="model">LeftTreeStore</property> + <property name="headers-visible">False</property> + <child> + <object class="GtkTreeViewColumn" id="LeftTreeColumn"> + <property name="title" translatable="yes" context="ObjectBrowserPanel">Objects</property> + <child> + <object class="GtkCellRendererText" id="LeftTreeCellRenderer"/> + </child> + </object> + </child> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> + </child> + <accessibility> + <relation type="labelled-by" target="LeftPaneLabel"/> + </accessibility> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="resize">True</property> + <property name="shrink">True</property> + </packing> + </child> + <child> + <object class="GtkBox" id="RightPaneContainer"> + <property name="name">RightPaneContainer</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="vexpand">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="RightPaneHeaderLabel"> + <property name="name">RightPaneHeaderLabel</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes" context="objectbrowser|RightPaneHeaderLabel">Members</property> + <accessibility> + <relation type="label-for" target="RightMembersView"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="RightScroller"> + <property name="name">RightMembersWindow</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="vexpand">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkTreeView" id="RightMembersView"> + <property name="name">RightMembersView</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="model">RightMembersStore</property> + <property name="headers-visible">False</property> + <child> + <object class="GtkTreeViewColumn" id="RightTreeColumn"> + <property name="title" translatable="yes" context="ObjectBrowserMembers">Members</property> + <child> + <object class="GtkCellRendererText" id="RightTreeCellRenderer"/> + </child> + </object> + </child> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> + </child> + <accessibility> + <relation type="labelled-by" target="RightPaneHeaderLabel"/> + </accessibility> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="resize">True</property> + <property name="shrink">True</property> + </packing> + </child> + </object> + <packing> + <property name="resize">True</property> + <property name="shrink">False</property> + </packing> + </child> + <child> + <object class="GtkBox" id="DetailPaneContainer"> + <property name="name">DetailPaneContainer</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="vexpand">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="DetailPaneLabel"> + <property name="name">DetailPaneLabel</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes" context="objectbrowser|DetailPaneLabel">Details</property> + <accessibility> + <relation type="label-for" target="DetailPane"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="DetailScroller"> + <property name="height-request">100</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="vexpand">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkTextView" id="DetailPane"> + <property name="name">DetailPane</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="editable">False</property> + <property name="wrap-mode">word</property> + <property name="cursor-visible">False</property> + <accessibility> + <relation type="labelled-by" target="DetailPaneLabel"/> + </accessibility> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="resize">False</property> + <property name="shrink">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <!-- Status Bar --> + <child> + <object class="GtkStatusbar" id="StatusBar"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="spacing">2</property> + <child> + <object class="GtkLabel" id="StatusLabel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes" context="objectbrowser|StatusLabel">Ready</property> + <property name="halign">start</property> + <property name="hexpand">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> +</interface> + diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc index b2364a1001ec..16dfaa129b7e 100644 --- a/include/sfx2/sfxsids.hrc +++ b/include/sfx2/sfxsids.hrc @@ -674,6 +674,7 @@ class SvxZoomItem; #define SID_BASICIDE_STACK TypedWhichId<SfxBoolItem>( SID_BASICIDE_START + 56 ) #define SID_BASICIDE_COLOR_SCHEME_DLG ( SID_BASICIDE_START + 57 ) #define SID_TOGGLE_COMMENT ( SID_BASICIDE_START + 58 ) +#define SID_BASICIDE_OBJECT_BROWSER ( SID_BASICIDE_START + 59 ) #define SID_OPTIONS_TREEDIALOG ( SID_BASICIDE_START + 862) #define SID_OPTIONS_SECURITY ( SID_BASICIDE_START + 863) diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu index 606109cb1549..fe7dc89621ab 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu @@ -1673,6 +1673,11 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 <value>9</value> </prop> </node> + <node oor:name=".uno:ObjectBrowser" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Object ~Browser</value> + </prop> + </node> <node oor:name=".uno:ObjectCatalog" oor:op="replace"> <prop oor:name="Label" oor:type="xs:string"> <value xml:lang="en-US">Object Catalog</value> diff --git a/officecfg/registry/schema/org/openoffice/Office/BasicIDE.xcs b/officecfg/registry/schema/org/openoffice/Office/BasicIDE.xcs index cc783b837046..c1e33e781461 100644 --- a/officecfg/registry/schema/org/openoffice/Office/BasicIDE.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/BasicIDE.xcs @@ -192,6 +192,12 @@ </info> <value>true</value> </prop> + <prop oor:name="ObjectBrowser" oor:type="xs:boolean" oor:nillable="false"> + <info> + <desc>Sets the visibility of the Object Browser window.</desc> + </info> + <value>true</value> + </prop> <prop oor:name="ObjectCatalog" oor:type="xs:boolean" oor:nillable="false"> <info> <desc>Sets the visibility of the Object Catalog window.</desc> diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi index 15238490292e..567b06c2d367 100644 --- a/sfx2/sdi/sfx.sdi +++ b/sfx2/sdi/sfx.sdi @@ -2797,6 +2797,25 @@ SfxVoidItem NewWindow SID_NEWWINDOW ] +SfxVoidItem ObjectBrowser SID_BASICIDE_OBJECT_BROWSER +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = TRUE, + Toggle = FALSE, + Container = TRUE, + RecordAbsolute = FALSE, + RecordPerSet; + Asynchron; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::Macro; +] + + SfxVoidItem ObjectCatalog SID_BASICIDE_OBJCAT () [
