Exemple #1
0
bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only) {

	uint32_t code = 0;
	Ref<InputEventKey> k = p_event;

	if (k.is_valid()) {
		code = k->get_scancode();
		if (code == 0)
			code = k->get_unicode();
		if (k->get_control())
			code |= KEY_MASK_CTRL;
		if (k->get_alt())
			code |= KEY_MASK_ALT;
		if (k->get_metakey())
			code |= KEY_MASK_META;
		if (k->get_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].shortcut.is_valid() && items[i].shortcut->is_shortcut(p_event) && (items[i].shortcut_is_global || !p_for_global_only)) {
			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, p_for_global_only)) {
				return true;
			}
		}
	}
	return false;
}
Exemple #2
0
void PopupMenu::_input_event(const InputEvent &p_event) {

	switch( p_event.type) {

		case InputEvent::KEY: {


			if (!p_event.key.pressed)
				break;

			switch(p_event.key.scancode) {


				case KEY_DOWN: {


					for(int i=mouse_over+1;i<items.size();i++) {

						if (i<0 || i>=items.size())
							continue;

						if (!items[i].separator && !items[i].disabled) {


							mouse_over=i;
							update();
							break;
						}
					}
				} break;
				case KEY_UP: {


					for(int i=mouse_over-1;i>=0;i--) {

						if (i<0 || i>=items.size())
							continue;


						if (!items[i].separator && !items[i].disabled) {


						   mouse_over=i;
						   update();
						   break;
						}
					}
				} break;
				case KEY_RETURN:
				case KEY_ENTER: {

					if (mouse_over>=0 && mouse_over<items.size() && !items[mouse_over].separator) {


						activate_item(mouse_over);

					}
				} break;
			}





		} break;

		case InputEvent::MOUSE_BUTTON: {
	
			
			const InputEventMouseButton &b=p_event.mouse_button;
			if (b.pressed)
				break;			

			switch(b.button_index) {


				case BUTTON_WHEEL_DOWN: {

					if (get_global_pos().y + get_size().y > get_viewport_rect().size.y) {

						int vseparation = get_constant("vseparation");
						Ref<Font> font = get_font("font");

						Point2 pos = get_pos();
						int s = (vseparation+font->get_height())*3;
						pos.y-=s;
						set_pos(pos);

						//update hover
						InputEvent ie;
						ie.type=InputEvent::MOUSE_MOTION;
						ie.mouse_motion.x=b.x;
						ie.mouse_motion.y=b.y+s;
						_input_event(ie);
					}
				} break;
				case BUTTON_WHEEL_UP: {

					if (get_global_pos().y < 0) {

						int vseparation = get_constant("vseparation");
						Ref<Font> font = get_font("font");

						Point2 pos = get_pos();
						int s = (vseparation+font->get_height())*3;
						pos.y+=s;
						set_pos(pos);

						//update hover
						InputEvent ie;
						ie.type=InputEvent::MOUSE_MOTION;
						ie.mouse_motion.x=b.x;
						ie.mouse_motion.y=b.y-s;
						_input_event(ie);


					}
				} break;
				case BUTTON_LEFT: {

					int over=_get_mouse_over(Point2(b.x,b.y));

					if (invalidated_click) {
						invalidated_click=false;
						break;
					}
					if (over<0) {
						hide();
						break; //non-activable
					}

					if (items[over].separator || items[over].disabled)
						break;

					if (items[over].submenu!="") {

						_activate_submenu(over);
						return;
					}
					activate_item(over);

				} break;
			}
			
			//update();
		} break;
		case InputEvent::MOUSE_MOTION: {
	

			if (invalidated_click) {
				moved+=Vector2(p_event.mouse_motion.relative_x,p_event.mouse_motion.relative_y);
				if (moved.length()>4)
					invalidated_click=false;

			}

			const InputEventMouseMotion &m=p_event.mouse_motion;
			for(List<Rect2>::Element *E=autohide_areas.front();E;E=E->next()) {

				if (!Rect2(Point2(),get_size()).has_point(Point2(m.x,m.y)) && E->get().has_point(Point2(m.x,m.y))) {
					call_deferred("hide");
					return;
				}
			}

			int over=_get_mouse_over(Point2(m.x,m.y));
			int id = (over<0 || items[over].separator || items[over].disabled)?-1:items[over].ID;

			if (id<0) {
				mouse_over=-1;
				update();
				break;
			}

			if (items[over].submenu!="" && submenu_over!=over) {
				submenu_over=over;
				submenu_timer->start();
			}

			if (over!=mouse_over) {
				mouse_over=over;
				update();
			}
		} break;

	}
}
Exemple #3
0
void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {

	Ref<InputEventKey> k = p_event;

	if (k.is_valid()) {

		if (!k->is_pressed())
			return;

		switch (k->get_scancode()) {

			case KEY_DOWN: {

				for (int i = mouse_over + 1; i < items.size(); i++) {

					if (i < 0 || i >= items.size())
						continue;

					if (!items[i].separator && !items[i].disabled) {

						mouse_over = i;
						update();
						break;
					}
				}
			} break;
			case KEY_UP: {

				for (int i = mouse_over - 1; i >= 0; i--) {

					if (i < 0 || i >= items.size())
						continue;

					if (!items[i].separator && !items[i].disabled) {

						mouse_over = i;
						update();
						break;
					}
				}
			} break;
			case KEY_ENTER:
			case KEY_KP_ENTER: {

				if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) {

					activate_item(mouse_over);
				}
			} break;
		}
	}

	Ref<InputEventMouseButton> b = p_event;

	if (b.is_valid()) {

		if (b->is_pressed())
			return;

		switch (b->get_button_index()) {

			case BUTTON_WHEEL_DOWN: {

				if (get_global_position().y + get_size().y > get_viewport_rect().size.y) {

					int vseparation = get_constant("vseparation");
					Ref<Font> font = get_font("font");

					Point2 pos = get_position();
					int s = (vseparation + font->get_height()) * 3;
					pos.y -= (s * b->get_factor());
					set_position(pos);

					//update hover
					Ref<InputEventMouseMotion> ie;
					ie.instance();
					ie->set_position(b->get_position() + Vector2(0, s));
					_gui_input(ie);
				}
			} break;
			case BUTTON_WHEEL_UP: {

				if (get_global_position().y < 0) {

					int vseparation = get_constant("vseparation");
					Ref<Font> font = get_font("font");

					Point2 pos = get_position();
					int s = (vseparation + font->get_height()) * 3;
					pos.y += (s * b->get_factor());
					set_position(pos);

					//update hover
					Ref<InputEventMouseMotion> ie;
					ie.instance();
					ie->set_position(b->get_position() - Vector2(0, s));
					_gui_input(ie);
				}
			} break;
			case BUTTON_LEFT: {

				int over = _get_mouse_over(b->get_position());

				if (invalidated_click) {
					invalidated_click = false;
					break;
				}
				if (over < 0) {
					hide();
					break; //non-activable
				}

				if (items[over].separator || items[over].disabled)
					break;

				if (items[over].submenu != "") {

					_activate_submenu(over);
					return;
				}
				activate_item(over);

			} break;
		}

		//update();
	}

	Ref<InputEventMouseMotion> m = p_event;

	if (m.is_valid()) {

		if (invalidated_click) {
			moved += m->get_relative();
			if (moved.length() > 4)
				invalidated_click = false;
		}

		for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {

			if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) {
				call_deferred("hide");
				return;
			}
		}

		int over = _get_mouse_over(m->get_position());
		int id = (over < 0 || items[over].separator || items[over].disabled) ? -1 : (items[over].ID >= 0 ? items[over].ID : over);

		if (id < 0) {
			mouse_over = -1;
			update();
			return;
		}

		if (items[over].submenu != "" && submenu_over != over) {
			submenu_over = over;
			submenu_timer->start();
		}

		if (over != mouse_over) {
			mouse_over = over;
			update();
		}
	}
}
Exemple #4
0
void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {

	if (p_event->is_action("ui_down") && p_event->is_pressed()) {

		int search_from = mouse_over + 1;
		if (search_from >= items.size())
			search_from = 0;

		for (int i = search_from; i < items.size(); i++) {

			if (i < 0 || i >= items.size())
				continue;

			if (!items[i].separator && !items[i].disabled) {

				mouse_over = i;
				emit_signal("id_focused", i);
				update();
				accept_event();
				break;
			}
		}
	} else if (p_event->is_action("ui_up") && p_event->is_pressed()) {

		int search_from = mouse_over - 1;
		if (search_from < 0)
			search_from = items.size() - 1;

		for (int i = search_from; i >= 0; i--) {

			if (i < 0 || i >= items.size())
				continue;

			if (!items[i].separator && !items[i].disabled) {

				mouse_over = i;
				emit_signal("id_focused", i);
				update();
				accept_event();
				break;
			}
		}
	} else if (p_event->is_action("ui_left") && p_event->is_pressed()) {

		Node *n = get_parent();
		if (n && Object::cast_to<PopupMenu>(n)) {
			hide();
			accept_event();
		}
	} else if (p_event->is_action("ui_right") && p_event->is_pressed()) {

		if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && items[mouse_over].submenu != "" && submenu_over != mouse_over) {
			_activate_submenu(mouse_over);
			accept_event();
		}
	} else if (p_event->is_action("ui_accept") && p_event->is_pressed()) {

		if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) {

			if (items[mouse_over].submenu != "" && submenu_over != mouse_over) {
				_activate_submenu(mouse_over);
			} else {
				activate_item(mouse_over);
			}
			accept_event();
		}
	}

	Ref<InputEventMouseButton> b = p_event;

	if (b.is_valid()) {

		if (b->is_pressed())
			return;

		int button_idx = b->get_button_index();
		switch (button_idx) {

			case BUTTON_WHEEL_DOWN: {

				if (get_global_position().y + get_size().y > get_viewport_rect().size.y) {
					_scroll(-b->get_factor(), b->get_position());
				}
			} break;
			case BUTTON_WHEEL_UP: {

				if (get_global_position().y < 0) {
					_scroll(b->get_factor(), b->get_position());
				}
			} break;
			default: {
				// Allow activating item by releasing the LMB or any that was down when the popup appeared
				if (button_idx == BUTTON_LEFT || (initial_button_mask & (1 << (button_idx - 1)))) {

					bool was_during_grabbed_click = during_grabbed_click;
					during_grabbed_click = false;

					int over = _get_mouse_over(b->get_position());

					if (invalidated_click) {
						invalidated_click = false;
						break;
					}
					if (over < 0) {
						if (!was_during_grabbed_click) {
							hide();
						}
						break; //non-activable
					}

					if (items[over].separator || items[over].disabled)
						break;

					if (items[over].submenu != "") {

						_activate_submenu(over);
						return;
					}
					activate_item(over);
				}
			}
		}

		//update();
	}

	Ref<InputEventMouseMotion> m = p_event;

	if (m.is_valid()) {

		if (invalidated_click) {
			moved += m->get_relative();
			if (moved.length() > 4)
				invalidated_click = false;
		}

		for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {

			if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) {
				call_deferred("hide");
				return;
			}
		}

		int over = _get_mouse_over(m->get_position());
		int id = (over < 0 || items[over].separator || items[over].disabled) ? -1 : (items[over].ID >= 0 ? items[over].ID : over);

		if (id < 0) {
			mouse_over = -1;
			update();
			return;
		}

		if (items[over].submenu != "" && submenu_over != over) {
			submenu_over = over;
			submenu_timer->start();
		}

		if (over != mouse_over) {
			mouse_over = over;
			update();
		}
	}

	Ref<InputEventPanGesture> pan_gesture = p_event;
	if (pan_gesture.is_valid()) {
		if (get_global_position().y + get_size().y > get_viewport_rect().size.y || get_global_position().y < 0) {
			_scroll(-pan_gesture->get_delta().y, pan_gesture->get_position());
		}
	}
}