2014-02-10 09:10:30 +08:00
/*************************************************************************/
/* popup.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
2017-01-02 05:01:57 +08:00
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
2014-02-10 09:10:30 +08:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
# include "popup.h"
# include "os/keyboard.h"
2017-01-09 03:28:12 +08:00
void Popup : : _gui_input ( InputEvent p_event ) {
2016-03-09 07:00:52 +08:00
2014-02-10 09:10:30 +08:00
}
void Popup : : _notification ( int p_what ) {
2016-03-09 07:00:52 +08:00
2014-05-05 09:50:23 +08:00
if ( p_what = = NOTIFICATION_VISIBILITY_CHANGED ) {
2017-01-13 21:45:50 +08:00
if ( popped_up & & ! is_visible_in_tree ( ) ) {
2014-05-05 09:50:23 +08:00
popped_up = false ;
notification ( NOTIFICATION_POPUP_HIDE ) ;
emit_signal ( " popup_hide " ) ;
}
2016-05-18 05:27:15 +08:00
update_configuration_warning ( ) ;
2014-05-05 09:50:23 +08:00
}
2015-12-29 20:26:17 +08:00
if ( p_what = = NOTIFICATION_ENTER_TREE ) {
//small helper to make editing of these easier in editor
2015-12-29 23:14:02 +08:00
# ifdef TOOLS_ENABLED
2015-12-29 20:26:17 +08:00
if ( get_tree ( ) - > is_editor_hint ( ) & & get_tree ( ) - > get_edited_scene_root ( ) & & get_tree ( ) - > get_edited_scene_root ( ) - > is_a_parent_of ( this ) ) {
set_as_toplevel ( false ) ;
}
2015-12-29 23:14:02 +08:00
# endif
2015-12-29 20:26:17 +08:00
}
2014-02-10 09:10:30 +08:00
}
void Popup : : _fix_size ( ) {
2016-03-09 07:00:52 +08:00
2015-01-04 10:27:11 +08:00
#if 0
2014-02-10 09:10:30 +08:00
Point2 pos = get_pos ( ) ;
2016-03-09 07:00:52 +08:00
Size2 size = get_size ( ) ;
2014-02-10 09:10:30 +08:00
Point2 window_size = window = = this ? get_parent_area_size ( ) : window - > get_size ( ) ;
2015-01-04 10:27:11 +08:00
# else
Point2 pos = get_global_pos ( ) ;
Size2 size = get_size ( ) ;
Point2 window_size = get_viewport_rect ( ) . size ;
2014-02-10 09:10:30 +08:00
2015-01-04 10:27:11 +08:00
# endif
2014-02-10 09:10:30 +08:00
if ( pos . x + size . width > window_size . width )
pos . x = window_size . width - size . width ;
if ( pos . x < 0 )
pos . x = 0 ;
2016-03-09 07:00:52 +08:00
2014-02-10 09:10:30 +08:00
if ( pos . y + size . height > window_size . height )
pos . y = window_size . height - size . height ;
if ( pos . y < 0 )
pos . y = 0 ;
2015-01-04 10:27:11 +08:00
#if 0
2014-02-10 09:10:30 +08:00
if ( pos ! = get_pos ( ) )
set_pos ( pos ) ;
2015-01-04 10:27:11 +08:00
# else
if ( pos ! = get_pos ( ) )
set_global_pos ( pos ) ;
# endif
2014-02-10 09:10:30 +08:00
}
2015-06-14 09:12:53 +08:00
void Popup : : set_as_minsize ( ) {
Size2 total_minsize ;
for ( int i = 0 ; i < get_child_count ( ) ; i + + ) {
Control * c = get_child ( i ) - > cast_to < Control > ( ) ;
if ( ! c )
continue ;
2017-01-13 21:45:50 +08:00
if ( ! c - > is_visible ( ) )
2015-06-14 09:12:53 +08:00
continue ;
Size2 minsize = c - > get_combined_minimum_size ( ) ;
for ( int j = 0 ; j < 2 ; j + + ) {
Margin m_beg = Margin ( 0 + j ) ;
Margin m_end = Margin ( 2 + j ) ;
float margin_begin = c - > get_margin ( m_beg ) ;
float margin_end = c - > get_margin ( m_end ) ;
AnchorType anchor_begin = c - > get_anchor ( m_beg ) ;
AnchorType anchor_end = c - > get_anchor ( m_end ) ;
if ( anchor_begin = = ANCHOR_BEGIN )
minsize [ j ] + = margin_begin ;
if ( anchor_end = = ANCHOR_END )
minsize [ j ] + = margin_end ;
}
total_minsize . width = MAX ( total_minsize . width , minsize . width ) ;
total_minsize . height = MAX ( total_minsize . height , minsize . height ) ;
}
set_size ( total_minsize ) ;
}
2014-02-10 09:10:30 +08:00
void Popup : : popup_centered_minsize ( const Size2 & p_minsize ) {
Size2 total_minsize = p_minsize ;
for ( int i = 0 ; i < get_child_count ( ) ; i + + ) {
Control * c = get_child ( i ) - > cast_to < Control > ( ) ;
if ( ! c )
continue ;
2017-01-13 21:45:50 +08:00
if ( ! c - > is_visible ( ) )
2015-02-14 23:09:52 +08:00
continue ;
2014-02-10 09:10:30 +08:00
Size2 minsize = c - > get_combined_minimum_size ( ) ;
for ( int j = 0 ; j < 2 ; j + + ) {
Margin m_beg = Margin ( 0 + j ) ;
Margin m_end = Margin ( 2 + j ) ;
float margin_begin = c - > get_margin ( m_beg ) ;
float margin_end = c - > get_margin ( m_end ) ;
AnchorType anchor_begin = c - > get_anchor ( m_beg ) ;
AnchorType anchor_end = c - > get_anchor ( m_end ) ;
if ( anchor_begin = = ANCHOR_BEGIN )
minsize [ j ] + = margin_begin ;
if ( anchor_end = = ANCHOR_END )
minsize [ j ] + = margin_end ;
}
total_minsize . width = MAX ( total_minsize . width , minsize . width ) ;
total_minsize . height = MAX ( total_minsize . height , minsize . height ) ;
}
popup_centered ( total_minsize ) ;
2014-05-05 09:50:23 +08:00
popped_up = true ;
2014-02-10 09:10:30 +08:00
}
void Popup : : popup_centered ( const Size2 & p_size ) {
2016-03-09 07:00:52 +08:00
2016-01-17 09:41:10 +08:00
Point2 window_size = get_viewport_rect ( ) . size ;
2014-02-10 09:10:30 +08:00
emit_signal ( " about_to_show " ) ;
Rect2 rect ;
rect . size = p_size = = Size2 ( ) ? get_size ( ) : p_size ;
2016-01-17 09:41:10 +08:00
2014-02-10 09:10:30 +08:00
rect . pos = ( ( window_size - rect . size ) / 2.0 ) . floor ( ) ;
set_pos ( rect . pos ) ;
set_size ( rect . size ) ;
show_modal ( exclusive ) ;
_fix_size ( ) ;
Control * focusable = find_next_valid_focus ( ) ;
if ( focusable )
focusable - > grab_focus ( ) ;
_post_popup ( ) ;
notification ( NOTIFICATION_POST_POPUP ) ;
2014-05-05 09:50:23 +08:00
popped_up = true ;
2014-02-10 09:10:30 +08:00
}
void Popup : : popup_centered_ratio ( float p_screen_ratio ) {
2016-03-09 07:00:52 +08:00
2014-02-10 09:10:30 +08:00
emit_signal ( " about_to_show " ) ;
Rect2 rect ;
2016-01-17 09:41:10 +08:00
Point2 window_size = get_viewport_rect ( ) . size ;
2014-02-10 09:10:30 +08:00
rect . size = ( window_size * p_screen_ratio ) . floor ( ) ;
rect . pos = ( ( window_size - rect . size ) / 2.0 ) . floor ( ) ;
set_pos ( rect . pos ) ;
set_size ( rect . size ) ;
2016-03-09 07:00:52 +08:00
2014-02-10 09:10:30 +08:00
show_modal ( exclusive ) ;
_fix_size ( ) ;
Control * focusable = find_next_valid_focus ( ) ;
if ( focusable )
focusable - > grab_focus ( ) ;
_post_popup ( ) ;
notification ( NOTIFICATION_POST_POPUP ) ;
2014-05-05 09:50:23 +08:00
popped_up = true ;
2014-02-10 09:10:30 +08:00
}
void Popup : : popup ( ) {
emit_signal ( " about_to_show " ) ;
show_modal ( exclusive ) ;
_fix_size ( ) ;
Control * focusable = find_next_valid_focus ( ) ;
if ( focusable )
focusable - > grab_focus ( ) ;
_post_popup ( ) ;
notification ( NOTIFICATION_POST_POPUP ) ;
2014-05-05 09:50:23 +08:00
popped_up = true ;
2014-02-10 09:10:30 +08:00
}
void Popup : : set_exclusive ( bool p_exclusive ) {
exclusive = p_exclusive ;
}
bool Popup : : is_exclusive ( ) const {
return exclusive ;
}
void Popup : : _bind_methods ( ) {
2017-02-13 19:47:24 +08:00
ClassDB : : bind_method ( D_METHOD ( " popup_centered " , " size " ) , & Popup : : popup_centered , DEFVAL ( Size2 ( ) ) ) ;
ClassDB : : bind_method ( D_METHOD ( " popup_centered_ratio " , " ratio " ) , & Popup : : popup_centered_ratio , DEFVAL ( 0.75 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " popup_centered_minsize " , " minsize " ) , & Popup : : popup_centered_minsize , DEFVAL ( Size2 ( ) ) ) ;
ClassDB : : bind_method ( D_METHOD ( " popup " ) , & Popup : : popup ) ;
ClassDB : : bind_method ( D_METHOD ( " set_exclusive " , " enable " ) , & Popup : : set_exclusive ) ;
ClassDB : : bind_method ( D_METHOD ( " is_exclusive " ) , & Popup : : is_exclusive ) ;
2014-02-10 09:10:30 +08:00
ADD_SIGNAL ( MethodInfo ( " about_to_show " ) ) ;
2014-05-05 09:50:23 +08:00
ADD_SIGNAL ( MethodInfo ( " popup_hide " ) ) ;
2017-01-04 12:16:14 +08:00
ADD_GROUP ( " Popup " , " popup_ " ) ;
2017-02-12 08:11:37 +08:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " popup_exclusive " ) , " set_exclusive " , " is_exclusive " ) ;
2014-02-10 09:10:30 +08:00
BIND_CONSTANT ( NOTIFICATION_POST_POPUP ) ;
2014-05-05 09:50:23 +08:00
BIND_CONSTANT ( NOTIFICATION_POPUP_HIDE ) ;
2014-02-10 09:10:30 +08:00
}
Popup : : Popup ( ) {
set_as_toplevel ( true ) ;
exclusive = false ;
2014-05-05 09:50:23 +08:00
popped_up = false ;
2014-02-10 09:10:30 +08:00
hide ( ) ;
}
2016-05-18 05:27:15 +08:00
String Popup : : get_configuration_warning ( ) const {
2017-01-13 21:45:50 +08:00
if ( is_visible_in_tree ( ) ) {
2016-05-18 05:27:15 +08:00
return TTR ( " Popups will hide by default unless you call popup() or any of the popup * ( ) functions . Making them visible for editing is fine though , but they will hide upon running . " ) ;
}
return String ( ) ;
}
2014-02-10 09:10:30 +08:00
Popup : : ~ Popup ( )
{
}
void PopupPanel : : set_child_rect ( Control * p_child ) {
ERR_FAIL_NULL ( p_child ) ;
Ref < StyleBox > p = get_stylebox ( " panel " ) ;
p_child - > set_area_as_parent_rect ( ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
p_child - > set_margin ( Margin ( i ) , p - > get_margin ( Margin ( i ) ) ) ;
}
}
void PopupPanel : : _notification ( int p_what ) {
if ( p_what = = NOTIFICATION_DRAW ) {
get_stylebox ( " panel " ) - > draw ( get_canvas_item ( ) , Rect2 ( Point2 ( ) , get_size ( ) ) ) ;
}
}
PopupPanel : : PopupPanel ( ) {
}