00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "gui/widgets/text.hpp"
00016
00017 #include "clipboard.hpp"
00018 #include "gui/widgets/event_handler.hpp"
00019 #include "log.hpp"
00020 #include "serialization/string_utils.hpp"
00021
00022 #define DBG_G LOG_STREAM_INDENT(debug, gui)
00023 #define LOG_G LOG_STREAM_INDENT(info, gui)
00024 #define WRN_G LOG_STREAM_INDENT(warn, gui)
00025 #define ERR_G LOG_STREAM_INDENT(err, gui)
00026
00027 #define DBG_G_D LOG_STREAM_INDENT(debug, gui_draw)
00028 #define LOG_G_D LOG_STREAM_INDENT(info, gui_draw)
00029 #define WRN_G_D LOG_STREAM_INDENT(warn, gui_draw)
00030 #define ERR_G_D LOG_STREAM_INDENT(err, gui_draw)
00031
00032 #define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
00033 #define LOG_G_E LOG_STREAM_INDENT(info, gui_event)
00034 #define WRN_G_E LOG_STREAM_INDENT(warn, gui_event)
00035 #define ERR_G_E LOG_STREAM_INDENT(err, gui_event)
00036
00037 #define DBG_G_P LOG_STREAM_INDENT(debug, gui_parse)
00038 #define LOG_G_P LOG_STREAM_INDENT(info, gui_parse)
00039 #define WRN_G_P LOG_STREAM_INDENT(warn, gui_parse)
00040 #define ERR_G_P LOG_STREAM_INDENT(err, gui_parse)
00041
00042 namespace gui2 {
00043
00044 void ttext_::set_cursor(const size_t offset, const bool select)
00045 {
00046 if(select) {
00047
00048 if(sel_start_ == offset) {
00049 sel_len_ = 0;
00050 } else {
00051 sel_len_ = - (sel_start_ - offset);
00052 }
00053
00054 #ifdef __unix__
00055
00056 copy_selection(true);
00057 #endif
00058 set_canvas_text();
00059 set_dirty();
00060
00061 } else {
00062 assert(offset <= text_.size());
00063 sel_start_ = offset;
00064 sel_len_ = 0;
00065
00066 set_canvas_text();
00067 set_dirty();
00068 }
00069 }
00070
00071 void ttext_::mouse_move(tevent_handler&)
00072 {
00073 DBG_G_E << "Text_box: mouse move.\n";
00074
00075
00076 }
00077
00078 void ttext_::mouse_left_button_down(tevent_handler& event)
00079 {
00080 DBG_G_E << "Text_box: left mouse button down.\n";
00081
00082 event.keyboard_capture(this);
00083 event.mouse_capture();
00084 }
00085
00086 void ttext_::mouse_left_button_up(tevent_handler&)
00087 {
00088
00089 DBG_G_E << "Text_box: left mouse button up.\n";
00090 }
00091
00092 void ttext_::mouse_left_button_double_click(tevent_handler&)
00093 {
00094 DBG_G_E << "Text_box: left mouse button double click.\n";
00095
00096 sel_start_ = 0;
00097 sel_len_ = text_.size();
00098
00099 }
00100
00101 void ttext_::mouse_middle_button_click(tevent_handler&)
00102 {
00103 DBG_G_E << "Text_box: middle mouse button click.\n";
00104 #ifdef __unix__
00105
00106 paste_selection(true);
00107 #endif
00108
00109 }
00110
00111 void ttext_::key_press(tevent_handler& , bool& handled, SDLKey key, SDLMod modifier, Uint16 unicode)
00112 {
00113 DBG_G_E << "Text_box: key press.\n";
00114
00115
00116
00117
00118 #ifdef __APPLE__
00119 const unsigned copypaste_modifier = KMOD_LMETA | KMOD_RMETA;
00120 #else
00121 const unsigned copypaste_modifier = KMOD_CTRL;
00122 #endif
00123
00124 switch(key) {
00125
00126 case SDLK_LEFT :
00127 handle_key_left_arrow(modifier, handled);
00128 break;
00129
00130 case SDLK_RIGHT :
00131 handle_key_right_arrow(modifier, handled);
00132 break;
00133
00134 case SDLK_UP :
00135 handle_key_up_arrow(modifier, handled);
00136 break;
00137
00138 case SDLK_DOWN :
00139 handle_key_down_arrow(modifier, handled);
00140 break;
00141
00142 case SDLK_PAGEUP :
00143 handle_key_page_up(modifier, handled);
00144 break;
00145
00146 case SDLK_PAGEDOWN :
00147 handle_key_page_down(modifier, handled);
00148 break;
00149
00150 case SDLK_a :
00151 if(!(modifier & KMOD_CTRL)) {
00152 handle_key_default(handled, key, modifier, unicode);
00153 break;
00154 }
00155
00156
00157 modifier = static_cast<SDLMod>(modifier &~ KMOD_CTRL);
00158
00159
00160 case SDLK_HOME :
00161 handle_key_home(modifier, handled);
00162 break;
00163
00164 case SDLK_e :
00165 if(!(modifier & KMOD_CTRL)) {
00166 handle_key_default(handled, key, modifier, unicode);
00167 break;
00168 }
00169
00170
00171 modifier = static_cast<SDLMod>(modifier &~ KMOD_CTRL);
00172
00173
00174 case SDLK_END :
00175 handle_key_end(modifier, handled);
00176 break;
00177
00178 case SDLK_BACKSPACE :
00179 handle_key_backspace(modifier, handled);
00180 break;
00181
00182 case SDLK_u :
00183 if(modifier & KMOD_CTRL) {
00184 handle_key_clear_line(modifier, handled);
00185 } else {
00186 handle_key_default(handled, key, modifier, unicode);
00187 }
00188 break;
00189
00190 case SDLK_DELETE :
00191 handle_key_delete(modifier, handled);
00192 break;
00193
00194 case SDLK_c :
00195 if(!(modifier & copypaste_modifier)) {
00196 handle_key_default(handled, key, modifier, unicode);
00197 break;
00198 }
00199
00200
00201
00202 copy_selection(false);
00203 handled = true;
00204 break;
00205
00206 case SDLK_x :
00207 if(!(modifier & copypaste_modifier)) {
00208 handle_key_default(handled, key, modifier, unicode);
00209 break;
00210 }
00211
00212 copy_selection(false);
00213 delete_selection();
00214 handled = true;
00215 break;
00216
00217 case SDLK_v :
00218 if(!(modifier & copypaste_modifier)) {
00219 handle_key_default(handled, key, modifier, unicode);
00220 break;
00221 }
00222
00223 paste_selection(false);
00224 handled = true;
00225 break;
00226
00227 default :
00228 handle_key_default(handled, key, modifier, unicode);
00229
00230 }
00231
00232 }
00233
00234 void ttext_::set_text(const std::string& text)
00235 {
00236 if(text != text_) {
00237 text_ = text;
00238 calculate_char_offset();
00239
00240
00241 sel_start_ = text_.size();
00242 sel_len_ = 0;
00243 set_canvas_text();
00244 set_dirty();
00245 }
00246 }
00247
00248 void ttext_::set_state(tstate state)
00249 {
00250 if(state != state_) {
00251 state_ = state;
00252 set_dirty(true);
00253 }
00254 }
00255
00256
00257 void ttext_::copy_selection(const bool mouse)
00258 {
00259 int len = sel_len();
00260 unsigned start = sel_start();
00261
00262 if(len < 0) {
00263 len = - len;
00264 start -= len;
00265 }
00266
00267 const wide_string& wtext = utils::string_to_wstring(text_);
00268 const std::string& text = utils::wstring_to_string(wide_string(wtext.begin() + start, wtext.begin() + start +len));
00269 copy_to_clipboard(text, mouse);
00270 }
00271
00272
00273 void ttext_::paste_selection(const bool mouse)
00274 {
00275 const std::string& text = copy_from_clipboard(mouse);
00276 if(text.empty()) {
00277 return;
00278 }
00279
00280 delete_selection();
00281
00282 text_.insert(sel_start_, text);
00283
00284 sel_start_ += utils::string_to_wstring(text).size();
00285
00286 calculate_char_offset();
00287 set_canvas_text();
00288 set_dirty();
00289 }
00290
00291
00292
00293
00294 void ttext_::handle_key_left_arrow(SDLMod modifier, bool& handled)
00295 {
00296 DBG_G_E << "Text_box: key press: left arrow.\n";
00297
00298 handled = true;
00299 if(sel_start_) {
00300 set_cursor(sel_start_ - 1 + sel_len_, modifier & KMOD_SHIFT);
00301 }
00302 }
00303
00304
00305
00306
00307 void ttext_::handle_key_right_arrow(SDLMod modifier, bool& handled)
00308 {
00309 DBG_G_E << "Text_box: key press: right arrow.\n";
00310
00311 handled = true;
00312 if(sel_start_ < text_.size()) {
00313 set_cursor(sel_start_ + 1 + sel_len_, modifier & KMOD_SHIFT);
00314 }
00315 }
00316
00317
00318
00319
00320 void ttext_::handle_key_home(SDLMod modifier, bool& handled)
00321 {
00322 DBG_G_E << "Text_box: key press: home.\n";
00323
00324 handled = true;
00325 if(modifier & KMOD_CTRL) {
00326 goto_start_of_data(modifier & KMOD_SHIFT);
00327 } else {
00328 goto_start_of_line(modifier & KMOD_SHIFT);
00329 }
00330 }
00331
00332
00333
00334
00335 void ttext_::handle_key_end(SDLMod modifier, bool& handled)
00336 {
00337 DBG_G_E << "Text_box: key press: end.\n";
00338
00339 handled = true;
00340 if(modifier & KMOD_CTRL) {
00341 goto_end_of_data(modifier & KMOD_SHIFT);
00342 } else {
00343 goto_end_of_line(modifier & KMOD_SHIFT);
00344 }
00345 }
00346
00347
00348 void ttext_::handle_key_backspace(SDLMod , bool& handled)
00349 {
00350 DBG_G_E << "Text_box: key press: backspace.\n";
00351
00352 handled = true;
00353 if(sel_start_){
00354 delete_char(true);
00355 }
00356
00357 }
00358
00359
00360 void ttext_::handle_key_delete(SDLMod , bool& handled)
00361 {
00362 DBG_G_E << "Text_box: key press: delete.\n";
00363
00364 handled = true;
00365 if(sel_len_ != 0) {
00366 delete_selection();
00367 } else if (sel_start_ < text_.size()) {
00368 delete_char(false);
00369 }
00370 }
00371
00372 void ttext_::handle_key_default(bool& handled, SDLKey , SDLMod , Uint16 unicode)
00373 {
00374 DBG_G_E << "Text_box: key press: default.\n";
00375
00376 if(unicode >= 32 && unicode != 127) {
00377 handled = true;
00378 insert_char(unicode);
00379 }
00380 }
00381
00382 }
00383