Merge pull request #60170 from ConteZero/context_menu
This commit is contained in:
commit
d9cb39c2e8
3 changed files with 160 additions and 5 deletions
|
@ -94,6 +94,13 @@
|
|||
Returns the vertical offset of the line found at the provided index.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_menu" qualifiers="const">
|
||||
<return type="PopupMenu" />
|
||||
<description>
|
||||
Returns the [PopupMenu] of this [RichTextLabel]. By default, this menu is displayed when right-clicking on the [RichTextLabel].
|
||||
[b]Warning:[/b] This is a required internal node, removing and freeing it may cause a crash. If you wish to hide it or any of its children, use their [member Window.visible] property.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_paragraph_count" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
|
@ -163,6 +170,12 @@
|
|||
Installs a custom effect. [code]effect[/code] should be a valid [RichTextEffect].
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_menu_visible" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns whether the menu is visible. Use this instead of [code]get_menu().visible[/code] to improve performance (so the creation of the menu is avoided).
|
||||
</description>
|
||||
</method>
|
||||
<method name="newline">
|
||||
<return type="void" />
|
||||
<description>
|
||||
|
@ -433,6 +446,9 @@
|
|||
If [code]true[/code], the label uses BBCode formatting.
|
||||
</member>
|
||||
<member name="clip_contents" type="bool" setter="set_clip_contents" getter="is_clipping_contents" overrides="Control" default="true" />
|
||||
<member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled" default="false">
|
||||
If [code]true[/code], a right-click displays the context menu.
|
||||
</member>
|
||||
<member name="custom_effects" type="Array" setter="set_effects" getter="get_effects" default="[]">
|
||||
The currently installed custom effects. This is an array of [RichTextEffect]s.
|
||||
To add a custom effect, it's more convenient to use [method install_effect].
|
||||
|
@ -469,6 +485,9 @@
|
|||
<member name="selection_enabled" type="bool" setter="set_selection_enabled" getter="is_selection_enabled" default="false">
|
||||
If [code]true[/code], the label allows text selection.
|
||||
</member>
|
||||
<member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true">
|
||||
If [code]true[/code], shortcut keys for context menu items are enabled, even if the context menu is disabled.
|
||||
</member>
|
||||
<member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="Control.StructuredTextParser" default="0">
|
||||
Set BiDi algorithm override for the structured text.
|
||||
</member>
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "rich_text_label.h"
|
||||
|
||||
#include "core/input/input_map.h"
|
||||
#include "core/math/math_defs.h"
|
||||
#include "core/os/keyboard.h"
|
||||
#include "core/os/os.h"
|
||||
|
@ -1868,6 +1869,13 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
|
|||
vscroll->set_value(vscroll->get_value() + vscroll->get_page() * b->get_factor() * 0.5 / 8);
|
||||
}
|
||||
}
|
||||
if (b->get_button_index() == MouseButton::RIGHT && context_menu_enabled) {
|
||||
_generate_context_menu();
|
||||
menu->set_position(get_screen_position() + b->get_position());
|
||||
menu->reset_size();
|
||||
menu->popup();
|
||||
grab_focus();
|
||||
}
|
||||
}
|
||||
|
||||
Ref<InputEventPanGesture> pan_gesture = p_event;
|
||||
|
@ -1909,12 +1917,24 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
|
|||
vscroll->set_value(vscroll->get_max());
|
||||
handled = true;
|
||||
}
|
||||
if (k->is_action("ui_text_select_all")) {
|
||||
select_all();
|
||||
handled = true;
|
||||
if (is_shortcut_keys_enabled()) {
|
||||
if (k->is_action("ui_text_select_all")) {
|
||||
select_all();
|
||||
handled = true;
|
||||
}
|
||||
if (k->is_action("ui_copy")) {
|
||||
selection_copy();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
if (k->is_action("ui_copy")) {
|
||||
selection_copy();
|
||||
if (k->is_action("ui_menu", true)) {
|
||||
if (context_menu_enabled) {
|
||||
_generate_context_menu();
|
||||
menu->set_position(get_screen_position());
|
||||
menu->reset_size();
|
||||
menu->popup();
|
||||
menu->grab_focus();
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
|
||||
|
@ -4175,6 +4195,32 @@ String RichTextLabel::_get_line_text(ItemFrame *p_frame, int p_line, Selection p
|
|||
return text;
|
||||
}
|
||||
|
||||
void RichTextLabel::set_context_menu_enabled(bool p_enabled) {
|
||||
context_menu_enabled = p_enabled;
|
||||
}
|
||||
|
||||
bool RichTextLabel::is_context_menu_enabled() const {
|
||||
return context_menu_enabled;
|
||||
}
|
||||
|
||||
void RichTextLabel::set_shortcut_keys_enabled(bool p_enabled) {
|
||||
shortcut_keys_enabled = p_enabled;
|
||||
}
|
||||
|
||||
bool RichTextLabel::is_shortcut_keys_enabled() const {
|
||||
return shortcut_keys_enabled;
|
||||
}
|
||||
|
||||
// Context menu.
|
||||
PopupMenu *RichTextLabel::get_menu() const {
|
||||
const_cast<RichTextLabel *>(this)->_generate_context_menu();
|
||||
return menu;
|
||||
}
|
||||
|
||||
bool RichTextLabel::is_menu_visible() const {
|
||||
return menu && menu->is_visible();
|
||||
}
|
||||
|
||||
String RichTextLabel::get_selected_text() const {
|
||||
if (!selection.active || !selection.enabled) {
|
||||
return "";
|
||||
|
@ -4527,6 +4573,12 @@ void RichTextLabel::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_selection_enabled", "enabled"), &RichTextLabel::set_selection_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_selection_enabled"), &RichTextLabel::is_selection_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enabled"), &RichTextLabel::set_context_menu_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &RichTextLabel::is_context_menu_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enabled"), &RichTextLabel::set_shortcut_keys_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_shortcut_keys_enabled"), &RichTextLabel::is_shortcut_keys_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_deselect_on_focus_loss_enabled", "enable"), &RichTextLabel::set_deselect_on_focus_loss_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_deselect_on_focus_loss_enabled"), &RichTextLabel::is_deselect_on_focus_loss_enabled);
|
||||
|
||||
|
@ -4576,6 +4628,9 @@ void RichTextLabel::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_effects"), &RichTextLabel::get_effects);
|
||||
ClassDB::bind_method(D_METHOD("install_effect", "effect"), &RichTextLabel::install_effect);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_menu"), &RichTextLabel::get_menu);
|
||||
ClassDB::bind_method(D_METHOD("is_menu_visible"), &RichTextLabel::is_menu_visible);
|
||||
|
||||
// Note: set "bbcode_enabled" first, to avoid unnecessary "text" resets.
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode");
|
||||
|
||||
|
@ -4597,6 +4652,9 @@ void RichTextLabel::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
|
||||
|
||||
ADD_GROUP("Locale", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
|
||||
|
@ -4776,6 +4834,59 @@ Size2 RichTextLabel::get_minimum_size() const {
|
|||
return size;
|
||||
}
|
||||
|
||||
// Context menu.
|
||||
void RichTextLabel::_generate_context_menu() {
|
||||
if (!menu) {
|
||||
menu = memnew(PopupMenu);
|
||||
add_child(menu, false, INTERNAL_MODE_FRONT);
|
||||
|
||||
menu->connect("id_pressed", callable_mp(this, &RichTextLabel::_menu_option));
|
||||
}
|
||||
|
||||
// Reorganize context menu.
|
||||
menu->clear();
|
||||
if (selection.enabled) {
|
||||
menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : Key::NONE);
|
||||
menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : Key::NONE);
|
||||
}
|
||||
}
|
||||
|
||||
Key RichTextLabel::_get_menu_action_accelerator(const String &p_action) {
|
||||
const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(p_action);
|
||||
if (!events) {
|
||||
return Key::NONE;
|
||||
}
|
||||
|
||||
// Use first event in the list for the accelerator.
|
||||
const List<Ref<InputEvent>>::Element *first_event = events->front();
|
||||
if (!first_event) {
|
||||
return Key::NONE;
|
||||
}
|
||||
|
||||
const Ref<InputEventKey> event = first_event->get();
|
||||
if (event.is_null()) {
|
||||
return Key::NONE;
|
||||
}
|
||||
|
||||
// Use physical keycode if non-zero
|
||||
if (event->get_physical_keycode() != Key::NONE) {
|
||||
return event->get_physical_keycode_with_modifiers();
|
||||
} else {
|
||||
return event->get_keycode_with_modifiers();
|
||||
}
|
||||
}
|
||||
|
||||
void RichTextLabel::_menu_option(int p_option) {
|
||||
switch (p_option) {
|
||||
case MENU_COPY: {
|
||||
selection_copy();
|
||||
} break;
|
||||
case MENU_SELECT_ALL: {
|
||||
select_all();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void RichTextLabel::_draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item *it_from, Item *it_to, int start, int end, int fbg_flag) {
|
||||
Vector2i fbg_index = Vector2i(end, start);
|
||||
Color last_color = Color(0, 0, 0, 0);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define RICH_TEXT_LABEL_H
|
||||
|
||||
#include "rich_text_effect.h"
|
||||
#include "scene/gui/popup_menu.h"
|
||||
#include "scene/gui/scroll_bar.h"
|
||||
#include "scene/resources/text_paragraph.h"
|
||||
|
||||
|
@ -91,6 +92,11 @@ public:
|
|||
VC_GLYPHS_RTL,
|
||||
};
|
||||
|
||||
enum MenuItems {
|
||||
MENU_COPY,
|
||||
MENU_SELECT_ALL,
|
||||
};
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
@ -420,6 +426,15 @@ private:
|
|||
Selection selection;
|
||||
bool deselect_on_focus_loss_enabled = true;
|
||||
|
||||
bool context_menu_enabled = false;
|
||||
bool shortcut_keys_enabled = true;
|
||||
|
||||
// Context menu.
|
||||
PopupMenu *menu = nullptr;
|
||||
void _generate_context_menu();
|
||||
Key _get_menu_action_accelerator(const String &p_action);
|
||||
void _menu_option(int p_option);
|
||||
|
||||
int visible_characters = -1;
|
||||
float percent_visible = 1.0;
|
||||
VisibleCharactersBehavior visible_chars_behavior = VC_CHARS_BEFORE_SHAPING;
|
||||
|
@ -555,6 +570,12 @@ public:
|
|||
void set_tab_size(int p_spaces);
|
||||
int get_tab_size() const;
|
||||
|
||||
void set_context_menu_enabled(bool p_enabled);
|
||||
bool is_context_menu_enabled() const;
|
||||
|
||||
void set_shortcut_keys_enabled(bool p_enabled);
|
||||
bool is_shortcut_keys_enabled() const;
|
||||
|
||||
void set_fit_content_height(bool p_enabled);
|
||||
bool is_fit_content_height_enabled() const;
|
||||
|
||||
|
@ -590,6 +611,10 @@ public:
|
|||
bool is_deselect_on_focus_loss_enabled() const;
|
||||
void deselect();
|
||||
|
||||
// Context menu.
|
||||
PopupMenu *get_menu() const;
|
||||
bool is_menu_visible() const;
|
||||
|
||||
void parse_bbcode(const String &p_bbcode);
|
||||
void append_text(const String &p_bbcode);
|
||||
|
||||
|
|
Loading…
Reference in a new issue