Skip to content

Add get function for window menu object #7295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

EwingKang
Copy link
Contributor

@EwingKang EwingKang commented Jul 1, 2025

Useful for changing submenu/ items in the menu

  • Provide a get function for window menu object.
  • Provide a get function for menubar in O3DVisualizer

Type

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Motivation and Context

The current implementation doesn't provide means to retrieve submenu/ items. Which makes it impossible to add menu items to the existing O3DVisualizer

Checklist:

  • I have run python util/check_style.py --apply make check-style && make apply-style to apply Open3D code style
    to my code.
  • This PR changes Open3D behavior or adds new functionality.
    • Both C++ (Doxygen) and Python (Sphinx / Google style) documentation is
      updated accordingly.
    • I have added or updated C++ and / or Python unit tests OR included test
      results
      (e.g. screenshots or numbers) here.
  • I will follow up and update the code if CI fails.
  • For fork PRs, I have selected Allow edits from maintainers.

Description

This commit makes it possible to add item to the existing menu in the visualizer.

For example, we can easily add an menu item with proper callback behavior (file loading in this example) like this:

using namespace open3d::visualization
void OnMenuLoadCb(visualizer::O3DVisualizer* window)
{
	LOG_INFO("Menu CB!");

	auto dlg = std::make_shared<gui::FileDialog>(
			gui::FileDialog::Mode::OPEN, "Open File", window->GetTheme());
	dlg->AddFilter(".obj", "OBJ meshes for spray planning (.obj)");
	dlg->AddFilter("", "All files");
	dlg->SetOnCancel([window]() { window->CloseDialog(); });
	dlg->SetOnDone([window](const char *path) {
		window->CloseDialog();
		LOG_INFO("Loading file: " + std::string(path) );
	});
	window->ShowDialog(dlg);
}

int main()
{
	auto o3dvis = std::make_shared<visualizer::O3DVisualizer>( "Visualize", _width, height );
	//...
	o3dvis->GetMenubar()->GetMenu("File")->InsertItem(1, "Load STPF file", 599);
	o3dvis->SetOnMenuItemActivated(599, [o3dvis](){OnMenuLoadCb(o3dvis.get());});
}

With the result:
Screenshot from 2025-07-01 10-44-01


This change is Reviewable

Usefull for changing submenu/ items in the menu

* Provide get function for window menu object.
* Provide get function for menubar in O3DVisualizer
Copy link

update-docs bot commented Jul 1, 2025

Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes.

@ssheorey ssheorey requested review from Copilot and ssheorey July 1, 2025 20:17
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds retrieval functions for the menu bar and submenus, enabling users to query and modify existing menus in O3DVisualizer.

  • Adds GetMenubar to O3DVisualizer for access to the application menubar
  • Introduces GetMenu(name) and GetMenu(item_id) in MenuBase and implements them in Menu and MenuImgui
  • Updates changelog to document the new menu APIs

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
cpp/open3d/visualization/visualizer/O3DVisualizer.h Declares GetMenubar on O3DVisualizer
cpp/open3d/visualization/visualizer/O3DVisualizer.cpp Implements both impl‐ and wrapper versions of GetMenubar
cpp/open3d/visualization/gui/MenuBase.h Adds pure virtual GetMenu overloads
cpp/open3d/visualization/gui/MenuImgui.h & MenuImgui.cpp Declares and defines GetMenu in ImGui‐based menu
cpp/open3d/visualization/gui/Menu.h & Menu.cpp Declares and defines GetMenu in core Menu
CHANGELOG.md Documents the new menu‐retrieval feature
Comments suppressed due to low confidence (4)

cpp/open3d/visualization/visualizer/O3DVisualizer.h:166

  • [nitpick] Consider renaming GetMenubar to GetMenuBar (capital ‘B’) to follow standard camel‐case conventions for multiword identifiers, and mark it as a const method.
    std::shared_ptr<gui::MenuBase> GetMenubar();

cpp/open3d/visualization/visualizer/O3DVisualizer.h:164

  • [nitpick] The doc comment is a bit unclear. You could simplify to: /// Returns a shared_ptr to the application's menubar for this visualizer window.
    /// Get menubar from window system. The window came from

cpp/open3d/visualization/visualizer/O3DVisualizer.h:166

  • There are no existing tests for the new GetMenubar method—consider adding unit tests to verify it returns the correct menubar.
    std::shared_ptr<gui::MenuBase> GetMenubar();

CHANGELOG.md:63

  • [nitpick] Changelog mentions GetMenu on MenuBase but omits the new GetMenubar API—consider updating to include both additions.
-   Add `GetMenu` for MenuBase for easy menu item/submenu control. (PR #7295)

@@ -1400,6 +1400,10 @@ Ctrl-alt-click to polygon select)";
scene_->ForceRedraw();
}

std::shared_ptr<MenuBase> GetMenubar() {
Copy link
Preview

Copilot AI Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qualify MenuBase with its namespace (e.g., gui::MenuBase) to avoid ambiguity and match the header declaration.

Suggested change
std::shared_ptr<MenuBase> GetMenubar() {
std::shared_ptr<gui::MenuBase> GetMenubar() {

Copilot uses AI. Check for mistakes.

Copy link
Contributor Author

@EwingKang EwingKang Jul 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to do it, however, the same file L:45 already have a similar case without gui:: namespace. I followed the convention. Which is better?
https://github.com/EwingKang/Open3D/blob/menu_get_fun/cpp/open3d/visualization/gui/MenuBase.h#L47

@@ -2427,6 +2431,10 @@ void O3DVisualizer::ModifyGeometryMaterial(
impl_->ModifyGeometryMaterial(name, material);
}

std::shared_ptr<MenuBase> O3DVisualizer::GetMenubar() {
Copy link
Preview

Copilot AI Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be marked const since it does not modify object state: std::shared_ptr<gui::MenuBase> O3DVisualizer::GetMenubar() const {

Copilot uses AI. Check for mistakes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm baffled. Does the modification of the smart-pointer-pointed count as mutation to the object? I'm open to both ways.

Personally, after reading https://isocpp.org/wiki/faq/const-correctness#logical-vs-physical-const and some stackoverflow articles, I would say that this member should NOT be marked as const. Since the const label hints the programmer that no part of this object will be changed. This would not be intuitive since the purpose of the get function is for the user to modify the content. For example the sample code provided in the original PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be more specific, almost all discussion I read have the following syntax:

int *GetPointerToMember() { return &member; }
const int *GetPointerToMember() const { return &member; }

Usually there are always two versions of the get function. Should I straight up provide two versions of the get function?
@ssheorey I hate to bother you with this trivial question, but it would be nice if you can give some pointers.

Comment on lines +53 to +56
virtual std::shared_ptr<MenuBase> GetMenu(const char* name) = 0;

/// Get the Menu by ItemId. Returns nullptr if not found.
virtual std::shared_ptr<MenuBase> GetMenu(ItemId item_id) = 0;
Copy link
Preview

Copilot AI Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both GetMenu overloads should be marked const, e.g., virtual std::shared_ptr<MenuBase> GetMenu(const char* name) const = 0;, to reflect that they do not modify the menu.

Suggested change
virtual std::shared_ptr<MenuBase> GetMenu(const char* name) = 0;
/// Get the Menu by ItemId. Returns nullptr if not found.
virtual std::shared_ptr<MenuBase> GetMenu(ItemId item_id) = 0;
virtual std::shared_ptr<MenuBase> GetMenu(const char* name) const = 0;
/// Get the Menu by ItemId. Returns nullptr if not found.
virtual std::shared_ptr<MenuBase> GetMenu(ItemId item_id) const = 0;

Copilot uses AI. Check for mistakes.

@@ -35,6 +35,9 @@ class MenuImgui : public MenuBase {

int GetNumberOfItems() const override;

std::shared_ptr<MenuBase> GetMenu(const char* name) override;
Copy link
Preview

Copilot AI Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a const qualifier to this override: std::shared_ptr<MenuBase> GetMenu(const char* name) const override;

Suggested change
std::shared_ptr<MenuBase> GetMenu(const char* name) override;
std::shared_ptr<MenuBase> GetMenu(const char* name) const override;

Copilot uses AI. Check for mistakes.

@@ -45,6 +45,12 @@ class Menu : public MenuBase {

int GetNumberOfItems() const override;

/// Get the Menu by name. Returns nullptr if not found.
std::shared_ptr<MenuBase> GetMenu(const char* name) override;
Copy link
Preview

Copilot AI Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, mark this override as const: std::shared_ptr<MenuBase> GetMenu(const char* name) const override;

Suggested change
std::shared_ptr<MenuBase> GetMenu(const char* name) override;
std::shared_ptr<MenuBase> GetMenu(const char* name) const override;

Copilot uses AI. Check for mistakes.

@EwingKang
Copy link
Contributor Author

EwingKang commented Jul 2, 2025

Copilot suggests that I should use GetMenuBar instead of GetMenubar. How funny it is that this is actually my original naming. The reason I eventually changed it to GetMenubar is because there is already an existing example in https://github.com/EwingKang/Open3D/blob/menu_get_fun/cpp/open3d/visualization/gui/Application.h#L85, we have

std::shared_ptr<Menu> GetMenubar() const;
void SetMenubar(std::shared_ptr<Menu> menubar);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant