diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
commit | 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch) | |
tree | 276c4d099e178eb67fbd14f61d77b05e3808e9e3 /scene/gui/scroll_container.cpp | |
parent | 0e49da1687bc8192ed210947da52c9e5c5f301bb (diff) |
GODOT IS OPEN SOURCE
Diffstat (limited to 'scene/gui/scroll_container.cpp')
-rw-r--r-- | scene/gui/scroll_container.cpp | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp new file mode 100644 index 0000000000..817833083e --- /dev/null +++ b/scene/gui/scroll_container.cpp @@ -0,0 +1,427 @@ +/*************************************************************************/ +/* scroll_container.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 "scroll_container.h" +#include "os/os.h" +bool ScrollContainer::clips_input() const { + + return true; +} + +Size2 ScrollContainer::get_minimum_size() const { + + return Size2(1, 1); +}; + + +void ScrollContainer::_cancel_drag() { + set_fixed_process(false); + drag_touching_deaccel=false; + drag_touching=false; + drag_speed=Vector2(); + drag_accum=Vector2(); + last_drag_accum=Vector2(); + drag_from=Vector2(); +} + +void ScrollContainer::_input_event(const InputEvent& p_input_event) { + + + switch(p_input_event.type) { + + case InputEvent::MOUSE_BUTTON: { + + const InputEventMouseButton &mb=p_input_event.mouse_button; + + if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed && v_scroll->is_visible()) { + + v_scroll->set_val( v_scroll->get_val()-v_scroll->get_page()/8 ); + } + + if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed && v_scroll->is_visible()) { + + v_scroll->set_val( v_scroll->get_val()+v_scroll->get_page()/8 ); + } + + if(!OS::get_singleton()->has_touchscreen_ui_hint()) + return; + + if (mb.button_index!=BUTTON_LEFT) + break; + + if (mb.pressed) { + + if (drag_touching) { + set_fixed_process(false); + drag_touching_deaccel=false; + drag_touching=false; + drag_speed=Vector2(); + drag_accum=Vector2(); + last_drag_accum=Vector2(); + drag_from=Vector2(); + } + + if (true) { + drag_speed=Vector2(); + drag_accum=Vector2(); + last_drag_accum=Vector2(); + drag_from=Vector2(h_scroll->get_val(),v_scroll->get_val()); + drag_touching=OS::get_singleton()->has_touchscreen_ui_hint(); + drag_touching_deaccel=false; + time_since_motion=0; + if (drag_touching) { + set_fixed_process(true); + time_since_motion=0; + + } + } + + + } else { + if (drag_touching) { + + if (drag_speed==Vector2()) { + drag_touching_deaccel=false; + drag_touching=false; + set_fixed_process(false); + } else { + + drag_touching_deaccel=true; + } + } + } + + + } break; + case InputEvent::MOUSE_MOTION: { + + const InputEventMouseMotion &mm=p_input_event.mouse_motion; + + if (drag_touching && ! drag_touching_deaccel) { + + Vector2 motion = Vector2(mm.relative_x,mm.relative_y); + drag_accum-=motion; + Vector2 diff = drag_from+drag_accum; + + if (scroll_h) + h_scroll->set_val(diff.x); + else + drag_accum.x=0; + if (scroll_v) + v_scroll->set_val(diff.y); + else + drag_accum.y=0; + time_since_motion=0; + } + + } break; + } + +} + + +void ScrollContainer::_update_scrollbar_pos() { + + Size2 size = get_size(); + Size2 hmin = h_scroll->get_combined_minimum_size(); + Size2 vmin = v_scroll->get_combined_minimum_size(); + + v_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,vmin.width); + v_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0); + v_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,0); + v_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0); + + h_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,0); + h_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0); + h_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,hmin.height); + h_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0); + + h_scroll->raise(); + v_scroll->raise(); + +} + + +void ScrollContainer::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_SCENE || p_what == NOTIFICATION_THEME_CHANGED) { + + call_deferred("_update_scrollbar_pos"); + }; + + + if (p_what==NOTIFICATION_SORT_CHILDREN) { + + child_max_size = Size2(0, 0); + Size2 size = get_size(); + for(int i=0;i<get_child_count();i++) { + + Control *c = get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + if (c == h_scroll || c == v_scroll) + continue; + Size2 minsize = c->get_combined_minimum_size(); + child_max_size.x = MAX(child_max_size.x, minsize.x); + child_max_size.y = MAX(child_max_size.y, minsize.y); + + Rect2 r = Rect2(-scroll,minsize); + if (!scroll_h) { + r.pos.x=0; + r.size.width=size.width; + } + if (!scroll_v) { + r.pos.y=0; + r.size.height=size.height; + } + fit_child_in_rect(c,r); + } + update(); + }; + + if (p_what == NOTIFICATION_DRAW) { + + update_scrollbars(); + + VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + } + + if (p_what==NOTIFICATION_FIXED_PROCESS) { + + if (drag_touching) { + + if (drag_touching_deaccel) { + + Vector2 pos = Vector2(h_scroll->get_val(),v_scroll->get_val()); + pos+=drag_speed*get_fixed_process_delta_time(); + + bool turnoff_h=false; + bool turnoff_v=false; + + if (pos.x<0) { + pos.x=0; + turnoff_h=true; + } + if (pos.x > (h_scroll->get_max()-h_scroll->get_page())) { + pos.x=h_scroll->get_max()-h_scroll->get_page(); + turnoff_h=true; + } + + if (pos.y<0) { + pos.x=0; + turnoff_v=true; + } + if (pos.y > (v_scroll->get_max()-v_scroll->get_page())) { + pos.y=v_scroll->get_max()-v_scroll->get_page(); + turnoff_v=true; + } + + if (scroll_h) + h_scroll->set_val(pos.x); + if (scroll_v) + v_scroll->set_val(pos.y); + + float sgn_x = drag_speed.x<0? -1 : 1; + float val_x = Math::abs(drag_speed.x); + val_x-=1000*get_fixed_process_delta_time(); + + if (val_x<0) { + turnoff_h=true; + } + + + float sgn_y = drag_speed.y<0? -1 : 1; + float val_y = Math::abs(drag_speed.y); + val_y-=1000*get_fixed_process_delta_time(); + + if (val_y<0) { + turnoff_v=true; + } + + + drag_speed=Vector2(sgn_x*val_x,sgn_y*val_y); + + if (turnoff_h && turnoff_v) { + set_fixed_process(false); + drag_touching=false; + drag_touching_deaccel=false; + } + + + } else { + + + if (time_since_motion==0 || time_since_motion>0.1) { + + Vector2 diff = drag_accum - last_drag_accum; + last_drag_accum=drag_accum; + drag_speed=diff/get_fixed_process_delta_time(); + } + + time_since_motion+=get_fixed_process_delta_time(); + } + } + } + +}; + +void ScrollContainer::update_scrollbars() { + + Size2 size = get_size(); + + Size2 hmin = h_scroll->get_combined_minimum_size(); + Size2 vmin = v_scroll->get_combined_minimum_size(); + + Size2 min = child_max_size; + + if (!scroll_v || min.height <= size.height - hmin.height) { + + v_scroll->hide(); + scroll.y=0; + } else { + + v_scroll->show(); + scroll.y=v_scroll->get_val(); + + } + + v_scroll->set_max(min.height); + v_scroll->set_page(size.height - hmin.height); + + + if (!scroll_h || min.width <= size.width - vmin.width) { + + h_scroll->hide(); + scroll.x=0; + } else { + + h_scroll->show(); + h_scroll->set_max(min.width); + h_scroll->set_page(size.width - vmin.width); + scroll.x=h_scroll->get_val(); + } +} + +void ScrollContainer::_scroll_moved(float) { + + scroll.x=h_scroll->get_val(); + scroll.y=v_scroll->get_val(); + queue_sort(); + + update(); +}; + + +void ScrollContainer::set_enable_h_scroll(bool p_enable) { + + scroll_h=p_enable; + queue_sort(); +} + +bool ScrollContainer::is_h_scroll_enabled() const{ + + return scroll_h; +} + +void ScrollContainer::set_enable_v_scroll(bool p_enable) { + + scroll_v=p_enable; + queue_sort(); +} + +bool ScrollContainer::is_v_scroll_enabled() const{ + + return scroll_v; +} + +int ScrollContainer::get_v_scroll() const { + + + return v_scroll->get_val(); +} +void ScrollContainer::set_v_scroll(int p_pos) { + + v_scroll->set_val(p_pos); + _cancel_drag(); +} + +int ScrollContainer::get_h_scroll() const { + + return h_scroll->get_val(); +} +void ScrollContainer::set_h_scroll(int p_pos) { + + h_scroll->set_val(p_pos); + _cancel_drag(); + +} + + +void ScrollContainer::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_scroll_moved"),&ScrollContainer::_scroll_moved); + ObjectTypeDB::bind_method(_MD("_input_event"),&ScrollContainer::_input_event); + ObjectTypeDB::bind_method(_MD("set_enable_h_scroll","enable"),&ScrollContainer::set_enable_h_scroll); + ObjectTypeDB::bind_method(_MD("is_h_scroll_enabled"),&ScrollContainer::is_h_scroll_enabled); + ObjectTypeDB::bind_method(_MD("set_enable_v_scroll","enable"),&ScrollContainer::set_enable_v_scroll); + ObjectTypeDB::bind_method(_MD("is_v_scroll_enabled"),&ScrollContainer::is_v_scroll_enabled); + ObjectTypeDB::bind_method(_MD("_update_scrollbar_pos"),&ScrollContainer::_update_scrollbar_pos); + ObjectTypeDB::bind_method(_MD("set_h_scroll","val"),&ScrollContainer::set_h_scroll); + ObjectTypeDB::bind_method(_MD("get_h_scroll"),&ScrollContainer::get_h_scroll); + ObjectTypeDB::bind_method(_MD("set_v_scroll","val"),&ScrollContainer::set_v_scroll); + ObjectTypeDB::bind_method(_MD("get_v_scroll"),&ScrollContainer::get_v_scroll); + + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll/horizontal"), _SCS("set_enable_h_scroll"),_SCS("is_h_scroll_enabled")); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll/vertical"), _SCS("set_enable_v_scroll"),_SCS("is_v_scroll_enabled")); + +}; + +ScrollContainer::ScrollContainer() { + + h_scroll = memnew(HScrollBar); + h_scroll->set_name("_h_scroll"); + add_child(h_scroll); + + v_scroll = memnew(VScrollBar); + v_scroll->set_name("_v_scroll"); + add_child(v_scroll); + + h_scroll->connect("value_changed", this,"_scroll_moved"); + v_scroll->connect("value_changed", this,"_scroll_moved"); + + drag_speed=Vector2(); + drag_touching=false; + drag_touching_deaccel=false; + scroll_h=true; + scroll_v=true; + + +}; + |