1 /******************************************************************************
2 * Warmux is a convivial mass murder game.
3 * Copyright (C) 2001-2011 Warmux Team.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 *****************************************************************************/
19
20 #include <vector>
21 #include <sstream>
22 #include "graphic/polygon_generator.h"
23 #include "graphic/sprite.h"
24 #include "graphic/text.h"
25 #include "graphic/video.h"
26 #include "gui/combo_box.h"
27 #include "gui/torus_cache.h"
28 #include "include/app.h"
29 #include "tool/affine_transform.h"
30 #include "tool/math_tools.h"
31 #include "tool/resource_manager.h"
32
33 #define SMALL_R 25
34 #define BIG_R 35
35 #define OPEN_ANGLE 0.96f // 55
36
ComboBox(const std::string & label,const std::string & resource_id,const Point2i & _size,const std::vector<std::pair<std::string,std::string>> & choices,const std::string choice)37 ComboBox::ComboBox (const std::string &label,
38 const std::string &resource_id,
39 const Point2i &_size,
40 const std::vector<std::pair<std::string, std::string> > &choices,
41 const std::string choice)
42 : m_choices(choices)
43 , m_index(0)
44 {
45 position = Point2i(-1, -1);
46 size = _size;
47
48 Profile *res = GetResourceManager().LoadXMLProfile("graphism.xml", false);
49 torus = new TorusCache(res, resource_id, BIG_R, SMALL_R);
50
51 txt_label = new Text(label, dark_gray_color, Font::FONT_SMALL, Font::FONT_BOLD, false);
52 txt_label->SetMaxWidth(GetSizeX());
53
54 txt_value_black = new Text("", black_color, Font::FONT_MEDIUM, Font::FONT_BOLD, false);
55 txt_value_white = new Text("", white_color, Font::FONT_MEDIUM, Font::FONT_BOLD, false);
56
57 std::vector<std::string>::size_type index = 0;
58 for (std::vector<std::pair<std::string, std::string> >::const_iterator iter
59 = choices.begin ();
60 iter != choices.end ();
61 iter++) {
62
63 if (iter->first == choice)
64 m_index = index;
65 index++;
66 }
67
68 SetChoice(m_index);
69 }
70
~ComboBox()71 ComboBox::~ComboBox ()
72 {
73 delete txt_label;
74 delete txt_value_black;
75 delete txt_value_white;
76 delete torus;
77 }
78
Pack()79 void ComboBox::Pack()
80 {
81 txt_label->SetMaxWidth(size.x);
82 }
83
Draw(const Point2i & mousePosition)84 void ComboBox::Draw(const Point2i &mousePosition)
85 {
86 Surface& window = GetMainWindow();
87
88 // the computed positions are to center on the image part of the widget
89
90 // 1. first draw the torus
91 torus->Draw(*this);
92
93
94 // 2. then draw buttons
95 #define IMG_BUTTONS_W 5
96 #define IMG_BUTTONS_H 12
97
98 Point2i center = GetPosition() + torus->GetCenter();
99 if (m_index > 0) {
100
101 if (Contains(mousePosition) && mousePosition.x < center.x)
102 torus->m_minus->SetCurrentFrame(1);
103 else
104 torus->m_minus->SetCurrentFrame(0);
105
106 torus->m_minus->Blit(window, GetPositionX() + IMG_BUTTONS_W, GetPositionY() + IMG_BUTTONS_H);
107 }
108
109 if (m_index < m_choices.size() - 1) {
110 if (Contains(mousePosition) && mousePosition.x > center.x)
111 torus->m_plus->SetCurrentFrame(1);
112 else
113 torus->m_plus->SetCurrentFrame(0);
114
115 torus->m_plus->Blit(window, GetPositionX() + GetSizeX() - torus->m_plus->GetWidth() - IMG_BUTTONS_W,
116 GetPosition().y + IMG_BUTTONS_H);
117 }
118
119 // 3. add in the value image
120 uint tmp_x = GetPositionX() + GetSizeX()/2;
121 uint tmp_y = center.y + SMALL_R - 3;
122 uint value_h = Font::GetInstance(Font::FONT_MEDIUM)->GetHeight();
123
124 txt_value_black->DrawCenterTop(Point2i(tmp_x + 1, tmp_y + 1 - value_h/2));
125 txt_value_white->DrawCenterTop(Point2i(tmp_x, tmp_y - value_h/2));
126
127 // 7. and finally the label image
128 txt_label->DrawCenterTop(Point2i(tmp_x, GetPositionY() + GetSizeY() - txt_label->GetHeight()));
129 }
130
ClickUp(const Point2i & mousePosition,uint button)131 Widget* ComboBox::ClickUp(const Point2i &mousePosition, uint button)
132 {
133 NeedRedrawing();
134
135 bool is_click = Mouse::IS_CLICK_BUTTON(button);
136 if ( (is_click && mousePosition.x > (GetPositionX() + GetSizeX()/2))
137 || button == SDL_BUTTON_WHEELUP ) {
138 SetChoice(m_index + 1);
139 return this;
140 } else if ( (is_click && mousePosition.x <= (GetPositionX() + GetSizeX()/2))
141 || button == SDL_BUTTON_WHEELDOWN ) {
142 SetChoice(m_index - 1);
143 return this;
144 }
145
146 return NULL;
147 }
148
SetChoice(std::vector<std::string>::size_type index)149 void ComboBox::SetChoice(std::vector<std::string>::size_type index)
150 {
151 std::string text;
152
153 if (index >= m_choices.size ())
154 return; /* index = 0; // loop back */
155
156 m_index = index;
157
158 txt_value_black->SetText(m_choices[m_index].second);
159 txt_value_white->SetText(m_choices[m_index].second);
160
161 RecreateTorus();
162 NeedRedrawing();
163 }
164
GetIntValue() const165 int ComboBox::GetIntValue() const
166 {
167 int tmp = 0;
168 sscanf(GetValue().c_str(),"%d", &tmp);
169 return tmp;
170 }
171
RecreateTorus()172 void ComboBox::RecreateTorus()
173 {
174 float angle;
175 if (m_choices.size () > 1)
176 angle = m_index*(2.0f*M_PI - OPEN_ANGLE) / (m_choices.size () - 1);
177 else
178 angle = 0;
179 torus->Refresh(angle, OPEN_ANGLE);
180 }
181