@@ -148,7 +148,24 @@ void MenuItem::SetLabel(const std::optional<std::string>& label) {
148148 pimpl_->title_ = label;
149149 if (pimpl_->gtk_menu_item_ && pimpl_->type_ != MenuItemType::Separator) {
150150 const char * labelStr = label.has_value () ? label->c_str () : " " ;
151- gtk_menu_item_set_label (GTK_MENU_ITEM (pimpl_->gtk_menu_item_ ), labelStr);
151+
152+ // Check if we have a custom box layout (with icon)
153+ GtkWidget* child = gtk_bin_get_child (GTK_BIN (pimpl_->gtk_menu_item_ ));
154+ if (child && GTK_IS_BOX (child)) {
155+ // Custom layout with icon - find the label widget and update it
156+ GList* children = gtk_container_get_children (GTK_CONTAINER (child));
157+ for (GList* iter = children; iter != nullptr ; iter = iter->next ) {
158+ GtkWidget* widget = GTK_WIDGET (iter->data );
159+ if (GTK_IS_LABEL (widget)) {
160+ gtk_label_set_text (GTK_LABEL (widget), labelStr);
161+ break ;
162+ }
163+ }
164+ g_list_free (children);
165+ } else {
166+ // Simple label-only layout
167+ gtk_menu_item_set_label (GTK_MENU_ITEM (pimpl_->gtk_menu_item_ ), labelStr);
168+ }
152169 }
153170}
154171
@@ -158,7 +175,63 @@ std::optional<std::string> MenuItem::GetLabel() const {
158175
159176void MenuItem::SetIcon (std::shared_ptr<Image> image) {
160177 pimpl_->image_ = image;
161- // TODO: Implement icon setting for GTK menu item
178+
179+ if (!pimpl_->gtk_menu_item_ || pimpl_->type_ == MenuItemType::Separator) {
180+ return ;
181+ }
182+
183+ // Get current label text to preserve it
184+ const char * label_text = gtk_menu_item_get_label (GTK_MENU_ITEM (pimpl_->gtk_menu_item_ ));
185+ std::string current_label = label_text ? label_text : " " ;
186+
187+ // Remove existing child widget
188+ GtkWidget* existing_child = gtk_bin_get_child (GTK_BIN (pimpl_->gtk_menu_item_ ));
189+ if (existing_child) {
190+ gtk_container_remove (GTK_CONTAINER (pimpl_->gtk_menu_item_ ), existing_child);
191+ }
192+
193+ if (image && image->GetNativeObject ()) {
194+ // Create a horizontal box to hold icon and label
195+ GtkWidget* box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6 ); // 6px spacing
196+
197+ // Get the GdkPixbuf from the image
198+ GdkPixbuf* pixbuf = static_cast <GdkPixbuf*>(image->GetNativeObject ());
199+
200+ // Scale the icon to a reasonable menu size (16x16 is standard for menu items)
201+ const int icon_size = 16 ;
202+ GdkPixbuf* scaled_pixbuf = nullptr ;
203+
204+ int original_width = gdk_pixbuf_get_width (pixbuf);
205+ int original_height = gdk_pixbuf_get_height (pixbuf);
206+
207+ if (original_width != icon_size || original_height != icon_size) {
208+ scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf, icon_size, icon_size, GDK_INTERP_BILINEAR);
209+ } else {
210+ scaled_pixbuf = gdk_pixbuf_copy (pixbuf);
211+ }
212+
213+ // Create GtkImage from the pixbuf
214+ GtkWidget* gtk_image = gtk_image_new_from_pixbuf (scaled_pixbuf);
215+ g_object_unref (scaled_pixbuf); // GtkImage takes its own reference
216+
217+ // Create label widget
218+ GtkWidget* label = gtk_label_new (current_label.c_str ());
219+ gtk_label_set_xalign (GTK_LABEL (label), 0.0 ); // Left-align the label
220+
221+ // Pack icon and label into box
222+ gtk_box_pack_start (GTK_BOX (box), gtk_image, FALSE , FALSE , 0 );
223+ gtk_box_pack_start (GTK_BOX (box), label, TRUE , TRUE , 0 );
224+
225+ // Add box to menu item
226+ gtk_container_add (GTK_CONTAINER (pimpl_->gtk_menu_item_ ), box);
227+ gtk_widget_show_all (box);
228+ } else {
229+ // No icon - restore simple label display
230+ GtkWidget* label = gtk_label_new (current_label.c_str ());
231+ gtk_label_set_xalign (GTK_LABEL (label), 0.0 );
232+ gtk_container_add (GTK_CONTAINER (pimpl_->gtk_menu_item_ ), label);
233+ gtk_widget_show (label);
234+ }
162235}
163236
164237std::shared_ptr<Image> MenuItem::GetIcon () const {
0 commit comments