summaryrefslogtreecommitdiff
path: root/scene/gui/popup_menu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/popup_menu.cpp')
-rw-r--r--scene/gui/popup_menu.cpp196
1 files changed, 183 insertions, 13 deletions
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 3329d24890..b3f18bf8fa 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -32,9 +32,16 @@
#include "translation.h"
#include "os/input.h"
-String PopupMenu::_get_accel_text(uint32_t p_accel) const {
+String PopupMenu::_get_accel_text(int p_item) const {
+
+ ERR_FAIL_INDEX_V(p_item,items.size(),String());
+
+ if (items[p_item].shortcut.is_valid())
+ return items[p_item].shortcut->get_as_text();
+ else if (items[p_item].accel)
+ return keycode_get_string(items[p_item].accel);
+ return String();
- return keycode_get_string(p_accel);
/*
String atxt;
if (p_accel&KEY_MASK_SHIFT)
@@ -87,14 +94,15 @@ Size2 PopupMenu::get_minimum_size() const {
size.width+=check_w+hseparation;
}
- size.width+=font->get_string_size(items[i].text).width;
+ String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].text;
+ size.width+=font->get_string_size(text).width;
if (i>0)
size.height+=vseparation;
- if (items[i].accel) {
+ 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(items[i].accel)).width;
+ accel_w+=font->get_string_size(_get_accel_text(i)).width;
accel_max_w = MAX( accel_w, accel_max_w );
}
@@ -484,13 +492,15 @@ void PopupMenu::_notification(int p_what) {
}
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));
+ String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].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) {
+ if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) {
//accelerator
- String text = _get_accel_text(items[i].accel);
+ 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);
@@ -570,6 +580,64 @@ void PopupMenu::add_check_item(const String& p_label,int p_ID,uint32_t p_accel)
update();
}
+
+void PopupMenu::add_icon_shortcut(const Ref<Texture>& p_icon,const Ref<ShortCut>& p_shortcut,int p_ID) {
+
+ ERR_FAIL_COND(p_shortcut.is_null());
+
+ _ref_shortcut(p_shortcut);
+
+ Item item;
+ item.ID=p_ID;
+ item.icon=p_icon;
+ item.shortcut=p_shortcut;
+ items.push_back(item);
+ update();
+
+}
+
+void PopupMenu::add_shortcut(const Ref<ShortCut>& p_shortcut,int p_ID){
+
+ ERR_FAIL_COND(p_shortcut.is_null());
+
+ _ref_shortcut(p_shortcut);
+
+ Item item;
+ item.ID=p_ID;
+ item.shortcut=p_shortcut;
+ items.push_back(item);
+ update();
+
+}
+void PopupMenu::add_icon_check_shortcut(const Ref<Texture>& p_icon,const Ref<ShortCut>& p_shortcut,int p_ID){
+
+ ERR_FAIL_COND(p_shortcut.is_null());
+
+ _ref_shortcut(p_shortcut);
+
+ Item item;
+ item.ID=p_ID;
+ item.shortcut=p_shortcut;
+ item.checkable=true;
+ item.icon=p_icon;
+ items.push_back(item);
+ update();
+}
+
+void PopupMenu::add_check_shortcut(const Ref<ShortCut>& p_shortcut,int p_ID){
+
+ ERR_FAIL_COND(p_shortcut.is_null());
+
+ _ref_shortcut(p_shortcut);
+
+ Item item;
+ item.ID=p_ID;
+ item.shortcut=p_shortcut;
+ item.checkable=true;
+ items.push_back(item);
+ update();
+}
+
void PopupMenu::set_item_text(int p_idx,const String& p_text) {
ERR_FAIL_INDEX(p_idx,items.size());
@@ -701,6 +769,12 @@ String PopupMenu::get_item_tooltip(int p_idx) const {
return items[p_idx].tooltip;
}
+Ref<ShortCut> PopupMenu::get_item_shortcut(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,items.size(),Ref<ShortCut>());
+ return items[p_idx].shortcut;
+}
+
void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
ERR_FAIL_INDEX(p_idx,items.size());
@@ -730,6 +804,21 @@ void PopupMenu::set_item_tooltip(int p_idx,const String& p_tooltip) {
update();
}
+void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut>& p_shortcut) {
+ ERR_FAIL_INDEX(p_idx,items.size());
+ if (items[p_idx].shortcut.is_valid()) {
+ _unref_shortcut(items[p_idx].shortcut);
+ }
+ items[p_idx].shortcut=p_shortcut;
+
+ if (items[p_idx].shortcut.is_valid()) {
+ _ref_shortcut(items[p_idx].shortcut);
+ }
+
+
+ update();
+}
+
bool PopupMenu::is_item_checkable(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,items.size(),false);
return items[p_idx].checkable;
@@ -740,15 +829,55 @@ int PopupMenu::get_item_count() const {
return items.size();
}
-int PopupMenu::find_item_by_accelerator(uint32_t p_accel) const {
+bool PopupMenu::activate_item_by_event(const InputEvent& p_event) {
+
+ uint32_t code=0;
+ if (p_event.type==InputEvent::KEY) {
+ code=p_event.key.scancode;
+ if (code==0)
+ code=p_event.key.unicode;
+ if (p_event.key.mod.control)
+ code|=KEY_MASK_CTRL;
+ if (p_event.key.mod.alt)
+ code|=KEY_MASK_ALT;
+ if (p_event.key.mod.meta)
+ code|=KEY_MASK_META;
+ if (p_event.key.mod.shift)
+ code|=KEY_MASK_SHIFT;
+ }
+
int il=items.size();
for(int i=0;i<il;i++) {
+ if (is_item_disabled(i))
+ continue;
- if (items[i].accel==p_accel)
- return i;
+
+ if (items[i].shortcut.is_valid() && items[i].shortcut->is_shortcut(p_event)) {
+ activate_item(i);
+ return true;
+ }
+
+ if (code!=0 && items[i].accel==code) {
+ activate_item(i);
+ return true;
+ }
+
+ if (items[i].submenu!="") {
+ Node* n = get_node(items[i].submenu);
+ if(!n)
+ continue;
+
+ PopupMenu* pm = n->cast_to<PopupMenu>();
+ if(!pm)
+ continue;
+
+ if(pm->activate_item_by_event(p_event)) {
+ return true;
+ }
+ }
}
- return -1;
+ return false;
}
void PopupMenu::activate_item(int p_item) {
@@ -773,6 +902,12 @@ void PopupMenu::activate_item(int p_item) {
void PopupMenu::remove_item(int p_idx) {
+ ERR_FAIL_INDEX(p_idx,items.size());
+
+ if (items[p_idx].shortcut.is_valid()) {
+ _unref_shortcut(items[p_idx].shortcut);
+ }
+
items.remove(p_idx);
update();
}
@@ -788,6 +923,11 @@ void PopupMenu::add_separator() {
void PopupMenu::clear() {
+ for(int i=0;i<items.size();i++) {
+ if (items[i].shortcut.is_valid()) {
+ _unref_shortcut(items[i].shortcut);
+ }
+ }
items.clear();
mouse_over=-1;
update();
@@ -816,6 +956,27 @@ Array PopupMenu::_get_items() const {
return items;
}
+
+void PopupMenu::_ref_shortcut( Ref<ShortCut> p_sc) {
+
+ if (!shortcut_refcount.has(p_sc)) {
+ shortcut_refcount[p_sc]=1;
+ p_sc->connect("changed",this,"update");
+ } else {
+ shortcut_refcount[p_sc]+=1;
+ }
+}
+
+void PopupMenu::_unref_shortcut(Ref<ShortCut> p_sc) {
+
+ ERR_FAIL_COND(!shortcut_refcount.has(p_sc));
+ shortcut_refcount[p_sc]--;
+ if (shortcut_refcount[p_sc]==0) {
+ p_sc->disconnect("changed",this,"update");
+ shortcut_refcount.erase(p_sc);
+ }
+}
+
void PopupMenu::_set_items(const Array& p_items){
ERR_FAIL_COND(p_items.size() % 10);
@@ -894,12 +1055,20 @@ void PopupMenu::_bind_methods() {
ObjectTypeDB::bind_method(_MD("add_icon_check_item","texture","label","id","accel"),&PopupMenu::add_icon_check_item,DEFVAL(-1),DEFVAL(0));
ObjectTypeDB::bind_method(_MD("add_check_item","label","id","accel"),&PopupMenu::add_check_item,DEFVAL(-1),DEFVAL(0));
ObjectTypeDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_submenu_item,DEFVAL(-1));
+
+ ObjectTypeDB::bind_method(_MD("add_icon_shortcut","texture","shortcut:ShortCut","id"),&PopupMenu::add_icon_shortcut,DEFVAL(-1));
+ ObjectTypeDB::bind_method(_MD("add_shortcut","shortcut:ShortCut","id"),&PopupMenu::add_shortcut,DEFVAL(-1));
+ ObjectTypeDB::bind_method(_MD("add_icon_check_shortcut","texture","shortcut:ShortCut","id"),&PopupMenu::add_icon_check_shortcut,DEFVAL(-1));
+ ObjectTypeDB::bind_method(_MD("add_check_shortcut","shortcut:ShortCut","id"),&PopupMenu::add_check_shortcut,DEFVAL(-1));
+
+
ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&PopupMenu::set_item_text);
ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon);
ObjectTypeDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator);
ObjectTypeDB::bind_method(_MD("set_item_metadata","idx","metadata"),&PopupMenu::set_item_metadata);
ObjectTypeDB::bind_method(_MD("set_item_checked","idx","checked"),&PopupMenu::set_item_checked);
ObjectTypeDB::bind_method(_MD("set_item_disabled","idx","disabled"),&PopupMenu::set_item_disabled);
+ ObjectTypeDB::bind_method(_MD("set_item_shortcut","idx","shortcut:ShortCut"),&PopupMenu::set_item_shortcut);
ObjectTypeDB::bind_method(_MD("set_item_submenu","idx","submenu"),&PopupMenu::set_item_submenu);
ObjectTypeDB::bind_method(_MD("set_item_as_separator","idx","enable"),&PopupMenu::set_item_as_separator);
ObjectTypeDB::bind_method(_MD("set_item_as_checkable","idx","enable"),&PopupMenu::set_item_as_checkable);
@@ -908,6 +1077,7 @@ void PopupMenu::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_item_icon","idx"),&PopupMenu::get_item_icon);
ObjectTypeDB::bind_method(_MD("get_item_metadata","idx"),&PopupMenu::get_item_metadata);
ObjectTypeDB::bind_method(_MD("get_item_accelerator","idx"),&PopupMenu::get_item_accelerator);
+ ObjectTypeDB::bind_method(_MD("get_item_shortcut:ShortCut","idx"),&PopupMenu::get_item_shortcut);
ObjectTypeDB::bind_method(_MD("get_item_submenu","idx"),&PopupMenu::get_item_submenu);
ObjectTypeDB::bind_method(_MD("is_item_separator","idx"),&PopupMenu::is_item_separator);
ObjectTypeDB::bind_method(_MD("is_item_checkable","idx"),&PopupMenu::is_item_checkable);