Quellcode durchsuchen

Make popups from `MenuButton`, `OptionButton`, and submenus obey the layout direction

Michael Alexsander vor 3 Jahren
Ursprung
Commit
8bde86da10
3 geänderte Dateien mit 34 neuen und 8 gelöschten Zeilen
  1. 3 0
      scene/gui/menu_button.cpp
  2. 4 1
      scene/gui/option_button.cpp
  3. 27 7
      scene/gui/popup_menu.cpp

+ 3 - 0
scene/gui/menu_button.cpp

@@ -136,6 +136,9 @@ int MenuButton::get_item_count() const {
 
 void MenuButton::_notification(int p_what) {
 	switch (p_what) {
+		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
+			popup->set_layout_direction((Window::LayoutDirection)get_layout_direction());
+		} break;
 		case NOTIFICATION_VISIBILITY_CHANGED: {
 			if (!is_visible_in_tree()) {
 				popup->hide();

+ 4 - 1
scene/gui/option_button.cpp

@@ -92,7 +92,10 @@ void OptionButton::_notification(int p_what) {
 			arrow->draw(ci, ofs, clr);
 		} break;
 		case NOTIFICATION_TRANSLATION_CHANGED:
-		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
+		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
+			popup->set_layout_direction((Window::LayoutDirection)get_layout_direction());
+			[[fallthrough]];
+		}
 		case NOTIFICATION_THEME_CHANGED: {
 			if (has_theme_icon(SNAME("arrow"))) {
 				if (is_layout_rtl()) {

+ 27 - 7
scene/gui/popup_menu.cpp

@@ -203,15 +203,17 @@ void PopupMenu::_activate_submenu(int p_over) {
 
 	float scroll_offset = control->get_position().y;
 
-	Point2 submenu_pos;
+	submenu_popup->set_as_minsize(); // Shrink the popup size to its contents.
 	Size2 submenu_size = submenu_popup->get_size();
+
+	Point2 submenu_pos;
 	if (control->is_layout_rtl()) {
 		submenu_pos = this_pos + Point2(-submenu_size.width, items[p_over]._ofs_cache + scroll_offset);
 	} else {
 		submenu_pos = this_pos + Point2(this_rect.size.width, items[p_over]._ofs_cache + scroll_offset);
 	}
 
-	// Fix pos if going outside parent rect
+	// Fix pos if going outside parent rect.
 	if (submenu_pos.x < get_parent_rect().position.x) {
 		submenu_pos.x = this_pos.x + submenu_size.width;
 	}
@@ -222,7 +224,6 @@ void PopupMenu::_activate_submenu(int p_over) {
 
 	submenu_popup->set_close_on_parent_focus(false);
 	submenu_popup->set_position(submenu_pos);
-	submenu_popup->set_as_minsize(); // Shrink the popup size to its contents.
 
 	PopupMenu *submenu_pum = Object::cast_to<PopupMenu>(submenu_popup);
 	if (!submenu_pum) {
@@ -642,8 +643,8 @@ void PopupMenu::_draw_items() {
 		if (items[i].separator) {
 			if (!text.is_empty()) {
 				Vector2 text_pos = Point2(separator_ofs, item_ofs.y + Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
-				if (!items[i].icon.is_null()) {
-					text_pos.x = rtl ? text_pos.x - (icon_size.width + hseparation) : text_pos.x + icon_size.width + hseparation;
+				if (!rtl && !items[i].icon.is_null()) {
+					text_pos.x += icon_size.width + hseparation;
 				}
 
 				if (outline_size > 0 && font_outline_color.a > 0) {
@@ -747,13 +748,32 @@ void PopupMenu::_notification(int p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 			PopupMenu *pm = Object::cast_to<PopupMenu>(get_parent());
 			if (pm) {
-				// Inherit submenu's popup delay time from parent menu
+				// Inherit submenu's popup delay time from parent menu.
 				float pm_delay = pm->get_submenu_popup_delay();
 				set_submenu_popup_delay(pm_delay);
 			}
 		} break;
 		case NOTIFICATION_THEME_CHANGED:
-		case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
+		case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
+			// Pass the layout direction to all submenus.
+			for (int i = 0; i < items.size(); i++) {
+				if (items[i].submenu.is_empty()) {
+					continue;
+				}
+
+				Node *n = get_node(items[i].submenu);
+				if (!n) {
+					continue;
+				}
+
+				PopupMenu *pm = Object::cast_to<PopupMenu>(n);
+				if (pm) {
+					pm->set_layout_direction(get_layout_direction());
+				}
+			}
+
+			[[fallthrough]];
+		}
 		case NOTIFICATION_TRANSLATION_CHANGED: {
 			for (int i = 0; i < items.size(); i++) {
 				items.write[i].xl_text = atr(items[i].text);