1
2 /*
3 Copyright (C) 2007 by David White <dave@whitevine.net>
4 Part of the Silver Tree Project
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 or later.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY.
10
11 See the COPYING file for more details.
12 */
13 #include <boost/bind.hpp>
14
15 #include "asserts.hpp"
16 #include "button.hpp"
17 #include "custom_object_functions.hpp"
18 #include "iphone_controls.hpp"
19 #include "formula.hpp"
20 #include "label.hpp"
21 #include "raster.hpp"
22 #include "surface_cache.hpp"
23 #include "framed_gui_element.hpp"
24 #include "widget_factory.hpp"
25
26 namespace gui {
27
button(const std::string & str,boost::function<void ()> onclick)28 button::button(const std::string& str, boost::function<void()> onclick)
29 : label_(new label(str, graphics::color_white())),
30 onclick_(onclick), button_resolution_(BUTTON_SIZE_NORMAL_RESOLUTION),
31 button_style_(BUTTON_STYLE_NORMAL), hpadding_(10), vpadding_(4),
32 down_(false)
33 {
34 set_environment();
35 setup();
36 }
37
button(widget_ptr label,boost::function<void ()> onclick,BUTTON_STYLE button_style,BUTTON_RESOLUTION button_resolution)38 button::button(widget_ptr label, boost::function<void ()> onclick, BUTTON_STYLE button_style, BUTTON_RESOLUTION button_resolution)
39 : label_(label), onclick_(onclick), button_resolution_(button_resolution), button_style_(button_style),
40 down_(false), hpadding_(10), vpadding_(4)
41
42 {
43 set_environment();
44 setup();
45 }
46
button(const variant & v,game_logic::formula_callable * e)47 button::button(const variant& v, game_logic::formula_callable* e) : widget(v,e), down_(false)
48 {
49 variant label_var = v["label"];
50 label_ = label_var.is_map() ? widget_factory::create(label_var, e) : new label(label_var.as_string_default("Button"), graphics::color_white());
51 ASSERT_LOG(v.has_key("on_click"), "Button must be supplied with an on_click handler");
52 // create delegate for onclick
53 ASSERT_LOG(get_environment() != 0, "You must specify a callable environment");
54 click_handler_ = get_environment()->create_formula(v["on_click"]);
55 onclick_ = boost::bind(&button::click, this);
56 button_resolution_ = v["resolution"].as_string_default("normal") == "normal" ? BUTTON_SIZE_NORMAL_RESOLUTION : BUTTON_SIZE_DOUBLE_RESOLUTION;
57 button_style_ = v["style"].as_string_default("default") == "default" ? BUTTON_STYLE_DEFAULT : BUTTON_STYLE_NORMAL;
58 hpadding_ = v["hpad"].as_int(10);
59 vpadding_ = v["vpad"].as_int(4);
60 if(v.has_key("padding")) {
61 ASSERT_LOG(v["padding"].num_elements() == 2, "Incorrect number of padding elements specifed." << v["padding"].num_elements());
62 hpadding_ = v["padding"][0].as_int();
63 vpadding_ = v["padding"][1].as_int();
64 }
65 setup();
66 }
67
click()68 void button::click()
69 {
70 if(get_environment()) {
71 variant value = click_handler_->execute(*get_environment());
72 get_environment()->execute_command(value);
73 } else {
74 std::cerr << "button::click() called without environment!" << std::endl;
75 }
76 }
77
setup()78 void button::setup()
79 {
80 if(button_style_ == BUTTON_STYLE_DEFAULT){
81 normal_button_image_set_ = framed_gui_element::get("default_button");
82 depressed_button_image_set_ = framed_gui_element::get("default_button_pressed");
83 focus_button_image_set_ = framed_gui_element::get("default_button_focus");
84 }else{
85 normal_button_image_set_ = framed_gui_element::get("regular_button");
86 depressed_button_image_set_ = framed_gui_element::get("regular_button_pressed");
87 focus_button_image_set_ = framed_gui_element::get("regular_button_focus");
88 }
89 current_button_image_set_ = normal_button_image_set_;
90
91 set_label(label_);
92 }
93
set_label(widget_ptr label)94 void button::set_label(widget_ptr label)
95 {
96 label_ = label;
97 set_dim(label_->width()+hpadding_*2,label_->height()+vpadding_*2);
98 }
99
handle_draw() const100 void button::handle_draw() const
101 {
102 label_->set_loc(x()+width()/2 - label_->width()/2,y()+height()/2 - label_->height()/2);
103 current_button_image_set_->blit(x(),y(),width(),height(), button_resolution_ != 0);
104 label_->draw();
105 }
106
handle_process()107 void button::handle_process()
108 {
109 widget::handle_process();
110 label_->process();
111 }
112
handle_event(const SDL_Event & event,bool claimed)113 bool button::handle_event(const SDL_Event& event, bool claimed)
114 {
115 if((event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP)
116 && (event.button.button == SDL_BUTTON_WHEELUP || event.button.button == SDL_BUTTON_WHEELDOWN)
117 && in_widget(event.button.x, event.button.y)) {
118 // skip processing if mousewheel event
119 return claimed;
120 }
121
122 if(claimed) {
123 current_button_image_set_ = normal_button_image_set_;
124 down_ = false;
125 }
126
127 if(event.type == SDL_MOUSEMOTION) {
128 const SDL_MouseMotionEvent& e = event.motion;
129 if(in_widget(e.x,e.y)) {
130 current_button_image_set_ = down_ ? depressed_button_image_set_ : focus_button_image_set_;
131 } else {
132 current_button_image_set_ = normal_button_image_set_;
133 }
134 } else if(event.type == SDL_MOUSEBUTTONDOWN) {
135 const SDL_MouseButtonEvent& e = event.button;
136 if(in_widget(e.x,e.y)) {
137 current_button_image_set_ = depressed_button_image_set_;
138 down_ = true;
139 claimed = true;
140 }
141 } else if(event.type == SDL_MOUSEBUTTONUP) {
142 down_ = false;
143 const SDL_MouseButtonEvent& e = event.button;
144 if(current_button_image_set_ == depressed_button_image_set_) {
145 if(in_widget(e.x,e.y)) {
146 current_button_image_set_ = focus_button_image_set_;
147 onclick_();
148 claimed = true;
149 } else {
150 current_button_image_set_ = normal_button_image_set_;
151 }
152 }
153 }
154 return claimed;
155 }
156
get_widget_by_id(const std::string & id)157 widget_ptr button::get_widget_by_id(const std::string& id)
158 {
159 if(label_ && label_->get_widget_by_id(id)) {
160 return label_;
161 }
162 return widget::get_widget_by_id(id);
163 }
164
get_value(const std::string & key) const165 variant button::get_value(const std::string& key) const
166 {
167 if(key == "label") {
168 return variant(label_.get());
169 }
170 return widget::get_value(key);
171 }
172
173 }
174