Size2 PopupMenu::get_minimum_size() const { int vseparation = get_constant("vseparation"); int hseparation = get_constant("hseparation"); Size2 minsize = get_stylebox("panel")->get_minimum_size(); Ref<Font> font = get_font("font"); float max_w = 0; int font_h = font->get_height(); int check_w = get_icon("checked")->get_width(); int accel_max_w = 0; for (int i = 0; i < items.size(); i++) { Size2 size; if (!items[i].icon.is_null()) { Size2 icon_size = items[i].icon->get_size(); size.height = MAX(icon_size.height, font_h); size.width += icon_size.width; size.width += hseparation; } else { size.height = font_h; } size.width += items[i].h_ofs; if (items[i].checkable) { size.width += check_w + hseparation; } String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].xl_text; size.width += font->get_string_size(text).width; if (i > 0) size.height += vseparation; if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { int accel_w = hseparation * 2; accel_w += font->get_string_size(_get_accel_text(i)).width; accel_max_w = MAX(accel_w, accel_max_w); } if (items[i].submenu != "") { size.width += get_icon("submenu")->get_width(); } minsize.height += size.height; max_w = MAX(max_w, size.width); } minsize.width += max_w + accel_max_w; return minsize; }
void PopupMenu::_notification(int p_what) { switch(p_what) { case NOTIFICATION_DRAW: { RID ci = get_canvas_item(); Size2 size=get_size(); Ref<StyleBox> style = get_stylebox("panel"); Ref<StyleBox> hover = get_stylebox("hover"); Ref<Font> font = get_font("font"); Ref<Texture> check = get_icon("checked"); Ref<Texture> uncheck = get_icon("unchecked"); Ref<Texture> submenu= get_icon("submenu"); Ref<StyleBox> separator = get_stylebox("separator"); style->draw( ci, Rect2( Point2(), get_size() ) ); Point2 ofs=style->get_offset(); int vseparation = get_constant("vseparation"); int hseparation = get_constant("hseparation"); Color font_color = get_color("font_color"); Color font_color_disabled = get_color("font_color_disabled"); Color font_color_accel = get_color("font_color_accel"); Color font_color_hover = get_color("font_color_hover"); float font_h=font->get_height(); for (int i=0;i<items.size();i++) { if (i>0) ofs.y+=vseparation; Point2 item_ofs=ofs; float h; Size2 icon_size; if (!items[i].icon.is_null()) { icon_size = items[i].icon->get_size(); h = MAX( icon_size.height, font_h ); } else { h=font_h; } if (i==mouse_over) { hover->draw(ci, Rect2( ofs+Point2(-hseparation,-vseparation), Size2( get_size().width - style->get_minimum_size().width + hseparation*2, h+vseparation*2 ) )); } if (items[i].separator) { int sep_h=separator->get_center_size().height+separator->get_minimum_size().height; separator->draw(ci, Rect2( ofs+Point2(0,Math::floor((h-sep_h)/2.0)), Size2( get_size().width - style->get_minimum_size().width , sep_h ) )); } if (items[i].checkable) { if (items[i].checked) check->draw(ci, item_ofs+Point2(0,Math::floor((h-check->get_height())/2.0))); else uncheck->draw(ci, item_ofs+Point2(0,Math::floor((h-check->get_height())/2.0))); item_ofs.x+=check->get_width()+hseparation; } if (!items[i].icon.is_null()) { items[i].icon->draw( ci, item_ofs+Point2(0,Math::floor((h-icon_size.height)/2.0))); item_ofs.x+=items[i].icon->get_width(); item_ofs.x+=hseparation; } if (items[i].submenu!="") { submenu->draw( ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(),item_ofs.y+Math::floor(h-submenu->get_height())/2)); } item_ofs.y+=font->get_ascent(); if (!items[i].separator) font->draw(ci,item_ofs+Point2(0,Math::floor((h-font_h)/2.0)),items[i].text,items[i].disabled?font_color_disabled:(i==mouse_over?font_color_hover:font_color)); if (items[i].accel) { //accelerator String text = _get_accel_text(items[i].accel); item_ofs.x=size.width-style->get_margin(MARGIN_RIGHT)-font->get_string_size(text).width; font->draw(ci,item_ofs+Point2(0,Math::floor((h-font_h)/2.0)),text,i==mouse_over?font_color_hover:font_color_accel); } items[i]._ofs_cache=ofs.y; ofs.y+=h; } } break; case NOTIFICATION_MOUSE_ENTER: { grab_focus(); } break; case NOTIFICATION_MOUSE_EXIT: { if (mouse_over>=0) { mouse_over=-1; update(); } } break; } }
void PopupMenu::_notification(int p_what) { switch (p_what) { case NOTIFICATION_TRANSLATION_CHANGED: { for (int i = 0; i < items.size(); i++) { items[i].xl_text = tr(items[i].text); } minimum_size_changed(); update(); } break; case NOTIFICATION_DRAW: { RID ci = get_canvas_item(); Size2 size = get_size(); Ref<StyleBox> style = get_stylebox("panel"); Ref<StyleBox> hover = get_stylebox("hover"); Ref<Font> font = get_font("font"); // In Item::checkable_type enum order (less the non-checkable member) Ref<Texture> check[] = { get_icon("checked"), get_icon("radio_checked") }; Ref<Texture> uncheck[] = { get_icon("unchecked"), get_icon("radio_unchecked") }; Ref<Texture> submenu = get_icon("submenu"); Ref<StyleBox> separator = get_stylebox("separator"); style->draw(ci, Rect2(Point2(), get_size())); Point2 ofs = style->get_offset(); int vseparation = get_constant("vseparation"); int hseparation = get_constant("hseparation"); Color font_color = get_color("font_color"); Color font_color_disabled = get_color("font_color_disabled"); Color font_color_accel = get_color("font_color_accel"); Color font_color_hover = get_color("font_color_hover"); float font_h = font->get_height(); for (int i = 0; i < items.size(); i++) { if (i > 0) ofs.y += vseparation; Point2 item_ofs = ofs; float h; Size2 icon_size; item_ofs.x += items[i].h_ofs; if (!items[i].icon.is_null()) { icon_size = items[i].icon->get_size(); h = MAX(icon_size.height, font_h); } else { h = font_h; } if (i == mouse_over) { hover->draw(ci, Rect2(item_ofs + Point2(-hseparation, -vseparation / 2), Size2(get_size().width - style->get_minimum_size().width + hseparation * 2, h + vseparation))); } if (items[i].separator) { int sep_h = separator->get_center_size().height + separator->get_minimum_size().height; separator->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(get_size().width - style->get_minimum_size().width, sep_h))); } if (items[i].checkable_type) { Texture *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr(); icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0))); item_ofs.x += icon->get_width() + hseparation; } if (!items[i].icon.is_null()) { items[i].icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon_size.height) / 2.0))); item_ofs.x += items[i].icon->get_width(); item_ofs.x += hseparation; } if (items[i].submenu != "") { submenu->draw(ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2)); } item_ofs.y += font->get_ascent(); String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].xl_text; if (!items[i].separator) { font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text, items[i].disabled ? font_color_disabled : (i == mouse_over ? font_color_hover : font_color)); } if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { //accelerator String text = _get_accel_text(i); item_ofs.x = size.width - style->get_margin(MARGIN_RIGHT) - font->get_string_size(text).width; font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text, i == mouse_over ? font_color_hover : font_color_accel); } items[i]._ofs_cache = ofs.y; ofs.y += h; } } break; case NOTIFICATION_MOUSE_ENTER: { grab_focus(); } break; case NOTIFICATION_MOUSE_EXIT: { if (mouse_over >= 0 && (items[mouse_over].submenu == "" || submenu_over != -1)) { mouse_over = -1; update(); } } break; case NOTIFICATION_POST_POPUP: { initial_button_mask = Input::get_singleton()->get_mouse_button_mask(); during_grabbed_click = (bool)initial_button_mask; } break; case NOTIFICATION_POPUP_HIDE: { if (mouse_over >= 0) { mouse_over = -1; update(); } } break; } }