Update list of wide characters
[centerim5.git] / cppconsui / Button.cpp
blob6b028b5ddb82ba206772a1d8c4d6281eed9e3756
1 // Copyright (C) 2007 Mark Pustjens <pustjens@dds.nl>
2 // Copyright (C) 2010-2015 Petr Pavlu <setup@dagobah.cz>
3 //
4 // This file is part of CenterIM.
5 //
6 // CenterIM is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // CenterIM is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with CenterIM. If not, see <http://www.gnu.org/licenses/>.
19 /// @file
20 /// Button class implementation.
21 ///
22 /// @ingroup cppconsui
24 #include "Button.h"
26 #include "ColorScheme.h"
28 #include <cassert>
29 #include <cstdio>
30 #include <cstring>
32 namespace CppConsUI {
34 Button::Button(int w, int h, const char *text, int flags, bool masked)
35 : Widget(w, h), flags_(flags), text_(nullptr), text_width_(0),
36 text_height_(0), value_(nullptr), value_width_(0), unit_(nullptr),
37 unit_width_(0), right_(nullptr), right_width_(0), masked_(masked)
39 setText(text);
40 setValue(static_cast<char *>(nullptr));
41 setUnit(nullptr);
42 setRight(nullptr);
44 can_focus_ = true;
45 declareBindables();
48 Button::Button(const char *text, int flags, bool masked)
49 : Widget(AUTOSIZE, AUTOSIZE), flags_(flags), text_(nullptr), text_width_(0),
50 text_height_(0), value_(nullptr), value_width_(0), unit_(nullptr),
51 unit_width_(0), right_(nullptr), right_width_(0), masked_(masked)
53 setText(text);
54 setValue(static_cast<char *>(nullptr));
55 setUnit(nullptr);
56 setRight(nullptr);
58 can_focus_ = true;
59 declareBindables();
62 Button::Button(int w, int h, int flags, const char *text, const char *value,
63 const char *unit, const char *right, bool masked)
64 : Widget(w, h), flags_(flags), text_(nullptr), text_width_(0),
65 text_height_(0), value_(nullptr), value_width_(0), unit_(nullptr),
66 unit_width_(0), right_(nullptr), right_width_(0), masked_(masked)
68 setText(text);
69 setValue(value);
70 setUnit(unit);
71 setRight(right);
73 can_focus_ = true;
74 declareBindables();
77 Button::Button(int flags, const char *text, const char *value, const char *unit,
78 const char *right, bool masked)
79 : Widget(AUTOSIZE, AUTOSIZE), flags_(flags), text_(nullptr), text_width_(0),
80 text_height_(0), value_(nullptr), value_width_(0), unit_(nullptr),
81 unit_width_(0), right_(nullptr), right_width_(0), masked_(masked)
83 setText(text);
84 setValue(value);
85 setUnit(unit);
86 setRight(right);
88 can_focus_ = true;
89 declareBindables();
92 Button::~Button()
94 delete[] text_;
95 delete[] value_;
96 delete[] unit_;
97 delete[] right_;
100 int Button::draw(Curses::ViewPort area, Error &error)
102 assert(text_ != nullptr);
103 assert(value_ != nullptr);
104 assert(unit_ != nullptr);
105 assert(right_ != nullptr);
107 int attrs;
108 if (has_focus_) {
109 DRAW(getAttributes(ColorScheme::PROPERTY_BUTTON_FOCUS, &attrs, error));
110 attrs |= Curses::Attr::REVERSE;
112 else
113 DRAW(getAttributes(ColorScheme::PROPERTY_BUTTON_NORMAL, &attrs, error));
114 DRAW(area.attrOn(attrs, error));
116 // Print text.
117 DRAW(area.fill(attrs, 0, 0, text_width_, real_height_, error));
118 int y = 0;
119 const char *start, *end;
120 start = end = text_;
121 while (*end != '\0') {
122 if (*end == '\n') {
123 DRAW(area.addString(0, y, real_width_, start, end, error));
124 ++y;
125 start = end + 1;
127 ++end;
129 DRAW(area.addString(0, y, real_width_, start, end, error));
131 int l = text_width_;
132 int h = (text_height_ - 1) / 2;
133 int printed;
135 // Print value.
136 if (flags_ & FLAG_VALUE) {
137 DRAW(area.fill(attrs, l, 0, value_width_ + 2, real_height_, error));
138 DRAW(area.addString(l, h, real_width_ - l, ": ", error, &printed));
139 l += printed;
141 if (masked_) {
142 int count = value_width_;
143 while (count--) {
144 DRAW(area.addString(l, h, real_width_ - l, "*", error, &printed));
145 l += printed;
148 else {
149 DRAW(area.addString(l, h, real_width_ - l, value_, error, &printed));
150 l += printed;
154 // Print unit text.
155 if (flags_ & FLAG_UNIT) {
156 DRAW(area.fill(attrs, l, 0, unit_width_ + 1, real_height_, error));
157 DRAW(area.addString(l, h, real_width_ - l, " ", error, &printed));
158 l += printed;
159 DRAW(area.addString(l, h, real_width_ - l, unit_, error, &printed));
160 l += printed;
163 DRAW(area.attrOff(attrs, error));
165 // Print right area text.
166 if (flags_ & FLAG_RIGHT) {
167 const char *cur = right_;
168 int width = right_width_;
169 while (width > real_width_ - l - 1) {
170 width -= Curses::onScreenWidth(UTF8::getUniChar(cur));
171 cur = UTF8::getNextChar(cur);
173 DRAW(area.addString(real_width_ - width, h, cur, error));
176 return 0;
179 void Button::setFlags(int new_flags)
181 if (new_flags == flags_)
182 return;
184 flags_ = new_flags;
185 redraw();
188 void Button::setMasked(bool new_masked)
190 if (new_masked == masked_)
191 return;
193 masked_ = new_masked;
194 redraw();
197 void Button::setText(const char *new_text)
199 std::size_t size = 1;
200 if (new_text != nullptr)
201 size += std::strlen(new_text);
202 auto new_storage = new char[size];
203 if (new_text != nullptr)
204 std::strcpy(new_storage, new_text);
205 else
206 new_storage[0] = '\0';
208 delete[] text_;
209 text_ = new_storage;
211 // Update text_width_, text_height_ and wish height.
212 text_width_ = 0;
213 text_height_ = 1;
215 const char *start, *end;
216 start = end = text_;
217 int w;
218 while (*end != '\0') {
219 if (*end == '\n') {
220 w = Curses::onScreenWidth(start, end);
221 if (w > text_width_)
222 text_width_ = w;
223 ++text_height_;
224 start = end + 1;
226 ++end;
228 w = Curses::onScreenWidth(start, end);
229 if (w > text_width_)
230 text_width_ = w;
231 setWishHeight(text_height_);
233 redraw();
236 void Button::setValue(const char *new_value)
238 std::size_t size = 1;
239 if (new_value != nullptr)
240 size += std::strlen(new_value);
241 auto new_storage = new char[size];
242 if (new_value != nullptr)
243 std::strcpy(new_storage, new_value);
244 else
245 new_storage[0] = '\0';
247 delete[] value_;
248 value_ = new_storage;
250 value_width_ = Curses::onScreenWidth(value_);
251 redraw();
254 void Button::setValue(int new_value)
256 char tmp[PRINTF_WIDTH(int) + 1];
257 std::sprintf(tmp, "%d", new_value);
258 setValue(tmp);
261 void Button::setUnit(const char *new_unit)
263 std::size_t size = 1;
264 if (new_unit != nullptr)
265 size += std::strlen(new_unit);
266 auto new_storage = new char[size];
267 if (new_unit != nullptr)
268 std::strcpy(new_storage, new_unit);
269 else
270 new_storage[0] = '\0';
272 delete[] unit_;
273 unit_ = new_storage;
275 unit_width_ = Curses::onScreenWidth(unit_);
276 redraw();
279 void Button::setRight(const char *new_right)
281 std::size_t size = 1;
282 if (new_right != nullptr)
283 size += std::strlen(new_right);
284 auto new_storage = new char[size];
285 if (new_right != nullptr)
286 std::strcpy(new_storage, new_right);
287 else
288 new_storage[0] = '\0';
290 delete[] right_;
291 right_ = new_storage;
293 right_width_ = Curses::onScreenWidth(right_);
294 redraw();
297 void Button::actionActivate()
299 signal_activate(*this);
302 void Button::declareBindables()
304 declareBindable("button", "activate",
305 sigc::mem_fun(this, &Button::actionActivate),
306 InputProcessor::BINDABLE_NORMAL);
309 } // namespace CppConsUI
311 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: