Skip to content

Latest commit

 

History

History
822 lines (507 loc) · 69.8 KB

class_control.rst

File metadata and controls

822 lines (507 loc) · 69.8 KB

Control

Inherits: :ref:`CanvasItem<class_canvasitem>` < :ref:`Node<class_node>` < :ref:`Object<class_object>`

Inherited By: :ref:`TextureRect<class_texturerect>`, :ref:`ColorRect<class_colorrect>`, :ref:`Label<class_label>`, :ref:`Tabs<class_tabs>`, :ref:`GraphEdit<class_graphedit>`, :ref:`VideoPlayer<class_videoplayer>`, :ref:`NinePatchRect<class_ninepatchrect>`, :ref:`LineEdit<class_lineedit>`, :ref:`Container<class_container>`, :ref:`TextEdit<class_textedit>`, :ref:`BaseButton<class_basebutton>`, :ref:`Popup<class_popup>`, :ref:`Tree<class_tree>`, :ref:`Separator<class_separator>`, :ref:`ReferenceRect<class_referencerect>`, :ref:`Panel<class_panel>`, :ref:`TabContainer<class_tabcontainer>`, :ref:`Range<class_range>`, :ref:`RichTextLabel<class_richtextlabel>`, :ref:`ItemList<class_itemlist>`

Category: Core

Brief Description

All User Interface nodes inherit from Control. Features anchors and margins to adapt its position and size to its parent.

Member Functions

:ref:`Vector2<class_vector2>` :ref:`_get_minimum_size<class_Control__get_minimum_size>` ( ) virtual
void :ref:`_gui_input<class_Control__gui_input>` ( :ref:`InputEvent<class_inputevent>` event ) virtual
void :ref:`accept_event<class_Control_accept_event>` ( )
void :ref:`add_color_override<class_Control_add_color_override>` ( :ref:`String<class_string>` name, :ref:`Color<class_color>` color )
void :ref:`add_constant_override<class_Control_add_constant_override>` ( :ref:`String<class_string>` name, :ref:`int<class_int>` constant )
void :ref:`add_font_override<class_Control_add_font_override>` ( :ref:`String<class_string>` name, :ref:`Font<class_font>` font )
void :ref:`add_icon_override<class_Control_add_icon_override>` ( :ref:`String<class_string>` name, :ref:`Texture<class_texture>` texture )
void :ref:`add_shader_override<class_Control_add_shader_override>` ( :ref:`String<class_string>` name, :ref:`Shader<class_shader>` shader )
void :ref:`add_stylebox_override<class_Control_add_stylebox_override>` ( :ref:`String<class_string>` name, :ref:`StyleBox<class_stylebox>` stylebox )
:ref:`bool<class_bool>` :ref:`can_drop_data<class_Control_can_drop_data>` ( :ref:`Vector2<class_vector2>` position, :ref:`Variant<class_variant>` data ) virtual
void :ref:`drop_data<class_Control_drop_data>` ( :ref:`Vector2<class_vector2>` position, :ref:`Variant<class_variant>` data ) virtual
void :ref:`force_drag<class_Control_force_drag>` ( :ref:`Variant<class_variant>` data, :ref:`Control<class_control>` preview )
:ref:`Vector2<class_vector2>` :ref:`get_begin<class_Control_get_begin>` ( ) const
:ref:`Color<class_color>` :ref:`get_color<class_Control_get_color>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`Vector2<class_vector2>` :ref:`get_combined_minimum_size<class_Control_get_combined_minimum_size>` ( ) const
:ref:`int<class_int>` :ref:`get_constant<class_Control_get_constant>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`int<class_int>` :ref:`get_cursor_shape<class_Control_get_cursor_shape>` ( :ref:`Vector2<class_vector2>` position=Vector2( 0, 0 ) ) const
:ref:`Object<class_object>` :ref:`get_drag_data<class_Control_get_drag_data>` ( :ref:`Vector2<class_vector2>` position ) virtual
:ref:`Vector2<class_vector2>` :ref:`get_end<class_Control_get_end>` ( ) const
:ref:`Control<class_control>` :ref:`get_focus_owner<class_Control_get_focus_owner>` ( ) const
:ref:`Font<class_font>` :ref:`get_font<class_Control_get_font>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`Rect2<class_rect2>` :ref:`get_global_rect<class_Control_get_global_rect>` ( ) const
:ref:`Texture<class_texture>` :ref:`get_icon<class_Control_get_icon>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`Vector2<class_vector2>` :ref:`get_minimum_size<class_Control_get_minimum_size>` ( ) const
:ref:`Vector2<class_vector2>` :ref:`get_parent_area_size<class_Control_get_parent_area_size>` ( ) const
:ref:`Control<class_control>` :ref:`get_parent_control<class_Control_get_parent_control>` ( ) const
:ref:`Rect2<class_rect2>` :ref:`get_rect<class_Control_get_rect>` ( ) const
:ref:`float<class_float>` :ref:`get_rotation<class_Control_get_rotation>` ( ) const
:ref:`StyleBox<class_stylebox>` :ref:`get_stylebox<class_Control_get_stylebox>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`String<class_string>` :ref:`get_tooltip<class_Control_get_tooltip>` ( :ref:`Vector2<class_vector2>` at_position=Vector2( 0, 0 ) ) const
void :ref:`grab_click_focus<class_Control_grab_click_focus>` ( )
void :ref:`grab_focus<class_Control_grab_focus>` ( )
:ref:`bool<class_bool>` :ref:`has_color<class_Control_has_color>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`bool<class_bool>` :ref:`has_color_override<class_Control_has_color_override>` ( :ref:`String<class_string>` name ) const
:ref:`bool<class_bool>` :ref:`has_constant<class_Control_has_constant>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`bool<class_bool>` :ref:`has_constant_override<class_Control_has_constant_override>` ( :ref:`String<class_string>` name ) const
:ref:`bool<class_bool>` :ref:`has_focus<class_Control_has_focus>` ( ) const
:ref:`bool<class_bool>` :ref:`has_font<class_Control_has_font>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`bool<class_bool>` :ref:`has_font_override<class_Control_has_font_override>` ( :ref:`String<class_string>` name ) const
:ref:`bool<class_bool>` :ref:`has_icon<class_Control_has_icon>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`bool<class_bool>` :ref:`has_icon_override<class_Control_has_icon_override>` ( :ref:`String<class_string>` name ) const
:ref:`bool<class_bool>` :ref:`has_point<class_Control_has_point>` ( :ref:`Vector2<class_vector2>` point ) virtual
:ref:`bool<class_bool>` :ref:`has_shader_override<class_Control_has_shader_override>` ( :ref:`String<class_string>` name ) const
:ref:`bool<class_bool>` :ref:`has_stylebox<class_Control_has_stylebox>` ( :ref:`String<class_string>` name, :ref:`String<class_string>` type="" ) const
:ref:`bool<class_bool>` :ref:`has_stylebox_override<class_Control_has_stylebox_override>` ( :ref:`String<class_string>` name ) const
void :ref:`minimum_size_changed<class_Control_minimum_size_changed>` ( )
void :ref:`release_focus<class_Control_release_focus>` ( )
void :ref:`set_anchor<class_Control_set_anchor>` ( :ref:`int<class_int>` margin, :ref:`float<class_float>` anchor, :ref:`bool<class_bool>` keep_margin=false, :ref:`bool<class_bool>` push_opposite_anchor=true )
void :ref:`set_anchor_and_margin<class_Control_set_anchor_and_margin>` ( :ref:`int<class_int>` margin, :ref:`float<class_float>` anchor, :ref:`float<class_float>` offset, :ref:`bool<class_bool>` push_opposite_anchor=false )
void :ref:`set_anchors_and_margins_preset<class_Control_set_anchors_and_margins_preset>` ( :ref:`int<class_int>` preset, :ref:`int<class_int>` resize_mode=0, :ref:`int<class_int>` margin=0 )
void :ref:`set_anchors_preset<class_Control_set_anchors_preset>` ( :ref:`int<class_int>` preset, :ref:`bool<class_bool>` keep_margin=false )
void :ref:`set_begin<class_Control_set_begin>` ( :ref:`Vector2<class_vector2>` position )
void :ref:`set_drag_forwarding<class_Control_set_drag_forwarding>` ( :ref:`Control<class_control>` target )
void :ref:`set_drag_preview<class_Control_set_drag_preview>` ( :ref:`Control<class_control>` control )
void :ref:`set_end<class_Control_set_end>` ( :ref:`Vector2<class_vector2>` position )
void :ref:`set_margins_preset<class_Control_set_margins_preset>` ( :ref:`int<class_int>` preset, :ref:`int<class_int>` resize_mode=0, :ref:`int<class_int>` margin=0 )
void :ref:`set_rotation<class_Control_set_rotation>` ( :ref:`float<class_float>` radians )
void :ref:`show_modal<class_Control_show_modal>` ( :ref:`bool<class_bool>` exclusive=false )
void :ref:`warp_mouse<class_Control_warp_mouse>` ( :ref:`Vector2<class_vector2>` to_position )

Signals

  • focus_entered ( )

Emitted when the node gains keyboard focus.

  • focus_exited ( )

Emitted when the node loses keyboard focus.

Emitted when the node receives an :ref:`InputEvent<class_inputevent>`.

  • minimum_size_changed ( )

Emitted when the node's minimum size changes.

  • modal_closed ( )

Emitted when a modal Control is closed. See :ref:`show_modal<class_Control_show_modal>`.

  • mouse_entered ( )

Emitted when the mouse enters the control's Rect area, provided its :ref:`mouse_filter<class_Control_mouse_filter>` lets the event reach it.

  • mouse_exited ( )

Emitted when the mouse leaves the control's Rect area, provided its :ref:`mouse_filter<class_Control_mouse_filter>` lets the event reach it.

  • resized ( )

Emitted when the control changes size.

  • size_flags_changed ( )

Emitted when one of the size flags changes. See :ref:`size_flags_horizontal<class_Control_size_flags_horizontal>` and :ref:`size_flags_vertical<class_Control_size_flags_vertical>`.

Member Variables

  • :ref:`float<class_float>` anchor_bottom - Anchors the bottom edge of the node to the origin, the center, or the end of its parent container. It changes how the bottom margin updates when the node moves or changes size. Use one of the ANCHOR_* constants. Default value: ANCHOR_BEGIN.
  • :ref:`float<class_float>` anchor_left - Anchors the left edge of the node to the origin, the center or the end of its parent container. It changes how the left margin updates when the node moves or changes size. Use one of the ANCHOR_* constants. Default value: ANCHOR_BEGIN.
  • :ref:`float<class_float>` anchor_right - Anchors the right edge of the node to the origin, the center or the end of its parent container. It changes how the right margin updates when the node moves or changes size. Use one of the ANCHOR_* constants. Default value: ANCHOR_BEGIN.
  • :ref:`float<class_float>` anchor_top - Anchors the top edge of the node to the origin, the center or the end of its parent container. It changes how the top margin updates when the node moves or changes size. Use one of the ANCHOR_* constants. Default value: ANCHOR_BEGIN.
  • :ref:`FocusMode<enum_control_focusmode>` focus_mode - The focus access mode for the control (None, Click or All). Only one Control can be focused at the same time, and it will receive keyboard signals.
  • :ref:`NodePath<class_nodepath>` focus_neighbour_bottom - Tells Godot which node it should give keyboard focus to if the user presses Tab, the down arrow on the keyboard, or down on a gamepad. The node must be a Control. If this property is not set, Godot will give focus to the closest Control to the bottom of this one.

If the user presses Tab, Godot will give focus to the closest node to the right first, then to the bottom. If the user presses Shift+Tab, Godot will look to the left of the node, then above it.

Margins are often controlled by one or multiple parent :ref:`Container<class_container>` nodes. Margins update automatically when you move or resize the node.

Numeric Constants

  • NOTIFICATION_RESIZED = 40 --- Sent when the node changes size. Use :ref:`rect_size<class_Control_rect_size>` to get the new size.
  • NOTIFICATION_MOUSE_ENTER = 41 --- Sent when the mouse pointer enters the node's Rect area.
  • NOTIFICATION_MOUSE_EXIT = 42 --- Sent when the mouse pointer exits the node's Rect area.
  • NOTIFICATION_FOCUS_ENTER = 43 --- Sent when the node grabs focus.
  • NOTIFICATION_FOCUS_EXIT = 44 --- Sent when the node loses focus.
  • NOTIFICATION_THEME_CHANGED = 45 --- Sent when the node's :ref:`theme<class_Control_theme>` changes, right before Godot redraws the Control. Happens when you call one of the add_*_override
  • NOTIFICATION_MODAL_CLOSE = 46 --- Sent when an open modal dialog closes. See :ref:`show_modal<class_Control_show_modal>`.

Enums

enum SizeFlags

enum CursorShape

  • CURSOR_ARROW = 0 --- Show the system's arrow mouse cursor when the user hovers the node. Use with :ref:`set_default_cursor_shape<class_Control_set_default_cursor_shape>`.
  • CURSOR_IBEAM = 1 --- Show the system's I-beam mouse cursor when the user hovers the node. The I-beam pointer has a shape similar to "I". It tells the user they can highlight or insert text.
  • CURSOR_POINTING_HAND = 2 --- Show the system's pointing hand mouse cursor when the user hovers the node.
  • CURSOR_CROSS = 3 --- Show the system's cross mouse cursor when the user hovers the node.
  • CURSOR_WAIT = 4 --- Show the system's wait mouse cursor, often an hourglass, when the user hovers the node.
  • CURSOR_BUSY = 5 --- Show the system's busy mouse cursor when the user hovers the node. Often an hourglass.
  • CURSOR_DRAG = 6 --- Show the system's drag mouse cursor, often a closed fist or a cross symbol, when the user hovers the node. It tells the user they're currently dragging an item, like a node in the Scene dock.
  • CURSOR_CAN_DROP = 7 --- Show the system's drop mouse cursor when the user hovers the node. It can be an open hand. It tells the user they can drop an item they're currently grabbing, like a node in the Scene dock.
  • CURSOR_FORBIDDEN = 8 --- Show the system's forbidden mouse cursor when the user hovers the node. Often a crossed circle.
  • CURSOR_VSIZE = 9 --- Show the system's vertical resize mouse cursor when the user hovers the node. A double headed vertical arrow. It tells the user they can resize the window or the panel vertically.
  • CURSOR_HSIZE = 10 --- Show the system's horizontal resize mouse cursor when the user hovers the node. A double headed horizontal arrow. It tells the user they can resize the window or the panel horizontally.
  • CURSOR_BDIAGSIZE = 11 --- Show the system's window resize mouse cursor when the user hovers the node. The cursor is a double headed arrow that goes from the bottom left to the top right. It tells the user they can resize the window or the panel both horizontally and vertically.
  • CURSOR_FDIAGSIZE = 12 --- Show the system's window resize mouse cursor when the user hovers the node. The cursor is a double headed arrow that goes from the top left to the bottom right, the opposite of CURSOR_BDIAGSIZE. It tells the user they can resize the window or the panel both horizontally and vertically.
  • CURSOR_MOVE = 13 --- Show the system's move mouse cursor when the user hovers the node. It shows 2 double-headed arrows at a 90 degree angle. It tells the user they can move a UI element freely.
  • CURSOR_VSPLIT = 14 --- Show the system's vertical split mouse cursor when the user hovers the node. On Windows, it's the same as CURSOR_VSIZE.
  • CURSOR_HSPLIT = 15 --- Show the system's horizontal split mouse cursor when the user hovers the node. On Windows, it's the same as CURSOR_HSIZE.
  • CURSOR_HELP = 16 --- Show the system's help mouse cursor when the user hovers the node, a question mark.

enum FocusMode

enum GrowDirection

  • GROW_DIRECTION_BEGIN = 0
  • GROW_DIRECTION_END = 1

enum LayoutPresetMode

  • PRESET_MODE_MINSIZE = 0
  • PRESET_MODE_KEEP_WIDTH = 1
  • PRESET_MODE_KEEP_HEIGHT = 2
  • PRESET_MODE_KEEP_SIZE = 3

enum LayoutPreset

enum MouseFilter

  • MOUSE_FILTER_STOP = 0 --- The control will receive mouse button input events through :ref:`_gui_input<class_Control__gui_input>` if clicked on. These events are automatically marked as handled and they will not propagate further to other controls.
  • MOUSE_FILTER_PASS = 1 --- The control will receive mouse button input events through :ref:`_gui_input<class_Control__gui_input>` if clicked on. If this control does not handle the event, the parent control (if any) will be considered for a mouse click, and so on until there is no more parent control to potentially handle it. Even if no control handled it at all, the event will still be handled automatically.
  • MOUSE_FILTER_IGNORE = 2 --- The control will not receive mouse button input events through :ref:`_gui_input<class_Control__gui_input>` and will not block other controls from receiving these events. These events will also not be handled automatically.

enum Anchor

Description

Base class for all User Interface or UI related nodes. Control features a bounding rectangle that defines its extents, an anchor position relative to its parent and margins that represent an offset to the anchor. The margins update automatically when the node, any of its parents, or the screen size change.

For more information on Godot's UI system, anchors, margins, and containers, see the related tutorials in the manual. To build flexible UIs, you'll need a mix of UI elements that inherit from Control and :ref:`Container<class_container>` nodes.

User Interface nodes and input

Godot sends input events to the scene's root node first, by calling :ref:`Node._input<class_Node__input>`. :ref:`Node._input<class_Node__input>` forwards the event down the node tree to the nodes under the mouse cursor, or on keyboard focus. To do so, it calls :ref:`MainLoop._input_event<class_MainLoop__input_event>`. Call :ref:`accept_event<class_Control_accept_event>` so no other node receives the event. Once you accepted an input, it becomes handled so :ref:`Node._unhandled_input<class_Node__unhandled_input>` will not process it.

Only one Control node can be in keyboard focus. Only the node in focus will receive keyboard events. To get the focus, call :ref:`grab_focus<class_Control_grab_focus>`. Control nodes lose focus when another node grabs it, or if you hide the node in focus.

Set :ref:`mouse_filter<class_Control_mouse_filter>` to MOUSE_FILTER_IGNORE to tell a Control node to ignore mouse or touch events. You'll need it if you place an icon on top of a button.

:ref:`Theme<class_theme>` resources change the Control's appearance. If you change the :ref:`Theme<class_theme>` on a Control node, it affects all of its children. To override some of the theme's parameters, call one of the add_*_override methods, like :ref:`add_font_override<class_Control_add_font_override>`. You can override the theme with the inspector.

Member Function Description

Returns the minimum size this Control can shrink to. The node can never be smaller than this minimum size.

The node's parent forwards input events to this method. Use it to process and accept inputs on UI elements. See :ref:`accept_event<class_Control_accept_event>`.

Replaces Godot 2's _input_event.

  • void accept_event ( )

Marks an input event as handled. Once you accept an input event, it stops propagating, even to nodes listening to :ref:`Node._unhandled_input<class_Node__unhandled_input>` or :ref:`Node._unhandled_key_input<class_Node__unhandled_key_input>`.

Overrides the color in the theme resource the node uses.

Overrides an integer constant in the :ref:`Theme<class_theme>` resource the node uses. If the constant is invalid, Godot clears the override. See :ref:`Theme.INVALID_CONSTANT<class_Theme_INVALID_CONSTANT>` for more information.

Overrides the name font in the theme resource the node uses. If font is empty, Godot clears the override.

Overrides the name icon in the theme resource the node uses. If icon is empty, Godot clears the override.

Overrides the name shader in the theme resource the node uses. If shader is empty, Godot clears the override.

Overrides the name Stylebox in the theme resource the node uses. If stylebox is empty, Godot clears the override.

Godot calls this method to test if data from a control's :ref:`get_drag_data<class_Control_get_drag_data>` can be dropped at position. position is local to this control.

This method should only be used to test the data. Process the data in :ref:`drop_data<class_Control_drop_data>`.

extends Control

func can_drop_data(position, data):
    # check position if it is relevant to you
    # otherwise just check data
    return typeof(data) == TYPE_DICTIONARY and data.has('expected')

Godot calls this method to pass you the data from a control's :ref:`get_drag_data<class_Control_get_drag_data>` result. Godot first calls :ref:`can_drop_data<class_Control_can_drop_data>` to test if data is allowed to drop at position where position is local to this control.

extends ColorRect

func can_drop_data(position, data):
    return typeof(data) == TYPE_DICTIONARY and data.has('color')

func drop_data(position, data):
    color = data['color']

Forces drag and bypasses :ref:`get_drag_data<class_Control_get_drag_data>` and :ref:`set_drag_preview<class_Control_set_drag_preview>` by passing data and preview. Drag will start even if the mouse is neither over nor pressed on this control.

The methods :ref:`can_drop_data<class_Control_can_drop_data>` and :ref:`drop_data<class_Control_drop_data>` must be implemented on controls that want to receive drop data.

Returns the mouse cursor shape the control displays on mouse hover, one of the CURSOR_* constants.

Godot calls this method to get data that can be dragged and dropped onto controls that expect drop data. Return null if there is no data to drag. Controls that want to receive drop data should implement :ref:`can_drop_data<class_Control_can_drop_data>` and :ref:`drop_data<class_Control_drop_data>`. position is local to this control. Drag may be forced with :ref:`force_drag<class_Control_force_drag>`.

A preview that will follow the mouse that should represent the data can be set with :ref:`set_drag_preview<class_Control_set_drag_preview>`. A good time to set the preview is in this method.

extends Control

func get_drag_data(position):
    var mydata = make_data()
    set_drag_preview(make_preview(mydata))
    return mydata

Returns MARGIN_LEFT and MARGIN_TOP at the same time. This is a helper (see :ref:`set_margin<class_Control_set_margin>`).

Return which control is owning the keyboard focus, or null if no one.

Return position and size of the Control, relative to the top-left corner of the window Control. This is a helper (see :ref:`get_global_position<class_Control_get_global_position>`, :ref:`get_size<class_Control_get_size>`).

Return the minimum size this Control can shrink to. A control will never be displayed or resized smaller than its minimum size.

Return position and size of the Control, relative to the top-left corner of the parent Control. This is a helper (see :ref:`get_position<class_Control_get_position>`, :ref:`get_size<class_Control_get_size>`).

Return the rotation (in radians)

Return the tooltip, which will appear when the cursor is resting over this control.

  • void grab_click_focus ( )
  • void grab_focus ( )

Steal the focus from another control and become the focused control (see :ref:`set_focus_mode<class_Control_set_focus_mode>`).

Return whether the Control is the current focused control (see :ref:`set_focus_mode<class_Control_set_focus_mode>`).

  • void minimum_size_changed ( )
  • void release_focus ( )

Give up the focus, no other control will be able to receive keyboard input.

Sets MARGIN_LEFT and MARGIN_TOP at the same time. This is a helper (see :ref:`set_margin<class_Control_set_margin>`).

Forwards the handling of this control's drag and drop to target control.

Forwarding can be implemented in the target control similar to the methods :ref:`get_drag_data<class_Control_get_drag_data>`, :ref:`can_drop_data<class_Control_can_drop_data>`, and :ref:`drop_data<class_Control_drop_data>` but with two differences:

  1. The function name must be suffixed with _fw
  2. The function must take an extra argument that is the control doing the forwarding
# ThisControl.gd
extends Control
func _ready():
    set_drag_forwarding(target_control)

# TargetControl.gd
extends Control
func can_drop_data_fw(position, data, from_control):
    return true

func drop_data_fw(position, data, from_control):
    my_handle_data(data)

func get_drag_data_fw(position, from_control):
    set_drag_preview(my_preview)
    return my_data()

Shows the given control at the mouse pointer. A good time to call this method is in :ref:`get_drag_data<class_Control_get_drag_data>`.

Sets MARGIN_RIGHT and MARGIN_BOTTOM at the same time. This is a helper (see :ref:`set_margin<class_Control_set_margin>`).

Set the rotation (in radians).

Display a Control as modal. Control must be a subwindow. Modal controls capture the input signals until closed or the area outside them is accessed. When a modal control loses focus, or the ESC key is pressed, they automatically hide. Modal controls are used extensively for popup dialogs and menus.