note description: "Generic PREFERENCE." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" deferred class TYPED_PREFERENCE [G] inherit PREFERENCE feature {NONE} --Initialization make (a_manager: PREFERENCE_MANAGER; a_name: STRING; a_value: G) -- New preference with `a_name' and `a_value'. require manager_not_void: a_manager /= Void name_not_void: a_name /= Void name_not_empty: not a_name.is_empty value_not_void: a_value /= Void do manager := a_manager name := a_name internal_value := a_value set_value (a_value) change_actions.extend (agent update_is_auto) ensure has_manager: manager /= Void has_name: name /= Void and not name.is_empty has_change_action: change_actions /= Void end make_from_string_value (a_manager: PREFERENCE_MANAGER; a_name: STRING; a_value: READABLE_STRING_GENERAL) -- Create preference and set value based on string value `a_value'. require manager_not_void: a_manager /= Void name_not_void: a_name /= Void name_not_empty: not a_name.is_empty value_not_void: a_value /= Void value_valid: is_string_value_validated (a_value) do manager := a_manager name := a_name init_value_from_string (a_value) change_actions.extend (agent update_is_auto) ensure has_manager: manager /= Void has_name: name /= Void and not name.is_empty has_change_action: change_actions /= Void end init_value_from_string (a_value: READABLE_STRING_GENERAL) -- Set initial value from String `a_value' require a_value_attached: a_value /= Void do set_value_from_string (a_value) end feature -- Status report is_valid_string_for_selection (s: READABLE_STRING_32): BOOLEAN -- do Result := is_string_value_validated (s) end feature -- Modification set_value (a_value: G) -- Set the value. require value_not_void: a_value /= Void do previous_value := value internal_value := a_value if attached internal_change_actions as l_actions then l_actions.call ([Current]) end if attached internal_typed_change_actions as l_actions then l_actions.call ([internal_value]) end ensure value_set: internal_value = a_value end set_value_to_auto -- Set the value to match that of `auto_preference'. require has_auto_preference: auto_preference /= Void local l_value: like value do -- Implied by precondition `has_auto_preference' check attached auto_preference as l_auto_preference then l_value := l_auto_preference.value check attached l_value end -- implied by invariant `attached_auto_preference_has_value' and precondition `has_auto_preference' set_value (l_value) end ensure value_set: (attached auto_preference as el_auto_preference) and then internal_value = el_auto_preference.value end select_value_from_string (s: READABLE_STRING_32) -- do set_value_from_string (s) end set_auto_preference (a_pref: like Current) -- Use value of `a_pref' for "auto" value for Current. require a_pref_not_void: a_pref /= Void and then a_pref.has_value do auto_preference := a_pref a_pref.change_actions.extend (agent try_to_set_value_to_auto) set_value_to_auto ensure auto_set: auto_preference = a_pref end feature -- Access value: G -- Actual value. do if is_auto then -- implied by `is_auto' and code from `update_is_auto' check attached auto_preference as l_auto_preference then Result := l_auto_preference.value end else Result := internal_value end end has_value: BOOLEAN -- Does Current have a value to use? do Result := value /= Void ensure then Result_implies_value_attached: Result implies value /= Void end typed_change_actions: ACTION_SEQUENCE [TUPLE [G]] -- Actions to be performed when `value' changes after actions of `change_actions'. local l_result: like internal_typed_change_actions do l_result := internal_typed_change_actions if l_result = Void then create l_result internal_typed_change_actions := l_result end Result := l_result ensure Result_attached: Result /= Void end feature {NONE} -- Implementation auto_default_value: G -- Value to use when Current is using auto by default (until real auto is set) deferred end try_to_set_value_to_auto -- Set the value to match that of `auto_preference' (only if `value' was not changed manually). do if attached auto_preference as l_auto_preference then if (attached l_auto_preference.previous_value as l_previous_value) and then internal_value ~ l_previous_value then set_value_to_auto elseif (attached l_auto_preference.value as l_value) and then internal_value ~ l_value then set_value_to_auto end end end update_is_auto -- Update based on value if now the value is auto do is_auto := (attached auto_preference as l_auto_preference) and then internal_value ~ l_auto_preference.value end internal_typed_change_actions: detachable like typed_change_actions -- Storage for `typed_change_actions'. internal_value: G -- Internal value. feature {TYPED_PREFERENCE} -- Implementation previous_value: detachable like value -- Value held before this one, if any. invariant typed_change_actions_not_void: typed_change_actions /= Void attached_auto_preference_has_value: (attached auto_preference as l_auto_preference) implies l_auto_preference.has_value note copyright: "Copyright (c) 1984-2019, 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 -- class TYPED_PREFERENCE