GSoC 25: BASIC IDE - Object Browser Live Data, Architectural Lessons & Future Vision [WEEK 6]
Devansh Varshney
varshney.devansh614 at gmail.com
Fri Jul 4 17:30:24 UTC 2025
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*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/libreoffice/attachments/20250704/c6f8c259/attachment-0001.htm>
-------------- next part --------------
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
More information about the LibreOffice
mailing list