indexing description: "Objects that implements a Button." author: "Beat Steiger and UC Team" date: "$Date$" revision: "$Revision$" class BUTTON inherit EM_DRAWABLE_CONTAINER[EM_DRAWABLE] rename make as make_container, initialize_events as initialize_container_events end UC_SHARED_ITEMS rename width as window_width, height as window_height export {NONE} all undefine copy, is_equal end creation make, make_with_name, make_with_icon feature -- Access font : EM_FONT active_color, normal_color, prelight_color, highlight_color : EM_COLOR border_color : EM_COLOR border_width : INTEGER name : STRING icon : EM_BITMAP min_width, min_height : INTEGER horizontal_margin, vertical_margin : INTEGER button_clicked_event : EM_EVENT_CHANNEL [TUPLE []] mouse_over_button_event : EM_EVENT_CHANNEL [TUPLE []] has_icon, has_name : BOOLEAN corners_rounded : BOOLEAN is_active, change_color_on_toggle_active : BOOLEAN is_prelighted, is_highlighted, is_pressed : BOOLEAN feature -- Status setting set_width (a_width : INTEGER) is -- set the `width' of the button require not_too_small : a_width >= min_width do horizontal_margin := (a_width - min_width) // 2 body.set_size (a_width, body.height) if has_name then drawable_name.set_x (body.x + (body.width - drawable_name.width) // 2) end if has_icon then icon.set_x (body.x + (body.width - icon.width) // 2 + border_width) end end set_height (a_height : INTEGER) is -- set the `height' of the button require not_too_small : a_height >= min_height do vertical_margin := (a_height - min_height) // 2 body.set_size (body.width, a_height) if has_name then drawable_name.set_y (body.y + (body.height - drawable_name.height) // 2) end if has_icon then icon.set_y (body.y + (body.height - icon.height) // 2 + border_width) end end set_vertical_margin (a_vertical_margin : INTEGER) is -- set the `vertical_margin' of the button require not_negative : a_vertical_margin >= 0 do vertical_margin := a_vertical_margin body.set_size (body.width, min_height + 2 * vertical_margin) if has_name then drawable_name.set_y (body.y + (body.height - drawable_name.height) // 2) end if has_icon then icon.set_y (body.y + (body.height - icon.height) // 2 + border_width) end end set_horizontal_margin (a_horizontal_margin : INTEGER) is -- set the `horizontal_margin' of the button require not_negative : a_horizontal_margin >= 0 do horizontal_margin := a_horizontal_margin body.set_size (min_width + 2 * horizontal_margin, body.width) if has_name then drawable_name.set_x (body.x + (body.width - drawable_name.width) // 2) end if has_icon then icon.set_x (body.x + (body.width - icon.width) // 2 + border_width) end end set_name (a_name : STRING) is -- set the `name' of the button require a_name_not_void: a_name /= void do create name.make_from_string(a_name) if not has_name then create drawable_name.make (name, font) drawable_name.set_x_y (body.x + horizontal_margin, body.y + vertical_margin) extend(drawable_name) else drawable_name.set_value (name) end has_name := true min_width := drawable_name.width min_height := drawable_name.height if has_icon then if icon.width > min_width then min_width := icon.width end if icon.height > min_height then min_height := icon.height end end body.set_size (min_width + 2 * horizontal_margin, min_height + 2 * vertical_margin) drawable_name.set_x_y (body.x + (body.width - drawable_name.width) // 2, body.y + (body.height - drawable_name.height) // 2) if has_icon then icon.set_x_y (body.x + (body.width - icon.width) // 2 + border_width, body.y + (body.height - icon.height) // 2 + border_width) end end set_icon (an_icon : EM_BITMAP) is -- set the `icon' of the button require an_icon_not_void: an_icon /= void do icon := an_icon if has_icon then icon_cell.put (icon) else extend (icon) icon_cell := last_cell end min_width := icon.width min_height := icon.height if has_name then if drawable_name.width > min_width then min_width := drawable_name.width end if drawable_name.height > min_height then min_height := drawable_name.height end end body.set_size (min_width + 2 * horizontal_margin, min_height + 2 * vertical_margin) if has_name then drawable_name.set_x_y (body.x + (body.width - drawable_name.width) // 2, body.y + (body.height - drawable_name.height) // 2) end icon.set_x_y (body.x + (body.width - icon.width) // 2 + border_width, body.y + (body.height - icon.height) // 2 + border_width) has_icon := true end set_font (a_font : EM_FONT) is -- set the `font' of the button require a_font_not_void: a_font /= void do font := a_font drawable_name.set_font (font) min_width := drawable_name.width min_height := drawable_name.height if has_icon then if icon.width > min_width then min_width := icon.width end if icon.height > min_height then min_height := icon.height end end body.set_size (min_width + 2 * horizontal_margin, min_height + 2 * vertical_margin) if has_name then drawable_name.set_x_y (body.x + (body.width - drawable_name.width) // 2, body.y + (body.height - drawable_name.height) // 2) end if has_icon then icon.set_x_y (body.x + (body.width - icon.width) // 2 + border_width, body.y + (body.height - icon.height) // 2 + border_width) end end set_normal_color (a_normal_color : EM_COLOR) is -- set the `normal_color' of the button require a_normal_color_not_void: a_normal_color /= void do normal_color := a_normal_color end set_prelight_color (a_prelight_color : EM_COLOR) is -- set the `prelight_color' of the button require a_prelight_color_not_void: a_prelight_color /= void do prelight_color := a_prelight_color end set_highlight_color (a_highlight_color : EM_COLOR) is -- set the `highlight_color' of the button require a_highlight_color_not_void: a_highlight_color /= void do highlight_color := a_highlight_color end set_border_color (a_border_color : EM_COLOR) is -- set the `border_color' of the button-border require a_border_color_not_void: a_border_color /= void do border_color := a_border_color end set_border_width (a_border_width : INTEGER) is -- set the `border_width' to `a_border_width' require not_too_small: a_border_width >= 0 do border_width := a_border_width body.set_line_width (border_width) if corners_rounded then body.set_rounded_corner_radius (2 * border_width) end end set_corners_rounded is -- make the corners round do corners_rounded := true body.set_rounded_corner_radius (2 * border_width) end set_corners_square is -- make the corners square do corners_rounded := false body.set_rounded_corner_radius (0) end toggle_active is -- toggle `active' state of this button. -- right after creation the state is false do is_active := not is_active end toggle_change_color_on_toggle_active is -- toggle `change_color_on_toggle_active' state of this button. -- right after the creation the state is true do change_color_on_toggle_active := not change_color_on_toggle_active end feature {NONE} -- Creation make (an_event_loop : EM_EVENT_LOOP) is -- create a button require an_event_loop_not_void : an_event_loop /= void do event_loop := an_event_loop make_container is_pressed := false is_prelighted := false is_highlighted := false has_name := false has_icon := false set_default_values min_width := 10 min_height := 10 create body.make_from_position_and_size (1, 1, min_width, min_height) body.set_fill_color (normal_color) body.set_line_color (border_color) body.set_line_width (border_width) extend (body) initialize_events end make_with_name (a_name : STRING; an_event_loop : EM_EVENT_LOOP) is -- create a button with the `name' set to `a_name' require a_name_not_void : a_name /= void an_event_loop_not_void : an_event_loop /= void do event_loop := an_event_loop make_container event_loop := an_event_loop is_pressed := false is_prelighted := false is_highlighted := false has_name := true has_icon := false set_default_values create name.make_from_string (a_name) create drawable_name.make (name, font) create body.make_from_position_and_size (1, 1, drawable_name.width, drawable_name.height) body.set_fill_color (normal_color) body.set_line_color (border_color) body.set_line_width (border_width) drawable_name.set_x_y (body.x, body.y) min_width := drawable_name.width min_height := drawable_name.height extend (body) extend (drawable_name) initialize_events end make_with_icon (an_icon : EM_BITMAP; an_event_loop : EM_EVENT_LOOP) is -- create a button with `an_icon' on it require an_icon_not_void : an_icon /= void an_event_loop_not_void : an_event_loop /= void do event_loop := an_event_loop make_container is_pressed := false is_prelighted := false is_highlighted := false has_name := false has_icon := true icon := an_icon set_default_values create body.make_from_position_and_size (1, 1, icon.width, icon.height) body.set_fill_color (normal_color) body.set_line_color (border_color) body.set_line_width (border_width) icon.set_x_y (body.x + (body.width - icon.width) // 2 + border_width, body.y + (body.height - icon.height) // 2 + border_width) min_width := icon.width min_height := icon.height extend (body) extend (icon) icon_cell := last_cell initialize_events end feature {NONE} -- Implementation drawable_name : EM_STRING icon_cell : DS_BILINKABLE [EM_DRAWABLE] body : EM_RECTANGLE event_loop : EM_EVENT_LOOP set_default_values is -- set some values to their default do horizontal_margin := 0 vertical_margin := 0 border_width := 1 active_color := uc_default_button_active_color normal_color := uc_default_button_normal_color prelight_color := uc_default_button_prelight_color highlight_color := uc_default_button_highlight_color border_color := uc_default_button_border_color font := uc_gui_elements_default_font is_active := false change_color_on_toggle_active := true end initialize_events is -- initialize requred mouse_events do create button_clicked_event create mouse_over_button_event event_loop.mouse_button_down_event.subscribe (agent button_clicked) event_loop.mouse_button_up_event.subscribe (agent button_released) event_loop.mouse_motion_event.subscribe (agent button_prelight) end button_clicked (ev : EM_MOUSEBUTTON_EVENT) is -- perform button-clicked actions do if (bounding_box.has (create {EM_VECTOR_2D}.make (ev.x, ev.y)) and ev.is_left_button and not is_pressed) then body.set_fill_color (highlight_color) is_highlighted := true is_pressed := true is_prelighted := false end end button_released (ev : EM_MOUSEBUTTON_EVENT) is -- perform button-released actions do if bounding_box.has (create {EM_VECTOR_2D}.make (ev.x, ev.y)) and ev.is_left_button then if is_active and change_color_on_toggle_active then body.set_fill_color (active_color) else body.set_fill_color (prelight_color) end button_clicked_event.publish ([]) is_highlighted := false is_pressed := false is_prelighted := true else if is_active and change_color_on_toggle_active then body.set_fill_color (active_color) else body.set_fill_color (normal_color) end is_highlighted := false is_pressed := false is_prelighted := false end end button_prelight (ev : EM_MOUSEMOTION_EVENT) is -- perform prelight-button actions when mouse is over button do if not bounding_box.has (create {EM_VECTOR_2D}.make (ev.x, ev.y) + ev.motion) then if is_active and change_color_on_toggle_active then body.set_fill_color (active_color) else body.set_fill_color (normal_color) end is_prelighted := false is_highlighted := false elseif not is_prelighted and not is_pressed then body.set_fill_color (prelight_color) mouse_over_button_event.publish ([]) is_prelighted := true is_highlighted := false elseif not is_highlighted and is_pressed then body.set_fill_color (highlight_color) mouse_over_button_event.publish ([]) is_highlighted := true is_prelighted := false end end end -- class BUTTON