note description: "Eiffel Vision fixed. MS Windows implementation." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class EV_FIXED_IMP inherit EV_FIXED_I redefine interface, extend_with_position_and_size, set_item_position_and_size end EV_WIDGET_LIST_IMP redefine interface, on_size, insert_i_th, notify_change, make end EV_WEL_CONTROL_CONTAINER_IMP rename make as ev_wel_control_container_make undefine on_wm_dropfiles, background_brush_gdip redefine top_level_window_imp, on_erase_background, default_style end WEL_RGN_CONSTANTS export {NONE} all end create make feature -- Initialization old_make (an_interface: attached like interface) -- Create the fixed container. do assign_interface (an_interface) end make do ev_wel_control_container_make create ev_children.make (2) Precursor end feature -- Status setting extend_with_position_and_size (a_widget: EV_WIDGET; a_x, a_y, a_width, a_height: INTEGER) -- Add `a_widget' to `Current' with a position of `a_x', a_y' and a dimension of `a_width' and `a_height'. local v_imp: detachable EV_WIDGET_IMP wel_win: detachable WEL_WINDOW do -- Add `a_widget' to `Current'. a_widget.implementation.on_parented v_imp ?= a_widget.implementation check v_imp /= Void then end ev_children.go_i_th (count + 1) ev_children.put_left (v_imp) wel_win ?= Current v_imp.wel_set_parent (wel_win) v_imp.set_top_level_window_imp (top_level_window_imp) new_item_actions.call ([a_widget]) if index = count then index := index + 1 end -- Set size and position. v_imp.ev_move (a_x, a_y) v_imp.parent_ask_resize (a_width, a_height) v_imp.invalidate notify_change (nc_minsize, Current, False) end set_item_position_and_size (a_widget: EV_WIDGET; a_x, a_y, a_width, a_height: INTEGER) -- Assign `a_widget' with a position of `a_x' and a_y', and a dimension of `a_width' and `a_height'. local wel_win: detachable EV_WIDGET_IMP do wel_win ?= a_widget.implementation check wel_win /= Void then end wel_win.ev_move (a_x, a_y) wel_win.parent_ask_resize (a_width, a_height) wel_win.invalidate notify_change (Nc_minsize, wel_win, False) end set_item_position (a_widget: EV_WIDGET; an_x, a_y: INTEGER) -- Set `a_widget.x_position' to `an_x'. -- Set `a_widget.y_position' to `a_y'. local wel_win: detachable EV_WIDGET_IMP do application_implementation.erase_rubber_band wel_win ?= a_widget.implementation check wel_win_not_void: wel_win /= Void then end wel_win.ev_move (an_x, a_y) wel_win.invalidate notify_change (Nc_minsize, wel_win, False) end set_item_size (a_widget: EV_WIDGET; a_width, a_height: INTEGER) -- Set `a_widget.width' to `a_width'. -- Set `a_widget.height' to `a_height'. local wel_win: detachable EV_WIDGET_IMP do wel_win ?= a_widget.implementation check wel_win_not_void: wel_win /= Void then end wel_win.parent_ask_resize (a_width, a_height) notify_change (Nc_minsize, wel_win, False) end feature {EV_ANY_I} -- Implementation ev_children: ARRAYED_LIST [EV_WIDGET_IMP] -- Child widgets in z-order starting with farthest away. top_level_window_imp: detachable EV_WINDOW_IMP -- Top level window that contains the current widget. set_top_level_window_imp (a_window: detachable EV_WINDOW_IMP) -- Assign `a_window' to `top_level_window_imp'. do top_level_window_imp := a_window from ev_children.start until ev_children.after loop ev_children.item.set_top_level_window_imp (a_window) ev_children.forth end end feature {EV_ANY, EV_ANY_I} -- Implementation interface: detachable EV_FIXED note option: stable attribute end -- Provides a common user interface to platform dependent -- functionality implemented by `Current' feature {NONE} -- Implementation compute_minimum_width (a_is_size_forced: BOOLEAN) -- Compute both to avoid duplicate code. local v_imp: EV_WIDGET_IMP new_min_width: INTEGER cur: INTEGER do if not child_cell.is_user_min_width_set then cur := ev_children.index from ev_children.start until ev_children.after loop v_imp := ev_children.item new_min_width := new_min_width.max (v_imp.x_position + v_imp.width) ev_children.forth end ev_children.go_i_th (cur) ev_set_minimum_width (new_min_width, a_is_size_forced) end end compute_minimum_height (a_is_size_forced: BOOLEAN) -- Compute both to avoid duplicate code. local v_imp: EV_WIDGET_IMP new_min_height: INTEGER cur: INTEGER do if not child_cell.is_user_min_height_set then cur := ev_children.index from ev_children.start until ev_children.after loop v_imp := ev_children.item new_min_height := new_min_height.max (v_imp.y_position + v_imp.height) ev_children.forth end ev_children.go_i_th (cur) ev_set_minimum_height (new_min_height, a_is_size_forced) end end compute_minimum_size (a_is_size_forced: BOOLEAN) -- Recompute the minimum size of the object. local v_imp: EV_WIDGET_IMP new_min_width, new_min_height: INTEGER cur: INTEGER do if not child_cell.is_user_min_height_set or else not child_cell.is_user_min_width_set then cur := ev_children.index from ev_children.start until ev_children.after loop v_imp := ev_children.item new_min_width := new_min_width.max (v_imp.x_position + v_imp.width) new_min_height := new_min_height.max (v_imp.y_position + v_imp.height) ev_children.forth end ev_children.go_i_th (cur) ev_set_minimum_size (new_min_width, new_min_height, a_is_size_forced) end end insert_i_th (v: attached like item; i: INTEGER) -- Insert `v' at position `i'. do Precursor {EV_WIDGET_LIST_IMP} (v, i) if child_cell.is_user_min_height_set or else child_cell.is_user_min_width_set then set_item_size (v, v.minimum_width, v.minimum_height) end end notify_change (type: INTEGER; child: detachable EV_ANY_I; a_is_size_forced: BOOLEAN) -- Notify the current widget that the change identify by -- type have been done. For types, see `internal_changes' -- in class EV_SIZEABLE_IMP. If the container is shown, -- we integrate the changes immediatly, otherwise, we postpone -- them. -- Use the constants defined in EV_SIZEABLE_IMP do if not child_cell.is_user_min_height_set or else not child_cell.is_user_min_width_set then Precursor {EV_WIDGET_LIST_IMP} (type, child, a_is_size_forced) elseif attached {EV_SIZEABLE_IMP} child as l_child then l_child.parent_ask_resize (l_child.child_cell.width, l_child.child_cell.height) end end feature {NONE} -- WEL Implementation on_size (size_type: INTEGER; a_width, a_height: INTEGER) -- Move the window to `a_x', `a_y' position and -- resize it with `a_width', `a_height'. -- And we reajust size of all children. local v_imp: EV_WIDGET_IMP cur: INTEGER do cur := ev_children.index from ev_children.start until ev_children.after loop v_imp := ev_children.item v_imp.set_move_and_size (v_imp.x_position, v_imp.y_position, v_imp.width, v_imp.height) ev_children.forth end ev_children.go_i_th (cur) Precursor {EV_WIDGET_LIST_IMP} (size_type, a_width, a_height) end ev_apply_new_size (a_x, a_y, a_width, a_height: INTEGER; repaint: BOOLEAN) -- Move the window to `a_x', `a_y' position and -- resize it with `a_width', `a_height'. -- And we reajust size of all children. local v_imp: EV_WIDGET_IMP cur: INTEGER do ev_move_and_resize (a_x, a_y, a_width, a_height, repaint) cur := ev_children.index from ev_children.start until ev_children.after loop v_imp := ev_children.item v_imp.ev_apply_new_size (v_imp.x_position, v_imp.y_position, v_imp.width, v_imp.height, repaint) ev_children.forth end ev_children.go_i_th (cur) end on_erase_background (paint_dc: WEL_PAINT_DC; invalid_rect: WEL_RECT) local main_region: WEL_REGION tmp_region, new_region: WEL_REGION original_index: INTEGER temp_children: ARRAYED_LIST [EV_WIDGET_IMP] current_child: EV_WIDGET_IMP bk_brush: detachable WEL_BRUSH l_x, l_y, l_width, l_height: INTEGER l_gdip_brush: detachable WEL_GDIP_BRUSH l_gdip_graphics: WEL_GDIP_GRAPHICS l_region: WEL_RECT l_background_color: WEL_GDIP_COLOR do -- Disable default windows processing which would re-draw the -- complete background of `Current'. This is not nice behaviour -- as some widgets such as EV_LIST_IMP re-draw themselves as -- required and will be hidden by `Current' if they are inside. -- This will solve that problem. disable_default_processing set_message_return_value (to_lresult (1)) -- Quick access to `ev_children'. temp_children := ev_children -- Retrieve original index of `ev_children'. original_index := temp_children.index -- Create the region as the invalid area of `Current' that -- needs to be redrawn. create main_region.make_rect_indirect (invalid_rect) -- We now need to subtract the area of every child held in -- `Current' from the invalid area. from temp_children.start until temp_children.off loop current_child := temp_children.item -- Create a temporary region the size of the current child. if current_child.is_show_requested then create tmp_region.make_rect (current_child.x_position, current_child.y_position, current_child.x_position + current_child.width, current_child.y_position + current_child.height) -- Subtract this temporary region from the `main_region' -- and store in `main_region'. new_region := main_region.combine (tmp_region, Rgn_diff) tmp_region.delete main_region.delete main_region := new_region end -- Point to the next child if there is one. temp_children.forth end -- Fill the remaining region, `main_region'. l_gdip_brush := background_brush_gdip if l_gdip_brush /= Void then -- GDI+ is available l_region := main_region.get_region_box l_x := l_region.x l_y := l_region.y l_width := l_region.width l_height := l_region.height create l_gdip_graphics.make_from_dc (paint_dc) create l_background_color.make_from_argb (255, background_color.red_8_bit, background_color.green_8_bit, background_color.blue_8_bit) l_gdip_graphics.clear (l_background_color) l_gdip_graphics.fill_rectangle (l_gdip_brush, create {WEL_GDIP_RECT}.make_with_size (l_x, l_y, l_width, l_height)) l_gdip_graphics.destroy_item else -- Using GDI instead of GDI+ bk_brush := background_brush check bk_brush /= Void then end paint_dc.fill_region (main_region, bk_brush) -- Clean up GDI objects bk_brush.delete end -- Restore our index in the children. temp_children.go_i_th (original_index) main_region.delete end is_child (a_child: EV_WIDGET_IMP): BOOLEAN -- Is `a_child' currently contained in `Current'. do Result := a_child = item.implementation end default_style: INTEGER -- Default style used by windows at creation. do Result := Ws_child | Ws_visible | Ws_clipsiblings end note copyright: "Copyright (c) 1984-2018, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end