line_edit.cpp 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. /*************************************************************************/
  2. /* line_edit.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "line_edit.h"
  30. #include "os/keyboard.h"
  31. #include "os/os.h"
  32. #include "print_string.h"
  33. #include "label.h"
  34. void LineEdit::_input_event(InputEvent p_event) {
  35. switch(p_event.type) {
  36. case InputEvent::MOUSE_BUTTON: {
  37. const InputEventMouseButton &b = p_event.mouse_button;
  38. if (b.button_index!=1)
  39. break;
  40. if (b.pressed) {
  41. shift_selection_check_pre(b.mod.shift);
  42. set_cursor_at_pixel_pos(b.x);
  43. if (b.mod.shift) {
  44. selection_fill_at_cursor();
  45. selection.creating=true;
  46. } else {
  47. if (b.doubleclick) {
  48. selection.enabled=true;
  49. selection.begin=0;
  50. selection.end=text.length();
  51. selection.doubleclick=true;
  52. }
  53. selection.drag_attempt=false;
  54. if ((cursor_pos<selection.begin) || (cursor_pos>selection.end) || !selection.enabled) {
  55. selection_clear();
  56. selection.cursor_start=cursor_pos;
  57. selection.creating=true;
  58. } else if (selection.enabled) {
  59. selection.drag_attempt=true;
  60. }
  61. }
  62. // if (!editable)
  63. // non_editable_clicked_signal.call();
  64. update();
  65. } else {
  66. if ( (!selection.creating) && (!selection.doubleclick)) {
  67. selection_clear();
  68. }
  69. selection.creating=false;
  70. selection.doubleclick=false;
  71. if (OS::get_singleton()->has_virtual_keyboard())
  72. OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect());
  73. }
  74. update();
  75. } break;
  76. case InputEvent::MOUSE_MOTION: {
  77. const InputEventMouseMotion& m=p_event.mouse_motion;
  78. if (m.button_mask&1) {
  79. if (selection.creating) {
  80. set_cursor_at_pixel_pos(m.x);
  81. selection_fill_at_cursor();
  82. }
  83. }
  84. } break;
  85. case InputEvent::KEY: {
  86. const InputEventKey &k =p_event.key;
  87. if (!k.pressed)
  88. return;
  89. unsigned int code = k.scancode;
  90. if (k.mod.command) {
  91. bool handled=true;
  92. switch (code) {
  93. case (KEY_X): { // CUT
  94. if(k.mod.command && editable) {
  95. cut_text();
  96. }
  97. } break;
  98. case (KEY_C): { // COPY
  99. if(k.mod.command) {
  100. copy_text();
  101. }
  102. } break;
  103. case (KEY_V): { // PASTE
  104. if(k.mod.command && editable) {
  105. paste_text();
  106. }
  107. } break;
  108. case (KEY_Z): { // Simple One level undo
  109. if( k.mod.command && editable) {
  110. int old_cursor_pos = cursor_pos;
  111. text = undo_text;
  112. Ref<Font> font = get_font("font");
  113. cached_width = 0;
  114. for (int i = 0; i<text.length(); i++)
  115. cached_width += font->get_char_size(text[i]).width;
  116. if(old_cursor_pos > text.length()) {
  117. set_cursor_pos(text.length());
  118. } else {
  119. set_cursor_pos(old_cursor_pos);
  120. }
  121. }
  122. emit_signal("text_changed",text);
  123. _change_notify("text");
  124. } break;
  125. case (KEY_U): { // Delete from start to cursor
  126. if( k.mod.command && editable) {
  127. selection_clear();
  128. undo_text = text;
  129. text = text.substr(cursor_pos,text.length()-cursor_pos);
  130. Ref<Font> font = get_font("font");
  131. cached_width = 0;
  132. if (font != NULL) {
  133. for (int i = 0; i < text.length(); i++)
  134. cached_width += font->get_char_size(text[i]).width;
  135. }
  136. set_cursor_pos(0);
  137. emit_signal("text_changed",text);
  138. _change_notify("text");
  139. }
  140. } break;
  141. case (KEY_Y): { // PASTE (Yank for unix users)
  142. if(k.mod.command && editable) {
  143. paste_text();
  144. }
  145. } break;
  146. case (KEY_K): { // Delete from cursor_pos to end
  147. if(k.mod.command && editable) {
  148. selection_clear();
  149. undo_text = text;
  150. text = text.substr(0,cursor_pos);
  151. emit_signal("text_changed",text);
  152. _change_notify("text");
  153. }
  154. } break;
  155. case (KEY_A): { //Select All
  156. select();
  157. } break;
  158. default: { handled=false;}
  159. }
  160. if (handled) {
  161. accept_event();
  162. return;
  163. }
  164. }
  165. if (!k.mod.alt && !k.mod.meta && !k.mod.command) {
  166. bool handled=true;
  167. switch (code) {
  168. case KEY_ENTER:
  169. case KEY_RETURN: {
  170. emit_signal( "text_entered",text );
  171. if (OS::get_singleton()->has_virtual_keyboard())
  172. OS::get_singleton()->hide_virtual_keyboard();
  173. return;
  174. } break;
  175. case KEY_BACKSPACE: {
  176. if (editable) {
  177. undo_text = text;
  178. if (selection.enabled)
  179. selection_delete();
  180. else
  181. delete_char();
  182. }
  183. } break;
  184. case KEY_KP_4: {
  185. if (k.unicode != 0) {
  186. handled = false;
  187. break;
  188. }
  189. // numlock disabled. fallthrough to key_left
  190. }
  191. case KEY_LEFT: {
  192. shift_selection_check_pre(k.mod.shift);
  193. set_cursor_pos(get_cursor_pos()-1);
  194. shift_selection_check_post(k.mod.shift);
  195. } break;
  196. case KEY_KP_6: {
  197. if (k.unicode != 0) {
  198. handled = false;
  199. break;
  200. }
  201. // numlock disabled. fallthrough to key_right
  202. }
  203. case KEY_RIGHT: {
  204. shift_selection_check_pre(k.mod.shift);
  205. set_cursor_pos(get_cursor_pos()+1);
  206. shift_selection_check_post(k.mod.shift);
  207. } break;
  208. case KEY_DELETE: {
  209. if (k.mod.shift && !k.mod.command && !k.mod.alt && editable) {
  210. cut_text();
  211. break;
  212. }
  213. if (editable) {
  214. undo_text = text;
  215. if (selection.enabled)
  216. selection_delete();
  217. else if (cursor_pos<text.length()) {
  218. set_cursor_pos(get_cursor_pos()+1);
  219. delete_char();
  220. }
  221. }
  222. } break;
  223. case KEY_KP_7: {
  224. if (k.unicode != 0) {
  225. handled = false;
  226. break;
  227. }
  228. // numlock disabled. fallthrough to key_home
  229. }
  230. case KEY_HOME: {
  231. shift_selection_check_pre(k.mod.shift);
  232. set_cursor_pos(0);
  233. shift_selection_check_post(k.mod.shift);
  234. } break;
  235. case KEY_KP_1: {
  236. if (k.unicode != 0) {
  237. handled = false;
  238. break;
  239. }
  240. // numlock disabled. fallthrough to key_end
  241. }
  242. case KEY_END: {
  243. shift_selection_check_pre(k.mod.shift);
  244. set_cursor_pos(text.length());
  245. shift_selection_check_post(k.mod.shift);
  246. } break;
  247. default: {
  248. handled=false;
  249. } break;
  250. }
  251. if (handled) {
  252. accept_event();
  253. } else {
  254. if (k.unicode>=32 && k.scancode!=KEY_DELETE) {
  255. if (editable) {
  256. selection_delete();
  257. CharType ucodestr[2]={(CharType)k.unicode,0};
  258. append_at_cursor(ucodestr);
  259. emit_signal("text_changed",text);
  260. _change_notify("text");
  261. accept_event();
  262. }
  263. } else {
  264. return;
  265. }
  266. }
  267. update();
  268. }
  269. return;
  270. } break;
  271. }
  272. }
  273. void LineEdit::set_align(Align p_align) {
  274. ERR_FAIL_INDEX(p_align, 4);
  275. align = p_align;
  276. update();
  277. }
  278. LineEdit::Align LineEdit::get_align() const{
  279. return align;
  280. }
  281. Variant LineEdit::get_drag_data(const Point2& p_point) {
  282. if (selection.drag_attempt && selection.enabled) {
  283. String t = text.substr(selection.begin, selection.end - selection.begin);
  284. Label *l = memnew( Label );
  285. l->set_text(t);
  286. set_drag_preview(l);
  287. return t;
  288. }
  289. return Variant();
  290. }
  291. bool LineEdit::can_drop_data(const Point2& p_point,const Variant& p_data) const{
  292. return p_data.get_type()==Variant::STRING;
  293. }
  294. void LineEdit::drop_data(const Point2& p_point,const Variant& p_data){
  295. if (p_data.get_type()==Variant::STRING) {
  296. set_cursor_at_pixel_pos(p_point.x);
  297. int selected = selection.end - selection.begin;
  298. Ref<Font> font = get_font("font");
  299. if (font != NULL) {
  300. for (int i = selection.begin; i < selection.end; i++)
  301. cached_width -= font->get_char_size(text[i]).width;
  302. }
  303. text.erase(selection.begin, selected);
  304. append_at_cursor(p_data);
  305. selection.begin = cursor_pos-selected;
  306. selection.end = cursor_pos;
  307. }
  308. }
  309. void LineEdit::_notification(int p_what) {
  310. switch(p_what) {
  311. case NOTIFICATION_RESIZED: {
  312. set_cursor_pos( get_cursor_pos() );
  313. } break;
  314. case NOTIFICATION_DRAW: {
  315. int width,height;
  316. Size2 size=get_size();
  317. width=size.width;
  318. height=size.height;
  319. RID ci = get_canvas_item();
  320. Ref<StyleBox> style = get_stylebox("normal");
  321. if (!is_editable())
  322. style=get_stylebox("read_only");
  323. Ref<Font> font=get_font("font");
  324. style->draw( ci, Rect2( Point2(), size ) );
  325. if (has_focus()) {
  326. get_stylebox("focus")->draw( ci, Rect2( Point2(), size ) );
  327. }
  328. int x_ofs=0;
  329. switch (align) {
  330. case ALIGN_FILL:
  331. case ALIGN_LEFT: {
  332. x_ofs=style->get_offset().x;
  333. } break;
  334. case ALIGN_CENTER: {
  335. x_ofs=x_ofs=int(size.width-(cached_width))/2;
  336. } break;
  337. case ALIGN_RIGHT: {
  338. x_ofs=x_ofs=int(size.width-style->get_offset().x-(cached_width));
  339. } break;
  340. }
  341. int ofs_max=width-style->get_minimum_size().width;
  342. int char_ofs=window_pos;
  343. int y_area=height-style->get_minimum_size().height;
  344. int y_ofs=style->get_offset().y;
  345. int font_ascent=font->get_ascent();
  346. Color selection_color=get_color("selection_color");
  347. Color font_color=get_color("font_color");
  348. Color font_color_selected=get_color("font_color_selected");
  349. Color cursor_color=get_color("cursor_color");
  350. while(true) {
  351. //end of string, break!
  352. if (char_ofs>=text.length())
  353. break;
  354. CharType cchar=pass?'*':text[char_ofs];
  355. CharType next=pass?'*':text[char_ofs+1];
  356. int char_width=font->get_char_size( cchar,next ).width;
  357. // end of widget, break!
  358. if ((x_ofs + char_width) > ofs_max)
  359. break;
  360. bool selected=selection.enabled && char_ofs>=selection.begin && char_ofs<selection.end;
  361. if (selected)
  362. VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(char_width, y_area)), selection_color);
  363. font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, selected ? font_color_selected : font_color);
  364. if (char_ofs==cursor_pos && has_focus())
  365. VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(
  366. Point2( x_ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color );
  367. x_ofs+=char_width;
  368. char_ofs++;
  369. }
  370. if (char_ofs==cursor_pos && has_focus()) //may be at the end
  371. VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(
  372. Point2( x_ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color );
  373. } break;
  374. case NOTIFICATION_FOCUS_ENTER: {
  375. if (OS::get_singleton()->has_virtual_keyboard())
  376. OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect());
  377. } break;
  378. case NOTIFICATION_FOCUS_EXIT: {
  379. if (OS::get_singleton()->has_virtual_keyboard())
  380. OS::get_singleton()->hide_virtual_keyboard();
  381. } break;
  382. }
  383. }
  384. void LineEdit::copy_text() {
  385. if(selection.enabled) {
  386. OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
  387. }
  388. }
  389. void LineEdit::cut_text() {
  390. if(selection.enabled) {
  391. undo_text = text;
  392. OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
  393. selection_delete();
  394. }
  395. }
  396. void LineEdit::paste_text() {
  397. String paste_buffer = OS::get_singleton()->get_clipboard();
  398. if(paste_buffer != "") {
  399. if(selection.enabled) selection_delete();
  400. append_at_cursor(paste_buffer);
  401. emit_signal("text_changed",text);
  402. _change_notify("text");
  403. }
  404. }
  405. void LineEdit::shift_selection_check_pre(bool p_shift) {
  406. if (!selection.enabled && p_shift) {
  407. selection.cursor_start=cursor_pos;
  408. }
  409. if (!p_shift)
  410. selection_clear();
  411. }
  412. void LineEdit::shift_selection_check_post(bool p_shift) {
  413. if (p_shift)
  414. selection_fill_at_cursor();
  415. }
  416. void LineEdit::set_cursor_at_pixel_pos(int p_x) {
  417. Ref<Font> font = get_font("font");
  418. int ofs = window_pos;
  419. Ref<StyleBox> style = get_stylebox("normal");
  420. int pixel_ofs = 0;
  421. Size2 size = get_size();
  422. switch (align) {
  423. case ALIGN_FILL:
  424. case ALIGN_LEFT: {
  425. pixel_ofs = int(style->get_offset().x);
  426. } break;
  427. case ALIGN_CENTER: {
  428. pixel_ofs=int(size.width-(cached_width))/2;
  429. } break;
  430. case ALIGN_RIGHT: {
  431. pixel_ofs=int(size.width-style->get_offset().x-(cached_width));
  432. } break;
  433. }
  434. while (ofs<text.length()) {
  435. int char_w = 0;
  436. if (font != NULL) {
  437. char_w = font->get_char_size(text[ofs]).width;
  438. }
  439. pixel_ofs+=char_w;
  440. if (pixel_ofs > p_x) { //found what we look for
  441. if ( (pixel_ofs-p_x) < (char_w >> 1 ) ) {
  442. ofs+=1;
  443. }
  444. break;
  445. }
  446. ofs++;
  447. }
  448. set_cursor_pos( ofs );
  449. /*
  450. int new_cursor_pos=p_x;
  451. int charwidth=draw_area->get_font_char_width(' ',0);
  452. new_cursor_pos=( ( (new_cursor_pos-2)+ (charwidth/2) ) /charwidth );
  453. if (new_cursor_pos>(int)text.length()) new_cursor_pos=text.length();
  454. set_cursor_pos(window_pos+new_cursor_pos); */
  455. }
  456. void LineEdit::delete_char() {
  457. if ((text.length()<=0) || (cursor_pos==0)) return;
  458. Ref<Font> font = get_font("font");
  459. if (font != NULL) {
  460. cached_width -= font->get_char_size(text[cursor_pos - 1]).width;
  461. }
  462. text.erase( cursor_pos-1, 1 );
  463. set_cursor_pos(get_cursor_pos()-1);
  464. if (cursor_pos==window_pos) {
  465. // set_window_pos(cursor_pos-get_window_length());
  466. }
  467. emit_signal("text_changed",text);
  468. _change_notify("text");
  469. }
  470. void LineEdit::set_text(String p_text) {
  471. clear_internal();
  472. append_at_cursor(p_text);
  473. update();
  474. cursor_pos=0;
  475. window_pos=0;
  476. }
  477. void LineEdit::clear() {
  478. clear_internal();
  479. }
  480. String LineEdit::get_text() const {
  481. return text;
  482. }
  483. void LineEdit::set_cursor_pos(int p_pos) {
  484. if (p_pos>(int)text.length())
  485. p_pos=text.length();
  486. if(p_pos<0)
  487. p_pos=0;
  488. cursor_pos=p_pos;
  489. // if (cursor_pos>(window_pos+get_window_length())) {
  490. // set_window_pos(cursor_pos-get_window_lengt//h());
  491. // }
  492. if (!is_inside_tree()) {
  493. window_pos=cursor_pos;
  494. return;
  495. }
  496. Ref<StyleBox> style = get_stylebox("normal");
  497. Ref<Font> font=get_font("font");
  498. if (cursor_pos<window_pos) {
  499. /* Adjust window if cursor goes too much to the left */
  500. set_window_pos(cursor_pos);
  501. } else if (cursor_pos>window_pos) {
  502. /* Adjust window if cursor goes too much to the right */
  503. int window_width=get_size().width-style->get_minimum_size().width;
  504. if (window_width<0)
  505. return;
  506. int width_to_cursor=0;
  507. int wp=window_pos;
  508. if (font.is_valid()) {
  509. int accum_width=0;
  510. for(int i=cursor_pos;i>=window_pos;i--) {
  511. if (i>=text.length()) {
  512. accum_width=font->get_char_size(' ').width; //anything should do
  513. } else {
  514. accum_width+=font->get_char_size(text[i],i+1<text.length()?text[i+1]:0).width; //anything should do
  515. }
  516. if (accum_width>=window_width)
  517. break;
  518. wp=i;
  519. }
  520. }
  521. if (wp!=window_pos)
  522. set_window_pos( wp );
  523. }
  524. update();
  525. }
  526. int LineEdit::get_cursor_pos() const {
  527. return cursor_pos;
  528. }
  529. void LineEdit::set_window_pos(int p_pos) {
  530. window_pos=p_pos;
  531. if (window_pos<0) window_pos=0;
  532. }
  533. void LineEdit::append_at_cursor(String p_text) {
  534. if ( ( max_length <= 0 ) || (text.length()+p_text.length() <= max_length)) {
  535. undo_text = text;
  536. Ref<Font> font = get_font("font");
  537. if (font != NULL) {
  538. for (int i = 0; i < p_text.length(); i++)
  539. cached_width += font->get_char_size(p_text[i]).width;
  540. }
  541. else {
  542. cached_width = 0;
  543. }
  544. String pre = text.substr( 0, cursor_pos );
  545. String post = text.substr( cursor_pos, text.length()-cursor_pos );
  546. text=pre+p_text+post;
  547. set_cursor_pos(cursor_pos+p_text.length());
  548. }
  549. }
  550. void LineEdit::clear_internal() {
  551. cached_width = 0;
  552. cursor_pos=0;
  553. window_pos=0;
  554. undo_text="";
  555. text="";
  556. update();
  557. }
  558. Size2 LineEdit::get_minimum_size() const {
  559. Ref<StyleBox> style = get_stylebox("normal");
  560. Ref<Font> font=get_font("font");
  561. Size2 min=style->get_minimum_size();
  562. min.height+=font->get_height();
  563. min.width+=get_constant("minimum_spaces")*font->get_char_size(' ').x;
  564. return min;
  565. }
  566. /* selection */
  567. void LineEdit::selection_clear() {
  568. selection.begin=0;
  569. selection.end=0;
  570. selection.cursor_start=0;
  571. selection.enabled=false;
  572. selection.creating=false;
  573. selection.doubleclick=false;
  574. update();
  575. }
  576. void LineEdit::selection_delete() {
  577. if (selection.enabled) {
  578. undo_text = text;
  579. if (text.size() > 0)
  580. {
  581. Ref<Font> font = get_font("font");
  582. if (font != NULL) {
  583. for (int i = selection.begin; i < selection.end; i++)
  584. cached_width -= font->get_char_size(text[i]).width;
  585. }
  586. }
  587. else
  588. {
  589. cached_width = 0;
  590. }
  591. text.erase(selection.begin,selection.end-selection.begin);
  592. cursor_pos-=CLAMP( cursor_pos-selection.begin, 0, selection.end-selection.begin);
  593. if (cursor_pos>=text.length()) {
  594. cursor_pos=text.length();
  595. }
  596. if (window_pos>cursor_pos) {
  597. window_pos=cursor_pos;
  598. }
  599. emit_signal("text_changed",text);
  600. _change_notify("text");
  601. };
  602. selection_clear();
  603. }
  604. void LineEdit::set_max_length(int p_max_length) {
  605. ERR_FAIL_COND(p_max_length<0);
  606. max_length = p_max_length;
  607. set_text(text);
  608. }
  609. int LineEdit::get_max_length() const {
  610. return max_length;
  611. }
  612. void LineEdit::selection_fill_at_cursor() {
  613. int aux;
  614. selection.begin=cursor_pos;
  615. selection.end=selection.cursor_start;
  616. if (selection.end<selection.begin) {
  617. aux=selection.end;
  618. selection.end=selection.begin;
  619. selection.begin=aux;
  620. }
  621. selection.enabled=(selection.begin!=selection.end);
  622. }
  623. void LineEdit::select_all() {
  624. if (!text.length())
  625. return;
  626. selection.begin=0;
  627. selection.end=text.length();
  628. selection.enabled=true;
  629. update();
  630. }
  631. void LineEdit::set_editable(bool p_editable) {
  632. editable=p_editable;
  633. update();
  634. }
  635. bool LineEdit::is_editable() const {
  636. return editable;
  637. }
  638. void LineEdit::set_secret(bool p_secret) {
  639. pass=p_secret;
  640. update();
  641. }
  642. bool LineEdit::is_secret() const {
  643. return pass;
  644. }
  645. void LineEdit::select(int p_from, int p_to) {
  646. if (p_from==0 && p_to==0) {
  647. selection_clear();
  648. return;
  649. }
  650. int len = text.length();
  651. if (p_from<0)
  652. p_from=0;
  653. if (p_from>len)
  654. p_from=len;
  655. if (p_to<0 || p_to>len)
  656. p_to=len;
  657. if (p_from>=p_to)
  658. return;
  659. selection.enabled=true;
  660. selection.begin=p_from;
  661. selection.end=p_to;
  662. selection.creating=false;
  663. selection.doubleclick=false;
  664. update();
  665. }
  666. bool LineEdit::is_text_field() const {
  667. return true;
  668. }
  669. void LineEdit::_bind_methods() {
  670. ObjectTypeDB::bind_method(_MD("set_align", "align"), &LineEdit::set_align);
  671. ObjectTypeDB::bind_method(_MD("get_align"), &LineEdit::get_align);
  672. ObjectTypeDB::bind_method(_MD("_input_event"),&LineEdit::_input_event);
  673. ObjectTypeDB::bind_method(_MD("clear"),&LineEdit::clear);
  674. ObjectTypeDB::bind_method(_MD("select_all"),&LineEdit::select_all);
  675. ObjectTypeDB::bind_method(_MD("set_text","text"),&LineEdit::set_text);
  676. ObjectTypeDB::bind_method(_MD("get_text"),&LineEdit::get_text);
  677. ObjectTypeDB::bind_method(_MD("set_cursor_pos","pos"),&LineEdit::set_cursor_pos);
  678. ObjectTypeDB::bind_method(_MD("get_cursor_pos"),&LineEdit::get_cursor_pos);
  679. ObjectTypeDB::bind_method(_MD("set_max_length","chars"),&LineEdit::set_max_length);
  680. ObjectTypeDB::bind_method(_MD("get_max_length"),&LineEdit::get_max_length);
  681. ObjectTypeDB::bind_method(_MD("append_at_cursor","text"),&LineEdit::append_at_cursor);
  682. ObjectTypeDB::bind_method(_MD("set_editable","enabled"),&LineEdit::set_editable);
  683. ObjectTypeDB::bind_method(_MD("is_editable"),&LineEdit::is_editable);
  684. ObjectTypeDB::bind_method(_MD("set_secret","enabled"),&LineEdit::set_secret);
  685. ObjectTypeDB::bind_method(_MD("is_secret"),&LineEdit::is_secret);
  686. ObjectTypeDB::bind_method(_MD("select","from","to"),&LineEdit::select,DEFVAL(0),DEFVAL(-1));
  687. ADD_SIGNAL( MethodInfo("text_changed", PropertyInfo( Variant::STRING, "text" )) );
  688. ADD_SIGNAL( MethodInfo("text_entered", PropertyInfo( Variant::STRING, "text" )) );
  689. BIND_CONSTANT(ALIGN_LEFT);
  690. BIND_CONSTANT(ALIGN_CENTER);
  691. BIND_CONSTANT(ALIGN_RIGHT);
  692. BIND_CONSTANT(ALIGN_FILL);
  693. ADD_PROPERTY( PropertyInfo( Variant::STRING, "text" ), _SCS("set_text"),_SCS("get_text") );
  694. ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), _SCS("set_align"), _SCS("get_align"));
  695. ADD_PROPERTY( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") );
  696. ADD_PROPERTY( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") );
  697. ADD_PROPERTY( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") );
  698. }
  699. LineEdit::LineEdit() {
  700. align = ALIGN_LEFT;
  701. cached_width = 0;
  702. cursor_pos=0;
  703. window_pos=0;
  704. max_length = 0;
  705. pass=false;
  706. selection_clear();
  707. set_focus_mode( FOCUS_ALL );
  708. editable=true;
  709. set_default_cursor_shape(CURSOR_IBEAM);
  710. set_stop_mouse(true);
  711. }
  712. LineEdit::~LineEdit() {
  713. }