Hi everyone, This week was a masterclass in UI architecture and debugging within the VCL framework. The journey took us from a promising but flawed experiment to a foundational success: we now have a stable, working Object Browser UI, populated with live UNO API data for the first time.
This is a major milestone. The browser is no longer a concept; it's a real, functioning tool within the IDE. Gerrit Patch: https://gerrit.libreoffice.org/c/core/+/186822 <https://www.google.com/url?sa=E&q=https%3A%2F%2Fgerrit.libreoffice.org%2Fc%2Fcore%2F%2B%2F186822> Live UI Screenshot: https://bug-attachments.documentfoundation.org/attachment.cgi?id=201567 <https://www.google.com/url?sa=E&q=https%3A%2F%2Fbug-attachments.documentfoundation.org%2Fattachment.cgi%3Fid%3D201567> == The Experiment: The "Shell-Managed" Splitter Architecture == Our journey this week began with crucial feedback from Jonathan Clark on the stability of the Object Browser. His reports of docking issues, crashes, and the dreaded <No Module> error pointed to a deep architectural issue. My initial approach to fix this was to make the Object Browser a global tool managed directly by the basctl::Shell, using a Splitter to manage the layout. The premise was logical, but in practice, it was fighting the VCL framework. The experiment failed. The root cause was a fundamental conflict over layout control. We had two "managers"—the persistent Shell and the transient ModulWindowLayout—trying to control sibling windows. This created a race condition that corrupted the IDE's state. Here is a flowchart of the flawed experiment and what we learned from it: +--------------------------------------------------------------------+| The Flawed Experiment: Competing Layout Managers |+--------------------------------------------------------------------+| || +--------------------------+ || | basctl::Shell | <--- Manager #1 (Persistent) || | (Owns ObjectBrowser) | || +------------+-------------+ || | || (Tries to | (Owns Layout) || position OB) | || v || +------------------+ +-------------------------+ || | ObjectBrowser | | ModulWindowLayout | <--- Manager #2 (Transient)| +------------------+ | (Owns ObjectCatalog) | || ^ +-----------+-------------+ || | | || | (Tries to | (Positions Catalog) || | position Catalog) | || | v || | +-----------------+ || +----------------> | ObjectCatalog | || +-----------------+ || || LEARNING: Having two managers for sibling windows creates a || race condition. We were fighting the framework. This approach || was fundamentally unstable and had to be abandoned. || |+--------------------------------------------------------------------+ The lesson was clear: instead of fighting the framework, we must work with it. I made the strategic decision to *revert the Splitter changes*, go back to a clean state, and pursue a simpler, more robust solution. == The Solution: A Return to First Principles == The new plan was to make the Object Browser a first-class citizen of the ModulWindowLayout, forcing it to follow the exact same lifecycle rules as the stable, time-tested ObjectCatalog. This new architecture has a single, unambiguous line of control, which has resolved all stability, docking, and state corruption issues. +--------------------------------------------------------------------+| The Stable Solution: A Single, Authoritative Layout Manager |+--------------------------------------------------------------------+| || +--------------------------+ || | basctl::Shell | || +------------+-------------+ || | || (Owns) v || +-------------------------+ || | ModulWindowLayout | <--- The ONLY Manager| +------------+------------+ || | || (Manages ALL its children) || | || +-------------------+-------------------+ || | | || v v || +--------------------------------+ +-------------------------+ || | ObjectCatalog | | ObjectBrowser | || +--------------------------------+ +-------------------------+ || || LEARNING: By giving one Layout full ownership and control, the || component lifecycles are synchronized. Docking and other events || are now handled correctly by a single, authoritative system. || |+--------------------------------------------------------------------+ == A Deeper Dive: Q&A on This Week's Architecture == For those who want the technical details, here is the code-validated proof of the new architecture. The patchset is comprehensive, modifying over 20 files across the build system (.mk), UI definitions (.ui, .xml), slot definitions (.hrc, .sdi), and core C++ logic (.hxx, .cxx). *Q1: How can we prove both components are managed by the same layout?* A: The proof is in basctl/source/basicide/baside2.cxx. The method ModulWindowLayout::OnFirstSize() is called once to set up child windows. The diff clearly shows both are added as left-side panels: *// In ModulWindowLayout::OnFirstSize()*void ModulWindowLayout::OnFirstSize(...) { AddToLeft(&rObjectCatalog, ...); AddToLeft(GetShell()->GetObjectBrowser(), ...); // ... } This confirms they are siblings managed by the same engine, which is the key to fixing the docking and stability bugs. *Q2: What are the exact differences in UI management?* A: This is a key architectural choice. While managed by the same layout, their ownership and access patterns differ significantly. ┌───────────┬──────────────────────────────────┬──────────────────────────────────┐ │ *Aspect* │ *Object Catalog (Legacy)* │ *Object Browser (New)* │ ├───────────┼──────────────────────────────────┼──────────────────────────────────┤ │ Ownership │ Owned directly by the │ Owned by `basctl::Shell` as a │ │ │ `ModulWindowLayout`. │ `VclPtr` member. ││ │ │ │ │ Access │ Accessed as a direct member │ Accessed via a getter: │ │ │ reference: `rObjectCatalog`. │ `GetShell()->GetObject-` │ │ │ │ `Browser()`. │ │ │ │ │ │ Coupling │ Tightly Coupled: The layout's │ Loosely Coupled: The layout is │ │ │ constructor requires the catalog.│ a consumer of the Shell's │ │ │ │ service; it doesn't own it. │ └───────────┴──────────────────────────────────┴──────────────────────────────────┘ *Code Proof of Difference:* *Catalog (Tightly Coupled):* basctl/source/inc/baside2.hxx shows the layout requires the catalog in its constructor. *// in ModulWindowLayout class* private: ObjectCatalog& rObjectCatalog; *// Direct member reference* public: ModulWindowLayout (..., ObjectCatalog& rCat, ...); *Browser (Loosely Coupled):* basctl/source/inc/basidesh.hxx shows the Shell owns the browser pointer. *// in Shell class* private: VclPtr<ObjectBrowser> m_pObjectBrowser; *// Shell owns the browser* public: ObjectBrowser* GetObjectBrowser() const; This loosely-coupled design allows us to integrate a major new feature without changing the constructor of a complex, mature class (ModulWindowLayout), which is a safer and more maintainable approach. *Q3: How do we know the live data connection is real?* A: The patch introduces idedataprovider.cxx. Its *GetTopLevelNodes()* function explicitly calls ScriptDocument::getAllScriptDocuments() and sets up the "UNO APIs" root. The objectbrowser.cxx then calls this provider in its *RefreshUI()* and *OnNodeExpand()* methods, proving the clear link between the live UNO runtime and the UI. == Strategic Intel: The Long-Term Vision == This week, Jonathan's guidance ("we have to eventually get rid of the object catalog") helped clarify the project's long-term vision. When combined with the initial prompt from tdf#165785 ("Please note that this is different from: Object catalog"), a clear, two-phase strategy emerges. Think of it like building a new workshop next to an old shed: *Phase 1 (GSoC - Coexistence)*: Build the new "workshop" (Object Browser) and make it live stably alongside the old "shed" (ObjectCatalog). Don't touch the old one, just build the new one right. *Phase 2 (Post-GSoC - Replacement)*: Once the new workshop is fully equipped and can do everything the old shed did (and more), we can demolish the shed. This means our goal for GSoC is not to replace the catalog, but to build a superior tool that can replace it in the future. == The Future: A Proposal for a Better UX? == The lesson from our reverted Splitter experiment was that managing two competing side panels is complex. This makes the proposal for a *unified,tabbed UI* even more compelling. It could be a possible solution for the "coexistence" phase because it solves the layout problem by placing both components in a single container. That is we do not have to select from View *Conceptual UI Mockup for Discussion:* +-------------------------------------------------+| [ Object Catalog ] [ Object Browser ] <--- Tabs |+=================================================|| Left Pane (Content of the selected tab) || +---------------------------------------------+ || | If "Object Catalog" is active, this shows | || | the existing project navigation tree. | || | | || | If "Object Browser" is active, this shows | || | our new, powerful introspection UI. | || +---------------------------------------------+ |+-------------------------------------------------+ *What are the community's thoughts on pursuing this tabbed design as thenext future step. Do we need to do this?* This week was a test of the idea that sometimes you have to build something, see it fail, and understand why it failed to find a truly robust solution. I'm excited to finally move forward on populating the rest of the browser with rich data. *I have also added a txt file in case the diagrams format went off direction.* *Week 1 mail -* https://lists.freedesktop.org/archives/libreoffice/2025-May/093264.html *Week 2 and 3 mail -* https://lists.freedesktop.org/archives/libreoffice/2025-June/093362.html *Week 4 mail(Thread) -* https://lists.freedesktop.org/archives/libreoffice/2025-June/093392.html *Week 5 mail -* https://lists.freedesktop.org/archives/libreoffice/2025-June/093443.html -- *Regards,* *Devansh*
Hi everyone, This week was a masterclass in UI architecture and debugging within the VCL framework. The journey took us from a promising but flawed experiment to a foundational success: we now have a stable, working Object Browser UI, populated with live UNO API data for the first time. This is a major milestone. The browser is no longer a concept; it's a real, functioning tool within the IDE. Gerrit Patch: https://gerrit.libreoffice.org/c/core/+/186822 Live UI Screenshot: https://bug-attachments.documentfoundation.org/attachment.cgi?id=201567 == The Experiment: The "Shell-Managed" Splitter Architecture == Our journey this week began with crucial feedback from Jonathan Clark on the stability of the Object Browser. His reports of docking issues, ghost frames, and the dreaded <No Module> error pointed to a deep architectural issue. My initial approach to fix this was to make the Object Browser a global tool managed directly by the basctl::Shell, using a Splitter to manage the layout. The premise was logical, but in practice, it was fighting the VCL framework. == The Diagnosis: A Conflict of Ownership & The Revert == The experiment failed. The root cause was a fundamental conflict over layout control. We had two "managers"—the persistent Shell and the transient ModulWindowLayout—trying to control sibling windows. This created a race condition that corrupted the IDE's state. Here is a flowchart of the flawed experiment and what we learned from it: +--------------------------------------------------------------------+ | The Flawed Experiment: Competing Layout Managers | +--------------------------------------------------------------------+ | | | +--------------------------+ | | | basctl::Shell | <--- Manager #1 (Persistent) | | | (Owns ObjectBrowser) | | | +------------+-------------+ | | | | | (Tries to | (Owns Layout) | | position OB) | | | v | | +------------------+ +-------------------------+ | | | ObjectBrowser | | ModulWindowLayout | <--- Manager #2 (Transient) | +------------------+ | (Owns ObjectCatalog) | | | ^ +-----------+-------------+ | | | | | | | (Tries to | (Positions Catalog) | | | position Catalog) | | | | v | | | +-----------------+ | | +----------------> | ObjectCatalog | | | +-----------------+ | | | | LEARNING: Having two managers for sibling windows creates a | | race condition. We were fighting the framework. This approach | | was fundamentally unstable and had to be abandoned. | | | +--------------------------------------------------------------------+ The lesson was clear: instead of fighting the framework, we must work with it. I made the strategic decision to revert the Splitter changes, go back to a clean state, and pursue a simpler, more robust solution. == The Solution: A Return to First Principles == The new plan was to make the Object Browser a first-class citizen of the ModulWindowLayout, forcing it to follow the exact same lifecycle rules as the stable, time-tested ObjectCatalog. This new architecture has a single, unambiguous line of control, which has resolved all stability, docking, and state corruption issues. +--------------------------------------------------------------------+ | The Stable Solution: A Single, Authoritative Layout Manager | +--------------------------------------------------------------------+ | | | +--------------------------+ | | | basctl::Shell | | | +------------+-------------+ | | | | | (Owns) v | | +-------------------------+ | | | ModulWindowLayout | <--- The ONLY Manager | +------------+------------+ | | | | | (Manages ALL its children) | | | | | +-------------------+-------------------+ | | | | | | v v | | +--------------------------------+ +-------------------------+ | | | ObjectCatalog | | ObjectBrowser | | | +--------------------------------+ +-------------------------+ | | | | LEARNING: By giving one Layout full ownership and control, the | | component lifecycles are synchronized. Docking and other events | | are now handled correctly by a single, authoritative system. | | | +--------------------------------------------------------------------+ == Breakthrough: The UI is ALIVE! == With the stability issues resolved, and the connected UI to our live data provider. The Object Browser now successfully calls the IdeDataProvider, which uses the theCoreReflection logic from our C++ PoCs to fetch and display the top-level UNO API nodes. == A Deeper Dive: Q&A on This Week's Architecture == For those who want the technical details, here is the code-validated proof of the new architecture. The patchset is comprehensive, modifying over 20 files across the build system (.mk), UI definitions (.ui, .xml), slot definitions (.hrc, .sdi), and core C++ logic (.hxx, .cxx). Q1: How can we prove both components are managed by the same layout? A: The proof is in basctl/source/basicide/baside2.cxx. The method ModulWindowLayout::OnFirstSize() is called once to set up child windows. The diff clearly shows both are added as left-side panels: // In ModulWindowLayout::OnFirstSize() void ModulWindowLayout::OnFirstSize(...) { AddToLeft(&rObjectCatalog, ...); AddToLeft(GetShell()->GetObjectBrowser(), ...); // ... } This confirms they are siblings managed by the same engine, which is the key to fixing the docking and stability bugs. Q2: What are the exact differences in UI management? A: This is a key architectural choice. While managed by the same layout, their ownership and access patterns differ significantly. ┌───────────┬──────────────────────────────────┬──────────────────────────────────┐ │ Aspect │ Object Catalog (Legacy) │ Object Browser (New) │ ├───────────┼──────────────────────────────────┼──────────────────────────────────┤ │ Ownership │ Owned directly by the │ Owned by `basctl::Shell` as a │ │ │ `ModulWindowLayout`. │ `VclPtr` member. │ │ │ │ │ │ Access │ Accessed as a direct member │ Accessed via a getter: │ │ │ reference: `rObjectCatalog`. │ `GetShell()->GetObject-` │ │ │ │ `Browser()`. │ │ │ │ │ │ Coupling │ Tightly Coupled: The layout's │ Loosely Coupled: The layout is │ │ │ constructor requires the catalog.│ a consumer of the Shell's │ │ │ │ service; it doesn't own it. │ └───────────┴──────────────────────────────────┴──────────────────────────────────┘ This loosely-coupled design allows us to integrate a major new feature without changing the constructor of a complex, mature class (ModulWindowLayout), which is a safer and more maintainable approach. Q3: How do we know the live data connection is real? A: The patch introduces idedataprovider.cxx. Its GetTopLevelNodes() function explicitly calls ScriptDocument::getAllScriptDocuments() and sets up the "UNO APIs" root. The objectbrowser.cxx then calls this provider in its RefreshUI() and OnNodeExpand(), proving the clear link between the live UNO runtime and the UI. == Strategic Intel: The Long-Term Vision == This week, Jonathan's guidance ("we have to eventually get rid of the object catalog") helped clarify the project's long-term vision. When combined with the initial prompt from tdf#165785 ("Please note that this is different from: Object catalog"), a clear, two-phase strategy emerges. Think of it like building a new workshop next to an old shed: Phase 1 (GSoC - Coexistence): Build the new "workshop" (Object Browser) and make it live stably alongside the old "shed" (ObjectCatalog). Don't touch the old one, just build the new one right. Phase 2 (Post-GSoC - Replacement): Once the new workshop is fully equipped and can do everything the old shed did (and more), we can demolish the shed? This means our goal for GSoC is not to replace the catalog, but to build a superior tool that can replace it in the future? == The Future: A Proposal for a Better UX? == The lesson from our reverted Splitter experiment was that managing two competing side panels is complex. This makes the proposal for a unified, tabbed UI even more compelling. It could be a possible solution for the "coexistence" phase because it solves the layout problem by placing both components in a single container, meaning we no longer have to select them separately from the "View" menu. Conceptual UI Mockup for Discussion: +-------------------------------------------------+ | [ Object Catalog ] [ Object Browser ] <--- Tabs | +=================================================| | Left Pane (Content of the selected tab) | | +---------------------------------------------+ | | | If "Object Catalog" is active, this shows | | | | the existing project navigation tree. | | | | | | | | If "Object Browser" is active, this shows | | | | our new, powerful introspection UI. | | | +---------------------------------------------+ | +-------------------------------------------------+ What are the community's thoughts on pursuing this tabbed design as the potential solution? Do we need to do this? This week was a testament to the idea that sometimes you have to build something, see it fail, and understand why it failed to find a truly robust solution. I'm excited to finally move forward on populating the rest of the browser with rich data. Week 1 mail - https://lists.freedesktop.org/archives/libreoffice/2025-May/093264.html Week 2 and 3 mail - https://lists.freedesktop.org/archives/libreoffice/2025-June/093362.html Week 4 mail(Thread) - https://lists.freedesktop.org/archives/libreoffice/2025-June/093392.html Week 5 mail - https://lists.freedesktop.org/archives/libreoffice/2025-June/093443.html -- Regards, Devansh