indexing description: "[ Button objects are made of a special frame containing a text and/or an image. Buttons are clickable and can change their visual style according to mouse events (clicking, hoovering). ]" author: "Ralph Wiedemeier, ralphw@student.ethz.ch" date: "$Date$" revision: "$Revision$" class GUI_SPECIAL_BUTTON inherit GUI_SPECIAL_FRAME redefine draw end GUI_SHARED export {NONE} all undefine out end EM_SHARED_BITMAP_FACTORY export {NONE} all undefine out end create make_with_text, make_with_image, make_with_text_and_image feature -- Initialization make_with_text (a_text: STRING; a_font: GUI_PROPORTIONAL_FONT) is -- create button with text representation require text_valid: a_text /= Void font_valid: a_font /= Void do make_with_text_and_image (a_text, a_font, Void) end make_with_image (a_path: STRING) is -- create button with image representation do make_with_text_and_image ( Void, Void, a_path) end make_with_text_and_image (a_text: STRING; a_font: GUI_PROPORTIONAL_FONT; a_path: STRING) is -- create button with text and image representation do make_from_position_and_size (0, 0, 1, 1) set_text (a_text) set_font (a_font) set_font_size (1.0) image_path := a_path set_border_thickness (1) set_layout_horizontal set_padding (2) set_visible load_texture (image_path) if font /= Void then font.set_gl_scaling (font_size) end end feature -- Appearance set_layout_horizontal is -- image and text are aligned horizontally -- --------------- -- | IMAGE TEXT | -- --------------- do layout_mode := layout_mode_horizontal end set_layout_vertical is -- image and text are aligned vertically -- --------- -- | IMAGE | -- | | -- | TEXT | -- --------- do layout_mode := layout_mode_vertical end set_text (a_text: STRING) is -- set the text displayed with the button do if a_text /= Void then text := a_text.twin text.replace_substring_all ("|", "") else text := a_text end end text: STRING set_font (a_font: GUI_PROPORTIONAL_FONT) is -- set the font used for drawing the button text do font := a_font end font: GUI_PROPORTIONAL_FONT -- access to the font used for drawing the button text set_font_size (a_size: DOUBLE) is -- set font size do font_size := a_size end set_font_color_normal (a_color: EM_COLOR) is -- set normal text color do font_color_normal := a_color font_color := font_color_normal end set_font_color_hoover (a_color: EM_COLOR) is -- set text color when hoovered do font_color_hoover := a_color end set_font_color_clicked (a_color: EM_COLOR) is -- set text color when clicked do font_color_clicked := a_color end set_padding (a_value: INTEGER) is -- set left, right, top and bottom padding do padding_horizontal := a_value padding_vertical := a_value end set_padding_horizontal (a_value: INTEGER) is -- set left and right padding do padding_horizontal := a_value end set_padding_vertical (a_value: INTEGER) is -- set top and bottom padding do padding_vertical := a_value end padding_horizontal: INTEGER padding_vertical: INTEGER -- padding values for left, right, top and bottom enable_multiline is -- Enable multiline text do multiline := True end disable_multiline is -- Disable multiline text do multiline := False end multiline: BOOLEAN -- Should text of button displayed with multiple lines? feature -- Operation auto_resize_width is -- auto resize width of button according to content local tw, min_width: INTEGER do if text /= Void then font.set_gl_scaling (font_size) tw := (font.text_width (text) * 1.03).truncated_to_integer + 1 end if layout_mode = layout_mode_horizontal then min_width := image_width + tw + 2 * padding_horizontal if tw > 0 and then image_width > 0 then min_width := min_width + padding_horizontal end elseif layout_mode = layout_mode_vertical then if tw > image_width then min_width := tw + 2 * padding_horizontal else min_width := image_width + 2 * padding_horizontal end end set_width (min_width) end auto_resize_height is -- auto resize height of button according to content local tw, th, min_height: INTEGER do if text /= Void then font.set_gl_scaling (font_size) if multiline then tw := width - 2 * padding_horizontal if image_width > 0 then tw := tw - image_width - padding_horizontal end th := (font.text_height (text, tw)).truncated_to_integer + 1 else th := (font.line_height * 0.8).truncated_to_integer + 1 end end if layout_mode = layout_mode_horizontal then if th > image_height then min_height := th + 2 * padding_vertical else min_height := image_height + 2 * padding_vertical end elseif layout_mode = layout_mode_vertical then min_height := image_height + th + 2 * padding_vertical if th > 0 and then image_height > 0 then min_height := min_height + padding_vertical end end height := min_height end draw (a_surface: EM_VIDEO_SURFACE) is -- draw button to 'a_surface' local p_x, p_y, p_width, p_height: INTEGER image_x, image_y, offset: INTEGER text_height: INTEGER text_area: EM_RECT color: EM_COLOR do if is_visible then Precursor {GUI_SPECIAL_FRAME} (a_surface) p_x := x + padding_horizontal p_y := y + padding_vertical p_width := width - 2 * padding_horizontal p_height := height - 2 * padding_vertical if p_width < 1 then p_width := 1 end if p_height < 1 then p_height := 1 end if layout_mode = layout_mode_vertical then image_x := p_x + (p_width - image_width) // 2 image_y := p_y if text /= Void then font.set_gl_scaling (font_size) font.set_alignment_centered if multiline then text_height := (font.text_height (text, p_width)).truncated_to_integer else text_height := font.line_height.truncated_to_integer + 1 end create text_area.make (p_x, p_y + p_height - text_height, p_width, text_height + 1) end elseif layout_mode = layout_mode_horizontal then image_x := p_x image_y := p_y + (p_height - image_height) // 2 if text /= Void then font.set_gl_scaling (font_size) font.set_alignment_left if image_valid then offset := image_width + padding_horizontal else offset := 0 end if multiline then text_height := (font.text_height (text, p_width - offset)).truncated_to_integer + 1 else text_height := font.line_height.truncated_to_integer + 1 end create text_area.make (p_x + offset, p_y + (p_height - text_height) // 2, p_width - offset, text_height) end end if image_valid then -- macro_bind_texture_antialiased_replace (image_id) macro_bind_texture_antialiased_replace (image) emgl_begin (EM_gl_quads) emgl_tex_coord2d (0.0, 0.0) emgl_vertex2i (image_x, image_y) emgl_tex_coord2d (1.0, 0.0) emgl_vertex2i (image_x + image_width, image_y) emgl_tex_coord2d (1.0, 1.0) emgl_vertex2i (image_x + image_width, image_y + image_height) emgl_tex_coord2d (0.0, 1.0) emgl_vertex2i (image_x, image_y + image_height) emgl_end image.unbind end if text /= Void then if not is_enabled then color := font.text_color font.set_text_color (gui_constants.color_button_text_disabled) end font.draw_text_multiline (text, text_area, a_surface) if not is_enabled then font.set_text_color (color) end end end end dispose_texture_memory is -- Free memory of used textures do -- if image_id > 0 then if image /= void then -- macro_free_texture (image_id) macro_free_texture (image) end end feature {NONE} -- Implementation load_texture (a_path: STRING) is -- load image file and create openGL texture do if a_path /= Void then bitmap_factory.create_bitmap_from_image (a_path) if bitmap_factory.last_bitmap = Void then gui.application.throw_unrecoverable_exception ("File not found error: " + a_path) else -- CHANGES -- image_id := bitmap_factory.last_bitmap.gl_texture_mipmap -- image_id := bitmap_factory.last_bitmap.texture.id create image.make_mipmap_from_surface_stretched ( bitmap_factory.last_bitmap ) --bitmap_factory.last_bitmap.texture.do_not_free_texture -- bitmap_factory.last_bitmap.texture.save image_width := bitmap_factory.last_bitmap.width image_height := bitmap_factory.last_bitmap.height image_valid := True end else image_width := 0 image_height := 0 image_valid := False end end font_size: DOUBLE -- size of font font_color: EM_COLOR font_color_normal: EM_COLOR font_color_hoover: EM_COLOR font_color_clicked: EM_COLOR image_path: STRING -- path to the button's image file -- image_id: INTEGER image: EM3D_TEXTURE_2D[ EMGL_FORMAT_RGBA ] -- texture ID containing the button image image_width: INTEGER image_height: INTEGER image_valid: BOOLEAN -- is there a valid image loaded? layout_mode: INTEGER layout_mode_horizontal: INTEGER is 1 layout_mode_vertical: INTEGER is 2 end -- class GUI_SPECIAL_BUTTON