indexing description: "[ Base class for text-fields in the GUI. To use a text-field in a ESDL_SCENE: - First you have to create the TEXT_FIELD object with the make_el creation procedure you need to pass the event_loop of the ESDL_SCENE where the text-field is to be placed in. - To have a blinking cursor you need to start the animation of the curser by using the start_animation procedure of the ESDL_SCENE which holds the text-field - Example: text_field : TEXT_FIELD create text_field.make_el(event_loop) start_animation (text_field) accessible features are : set_font (a_font : ESDL_FONT) -- sets the `font' of the TEXT_FIELD object to `a_color' set_background_color (a_color : ESDL_COLOR) -- sets the `background_color' of the TEXT_FIELD object to `a_color' set_cursor_color (a_color : ESDL_COLOR) -- sets the `cursor_color' of the cursor to `a_color' set_border_color (a_color : ESDL_COLOR) -- sets the `border_color' of the TEXT_FIELD object to `a_color' set_border_width (a_border_width : INTEGER) -- sets the `border_width' of the TEXT_FIELD object to `a_border_width' set_width (a_width : INTEGER) -- sets the `width' of the TEXT_FIELD object to `a_width' set_cursor_blinkrate (a_cursor_blinkrate : INTEGER) -- sets the `cursor_blinkrate' of the cursor to `a_cursor_blinkrate' set_value (a_value : STRING) -- sets the `value' of the TEXT_FIELD object to `a_value' go_to_time (a_time : INTEGER) -- Go to the frame of the `cursor' animation corresponding to `a_time' (in milliseconds). visible attributes are : background_color: ESDL_COLOR -- the color of the background border_color: ESDL_COLOR -- the color of the border border_width: INTEGER -- the width of the border cursor_blinkrate: INTEGER -- the blinking rate of the cursor -- (eg a cursor_blinkrate of 2 means that the cursor blinks twice a second) cursor_color: ESDL_COLOR -- the color of the cursor focused: BOOLEAN -- is the text-field focused? font: ESDL_FONT -- the font in which the text will be displayed value: STRING -- the string-value of the text-field ]" author: "Steiger Beat" date: "Fri 10 June 2005" class TEXT_FIELD inherit UC_SHARED_ITEMS rename width as screen_width, height as screen_height export {NONE} all undefine copy, is_equal, default_create end EM_DRAWABLE_CONTAINER [EM_DRAWABLE] rename make as make_container end creation make feature -- Access background_color : EM_COLOR -- the color of the background cursor_color : EM_COLOR -- the color of the cursor border_color : EM_COLOR -- the color of the border value : STRING -- the string-value of the text-field border_width : INTEGER -- the width of the border font : EM_FONT -- the font in which the text will be displayed focused : BOOLEAN -- is the text-field focused? cursor_blinkrate : INTEGER -- the blinking rate of the cursor -- (eg a cursor_blinkrate of 2 means that the cursor blinks twice a second) return_key_pressed_event : EM_EVENT_CHANNEL [TUPLE[STRING]] set_font (a_font : EM_FONT) is -- sets the `font' of the TEXT_FIELD object to `a_color' require a_font_exists : a_font /= void local font_height : INTEGER do font := a_font font_height := font.height ('Z') --anim.item (1).first.item (2).set_y (font_height) --anim.item (2).first.item (2).set_y (font_height) update_cursor_animation field.set_size (field.width, font_height + border_width + 4) e_string.set_font (font) display_value end set_background_color (a_color : EM_COLOR) is -- sets the `background_color' of the TEXT_FIELD object to `a_color' require a_color_exists : a_color /= void do background_color := a_color field.set_fill_color (background_color) update_cursor_animation --anim.item (1).first.set_line_color (background_color) --cursor.change_animation (anim) end set_cursor_color (a_color : EM_COLOR) is -- sets the `cursor_color' of the cursor to `a_color' require a_color_exists : a_color /= void do cursor_color := a_color update_cursor_animation --anim.item (2).set_line_color (cursor_color) --cursor.change_animation (anim) end set_border_color (a_color : EM_COLOR) is -- sets the `border_color' of the TEXT_FIELD object to `a_color' require a_color_exists : a_color /= void do border_color := a_color field.set_line_color (border_color) end set_border_width (a_border_width : INTEGER) is -- sets the `border_width' of the TEXT_FIELD object to `a_border_width' do border_width := a_border_width field.set_line_width (border_width) field.set_size (field.width, font.height ('Z') + 4 + border_width) cursor.set_x_y (field.x + border_width + 2, field.y + border_width + 2) end set_width (a_width : INTEGER) is -- sets the `width' of the TEXT_FIELD object to `a_width' require width_not_too_small: width >= border_width do field.set_size (a_width - border_width, field.height - border_width) display_value end set_cursor_blinkrate (br : INTEGER) is -- sets the `cursor_blinkrate' of the cursor to `a_cursor_blinkrate' require blinkrate_not_zero : br /= 0 do cursor_blinkrate := br cursor.set_frame_rate (br) end set_value (v : STRING) is -- sets the `value' of the TEXT_FIELD object to `a_value' require v_not_void : v /= void do value := v display_value end start_cursor_animation() is -- make cursor start blinking do cursor.start end stop_cursor_animation() is -- make cursor stop blinking do cursor.stop end feature {NONE} -- Initialisation make (an_event_loop : EM_EVENT_LOOP) is -- Create a textfield with default values require an_event_loop_not_void : an_event_loop /= void local cursor_line, cursor_blank : EM_POLYLINE cursor_start_end : ARRAY[EM_VECTOR_2D] do event_loop := an_event_loop -- call inherited make from ESDL_DRAWABLE_CONTAINER make_container -- set font to uc_gui_elements_default_font (which comes from UC_SHARED_ITEMS) font := uc_gui_elements_default_font -- set default border_width border_width := 1 -- set default color background_color := uc_light_color create border_color.make_black -- create field with default values create field.make_from_coordinates (1, 1, 300, (font.height ('Z') + border_width + 4).to_double) field.set_line_width (border_width) field.set_line_color (border_color) field.set_fill_color (background_color) extend (field) -- create array of VECTOR_2D to define cursor polyline (ESDL_POLYLINE) create cursor_start_end.make (1, 2) cursor_start_end.put (create {EM_VECTOR_2D}.make (1,1), 1) cursor_start_end.put (create {EM_VECTOR_2D}.make (1,font.height ('Z')), 2) -- set default cursor color create cursor_color.make_black -- create array of ESDL_POLYLINE to hold blinking cursor animation --create anim.make (1, 2) -- create first frame of blinking cursor animation create cursor_blank.make_from_array (cursor_start_end) cursor_blank.set_line_color (background_color) create cursor.make_from_drawable (cursor_blank, 250, 0, 0) --anim.put (create {EM_PAIR[EM_POLYLINE, INTEGER]}.make (cursor_blank, 1), 1) -- create second frame of blinking cursor animation create cursor_line.make_from_array (cursor_start_end) cursor_line.set_line_color (cursor_color) cursor.extend_drawable (cursor_line, 250) --anim.put (create {EM_PAIR[EM_POLYLINE, INTEGER]}.make (cursor_line, 1), 2) -- create animated sprite from animation and set its framerate --create cursor.make_from_animation (create {EM_ANIMATION}.make_from_array (anim), 0, 0) cursor_blinkrate := 2 --cursor.set_frame_rate (cursor_blinkrate) cursor.set_do_loop (true) -- stop animation while the text-field is not focused cursor.stop create value.make_empty create e_string.make (value, font) e_string.set_x_y (field.x + border_width + 1, field.y + border_width + 1) extend (e_string) -- position cursor at the right place cursor.set_x_y (e_string.x + e_string.width, e_string.y) extend (cursor) focused := false event_loop.mouse_button_down_event.subscribe (agent set_focused) event_loop.mouse_button_down_event.subscribe (agent set_unfocused) create return_key_pressed_event create keyboard.make_snapshot keyboard.enable_repeating_key_down_events (500, 100) keyboard.enable_unicode_characters end feature {NONE} -- Implementation field : EM_RECTANGLE cursor : EM_SPRITE --anim : ARRAY[EM_PAIR[EM_POLYLINE,INTEGER]] e_string : EM_STRING event_loop : EM_EVENT_LOOP keyboard : EM_KEYBOARD subscribed_procedures : LINKED_LIST[PROCEDURE[ANY,TUPLE[EM_KEYBOARD_EVENT]]] is -- linked-list to hold agents which were subscribed to the -- key_down_event of the `event_loop' once Result := create {LINKED_LIST[PROCEDURE[ANY,TUPLE[EM_KEYBOARD_EVENT]]]}.make end set_focused (ev : EM_MOUSEBUTTON_EVENT) is -- set the focus on this textfield if left-mouse-button -- is clicked on it do if ev.is_left_button and not focused then focused := true -- start blinking-animation of the cursor cursor.start -- unsubscribe other agents while focus is on this text_field from event_loop.key_down_event.subscriptions.start until event_loop.key_down_event.subscriptions.after loop subscribed_procedures.extend (event_loop.key_down_event.subscriptions.item_for_iteration) event_loop.key_down_event.unsubscribe (event_loop.key_down_event.subscriptions.item_for_iteration) end -- subscribe agent of this text_field to get the keyboard_events of the event_loop event_loop.key_down_event.subscribe (agent get_key) end end set_unfocused (ev : EM_MOUSEBUTTON_EVENT) is -- set the focus away from this textfield if left-mouse-button -- is clickt somewhere but on this textfield. do if focused and not bounding_box.has (ev.proportional_position) then focused := false -- stop blinking-animation of the cursor while this text_field is not focused cursor.stop -- restore subscription of the agents which were unsubscribed -- when the focus was set on this text_field from subscribed_procedures.start until subscribed_procedures.after loop event_loop.key_down_event.subscribe (subscribed_procedures.item) subscribed_procedures.remove end -- unsubscribe key_down_event agent of this text_field while it is not focused. event_loop.key_down_event.unsubscribe (agent get_key) end end get_key (ev : EM_KEYBOARD_EVENT) is -- Capture pressed keys local key : CHARACTER do if focused then key := ev.unicode_character if ev.is_alt_right_pressed then if (ev.key = keyboard.sdlk_backslash) then value.extend ('\') end elseif ev.is_shift_pressed then if (key.is_alpha) then value.extend (key.upper) elseif (ev.key = keyboard.sdlk_1) then value.extend('+') elseif (ev.key = keyboard.sdlk_2) then value.extend('"') elseif (ev.key = keyboard.sdlk_3) then value.extend('*') elseif (ev.key = keyboard.sdlk_4) then value.extend('ç') elseif (ev.key = keyboard.sdlk_5) then value.extend('%%') elseif (ev.key = keyboard.sdlk_6) then value.extend('&') elseif (ev.key = keyboard.sdlk_7) then value.extend('/') elseif (ev.key = keyboard.sdlk_8) then value.extend('(') elseif (ev.key = keyboard.sdlk_9) then value.extend(')') elseif (ev.key = keyboard.sdlk_0) then value.extend('=') elseif (ev.key = keyboard.sdlk_period) then value.extend(':') elseif (ev.key = keyboard.sdlk_underscore) then value.extend('_') end elseif ev.key = keyboard.sdlk_return then return_key_pressed_event.publish([value]) elseif ev.key = keyboard.sdlk_backspace and not value.is_empty then value.remove_tail (1) elseif not is_modifier_key (ev.key) and ev.key /= keyboard.sdlk_backspace then value.extend (key) end display_value end end display_value is -- generate the `e_string' which will be displayed in the textfield local v : STRING do create v.make_from_string (value) from e_string.set_value (v) until e_string.width < (field.width - border_width - 3) loop v.remove_head (1) e_string.set_value (v) end --cursor.set_x (e_string.x + e_string.width) cursor.set_x (e_string.x + (e_string.width/2).truncated_to_integer) end is_modifier_key (a_key_code : INTEGER) : BOOLEAN is -- returns true if `a_key_code' denotes a modifier_key (alt, ctrl, etc.) do Result := a_key_code = keyboard.sdlk_ralt or a_key_code = keyboard.sdlk_rctrl or a_key_code = keyboard.sdlk_rshift or a_key_code = keyboard.sdlk_rmeta or a_key_code = keyboard.sdlk_lalt or a_key_code = keyboard.sdlk_lctrl or a_key_code = keyboard.sdlk_lshift or a_key_code = keyboard.sdlk_lmeta or a_key_code = keyboard.sdlk_capslock or a_key_code = keyboard.sdlk_numlock or a_key_code = keyboard.sdlk_mode end update_cursor_animation () is -- update cursor if font, background_color or cursor_color is changed local cursor_line, cursor_blank : EM_POLYLINE cursor_start_end : ARRAY[EM_VECTOR_2D] do -- create array of VECTOR_2D to define cursor polyline (ESDL_POLYLINE) create cursor_start_end.make (1, 2) cursor_start_end.put (create {EM_VECTOR_2D}.make (1,1), 1) cursor_start_end.put (create {EM_VECTOR_2D}.make (1,font.height ('Z')), 2) -- create first frame of blinking cursor animation create cursor_blank.make_from_array (cursor_start_end) cursor_blank.set_line_color (background_color) create cursor.make_from_drawable (cursor_blank, 250, 0, 0) -- create second frame of blinking cursor animation create cursor_line.make_from_array (cursor_start_end) cursor_line.set_line_color (cursor_color) cursor.extend_drawable (cursor_line, 250) cursor.set_frame_rate (cursor_blinkrate) cursor.set_do_loop (true) -- stop animation while the text-field is not focused if focused then cursor.start else cursor.stop end end end -- class TEXT_FIELD