summaryrefslogtreecommitdiff
path: root/scene/gui/scroll_container.cpp
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
commit0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch)
tree276c4d099e178eb67fbd14f61d77b05e3808e9e3 /scene/gui/scroll_container.cpp
parent0e49da1687bc8192ed210947da52c9e5c5f301bb (diff)
GODOT IS OPEN SOURCE
Diffstat (limited to 'scene/gui/scroll_container.cpp')
-rw-r--r--scene/gui/scroll_container.cpp427
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;
+
+
+};
+