Difference between revisions of "Using Dialog Prompts (Advanced)"

m
m
Line 1: Line 1:
[[Category:Extending_EiffelStudio]]
+
[[Category:Extending EiffelStudio]]
 
+
{{UnderConstruction}}
There are two methods of displaying dialog prompts inside [[:Category:EiffelStudio|EiffelStudio]]. Firstly there is the simple and effective approach, which requires very little coding but offers very little in the way of customization. The second approach can be simple, but by not means as simple as the first, and can offer a great deal of customization. The information in this page pertains for the latter approach. To use the former please see [[Using Dialog Prompts (Basic)]].
+
Showing dialog prompts displaying the same messages over and over again can be annoying for most end-user. Take the security or alert notifications in your browser, most of us just turn them off after we have read them after they have been shown for the first time, we even discard them without reading them in some cases. [[:Category:EiffelStudio|EiffelStudio]] another product full of cases where "discardable" dialogs prompts are a necessity, without them we could hinder and annoy end-users.
  
 
== Getting Started ==
 
== Getting Started ==
If you have ended up here then you are either curious or have decided that you want to use some of the extended features of the [[:Category:EiffelStudio|EiffelStudio]] [[Tool Dialog Prompts]]. The page is given the title "Advanced" and there are more advanced topics here but using the deep level of customization features is for everyone as it's simple enough to use.
+
 
 +
You should already be familiar with the topics detailed in [[Using Dialog Prompts (Advanced)]] as the information there applies to discardable dialogs prompts also.
  
 
Before continuing you may also want to check out the following pages:
 
Before continuing you may also want to check out the following pages:
Line 12: Line 13:
 
* [[Dialog Prompt Messages and Formatting]]
 
* [[Dialog Prompt Messages and Formatting]]
  
== Introducing the Dialog Prompt Classes ==
+
== The Need For Discardable Dialog Prompts ==
  
There are, as of [[:Category:EiffelStudio|EiffelStudio]] [[EiffelStudio_6.1_Releases|6.1]], four common dialog prompt classes for use which are somewhat self-explanatory.
+
One such example of a need for a discardable dialog is performing a finalization compilation. Finalization asks the end-user if they want to discard or keep assertions. For the most part (95%-99% of cases) assertions are always discarded. It makes sense to offer a way to suppress the dialog in the future and perform a default, commonly used, pre-defined action (discarding assertions in this case) when performing a finalization in the future.
  
* [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_error_prompt.e ES_ERROR_PROMPT]: Used to display a error.
+
[[Image:Dialog prompts example discard assertions.png|Dialog shown when finalizing an Eiffel project]]
* [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_warning_prompt.e ES_WARNING_PROMPT]: Used to display a warning
+
* [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_information_prompt.e ES_INFORMATION_PROMPT]: Used to display a piece of informative text.
+
* [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_question_prompt.e ES_QUESTION_PROMPT]: Used to ask the user a yes/no question.
+
  
All dialog prompt classes are based on an abstract implementation [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_prompt.e ES_PROMPT].
 
  
{{Note| There is a running convention in [[:Category:EiffelStudio|EiffelStudio]] (for classes prefixed with <eiffel>ES_</eiffel>) whereby all dialog prompts end in <eiffel>_PROMPT</eiffel>. From this you can determine if there are any specialized dialog prompts available for you to use, as the base implementation in [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_prompt.e ES_PROMPT] is customizable. You can also use the code browsing tools to check for all descendents of [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_prompt.e ES_PROMPT].}}
+
== Introducing Discardable Dialog Prompt Classes ==
  
Each dialog prompt class provide two or more creation routines; <eiffel>make</eiffel> and <eiffel>make_standard</eiffel>. Some prompt classes also have an addition creation routine, <eiffel>make_standard_with_cancel</eiffel>, to augment the standard button set with a '''Cancel''' button. The creation routine <eiffel>make</eiffel> offers the most control but requires more information to create the dialog and some understanding of the concpt of a [[Dialog Buttons Sets]]. The <eiffel>make_standard</eiffel> creation routines are simpler and only require a dialog prompt message, just like the basic dialog prompt usage detailed in [[Using Dialog Prompts (Basic)]].
+
There are, as of [[:Category:EiffelStudio|EiffelStudio]] [[EiffelStudio_6.1_Releases|6.1]], three common discardable dialog prompt classes for use which are somewhat self-explanatory.
  
== Dialog Prompt Buttons ==
+
* [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_discardable_warning_prompt.e ES_DISCARDABLE_WARNING_PROMPT]: Used to display a discardable warning
The <eiffel>make_standard</eiffel> creation routines initialize the dialog prompt using a standard set of dialog buttons in the order dictated by the executing platform. The standard dialog buttons are as follows (ordering representative on Windows):
+
* [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_discardable_information_prompt.e ES_DISCARDABLE_INFORMATION_PROMPT]: Used to display a piece of informative text that can be discarded in the future.
 +
* [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_discardable_question_prompt.e ES_DISCARDABLE_QUESTION_PROMPT]: Used to ask the user a discardable yes/no question.
  
* Error: '''Ok'''
+
All dialog prompt classes are based on an abstract implementation [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_discardable_prompt.e ES_DISCARDABLE_PROMPT], which in turn implements parts of [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_prompt.e ES_PROMPT].
* Warning: '''Ok'''
+
* Information: '''Ok'''
+
* Question: '''Yes'''|'''No'''
+
  
As mentioned, some of the prompts come with a third creation routine, <eiffel>make_standard_with_cancel</eiffel>, augmenting the existing dialog prompt's button set with a '''Cancel''' button. The only dialog prompt not to have a third creation routine is the Error prompt as an error is usual considered an exception case and general there is no recourse action. The standard dialog buttons "with cancel" are as follows (ordering representative on Windows):
+
{{Note|There is no error variant of a discardable dialog prompt because errors are considered too important to discard. If an error occurs it should always been shown to the user!}}
  
* Warning: '''Ok'''|'''Cancel'''
+
== Using Discardable Dialog Prompts ==
* Information: '''Ok'''|'''Cancel'''
+
* Question: '''Yes'''|'''No'''|'''Cancel'''
+
  
=== Button Sets ===
+
There are only a couple of few pieces of information required when using a discardable dialog prompt over the non-discardable variant.  
Most dialog prompts have a standard set of buttons and being so [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/es_dialog_buttons.e ES_DIALOG_BUTTONS] provides access to the well-known and commonly used button sets, such as '''Ok'''|'''Cancel''', '''Yes'''|'''No''' and even '''Abort'''|'''Retry'''|'''Ignore'''.
+
  
{{Note|All dialog prompts inherit [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/shared/es_shared_dialog_buttons.e ES_SHARED_DIALOG_BUTTONS] through the base dialog implementation [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/es_dialog.e ES_DIALOG] (see [[Tool Dialogs]] for more information on [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/es_dialog.e ES_DIALOG] and dialog button sets.)}}
+
=== State Preference Persistence ===
  
For information of button set and creating your own button set see [[Dialog Buttons Sets]].
+
Most importantly is the configuration preference that the discardable states is stored. Upon creation of a discardable dialog prompt you will need to supply the full name of a preference, which is typically in the form ''interface.dialogs.confirm_xxxx'' where ''xxxx'' represents the name of the dialog.
  
=== Setting Default Buttons ===
+
{{Note|For dialog preferences and preference names examine the class [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/preference_tool/parameters/eb_dialogs_data.e EB_DIALOGS_DATA]. For a general overview of adding preferences to [[:Category:EiffelStudio|EiffelStudio]] see [[Adding EiffelStudio Preferences]].}}
  
==== Default Active Button ====
+
Not only does the preference record the state of a user-opted discard but it also permits the user to reactive the dialog prompt via the preferences tool.
Every prompt has a default active button, also known as the "Default Button". This is the button that will have the focus when the dialog is shown. In the following dialog prompt the '''No''' button is the default button.
+
  
<eiffel>
+
=== Default Discard Button ===
ask_save_changes
+
    -- Ask user if they want to save the changes before continuing
+
  local
+
    l_prompt: ES_QUESTION_PROMPT
+
  do
+
    create l_prompt.make_standard ("Save changes before continuing?")
+
    l_prompt.show_on_active_window
+
  end
+
</eiffel>
+
 
+
[[Image:Dialog prompts example question no default.png|No is the default set default button]]
+
 
+
 
+
'''No''' was set as the default-default button automatically. Unless set, every dialog prompt uses the least dangerous button as the default button. In the above example '''No''' is actually set as the automatic default button because '''No''' is considered (statically) the least dangerous button for question prompts. If the question prompt was created with <eiffel>make_standard_with_cancel</eiffel> the '''Cancel''' button would actually be the default button because '''Cancel''' is considered less dangerous than '''No'''.
+
  
To override the default behavior you'll need to specify the default button. This has to be a button identifier for a button that exists on the dialog prompt. The following code demonstrates this.
+
Like non-discardable dialog prompts, discardable prompts require setting of a "Discard Button". the discard button is the button who's actions are performed, and dialog result set to when the the dialog prompt is not show becasue it was selected to be discarded on a previous showing. To set the discard button call <eiffel>set_discard_button</eiffel> on the dialog prompt after it has been created, using a button identifier that corresponds to a button that is available on the dialog prompt:
  
 
<eiffel>
 
<eiffel>
Line 75: Line 52:
 
     -- Ask user if they want to save the changes before continuing
 
     -- Ask user if they want to save the changes before continuing
 
   local
 
   local
     l_prompt: ES_QUESTION_PROMPT
+
     l_prompt: ES_DISCARDABLE_QUESTION_PROMPT
 
   do
 
   do
     create l_prompt.make_standard ("Save changes before continuing?")
+
     create l_prompt.make_standard ("Save changes before continuing?", "", "interface.dialog.confirm_save")
     l_prompt.set_default_button ({ES_DIALOG_BUTTONS}.yes_button)
+
     l_prompt.set_discard_button ({ES_DIALOG_BUTTONS}.yes_button)
 
     l_prompt.show_on_active_window
 
     l_prompt.show_on_active_window
 
   end
 
   end
 
</eiffel>
 
</eiffel>
  
[[Image:Dialog prompts example question default.png|Yes is now the default button]]
+
[[Image:Discardable dialog prompts example no message.png|The discard button is set to Yes]]
  
  
The default button is activated by pressing ENTER or SPACE when the dialog prompt is shown. It is also selected when the user presses CTRL+ENTER, which is inherited behavior from top most inherited class [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/es_dialog.e ES_DIALOG].
+
For all of the predefined, common discardable dialogs as discard button is set by default when creating the dialog prompt using either <eiffel>make_standard</eiffel> or <eiffel>make_standard_with_cancel</eiffel>. Below outlines the dialog prompt type and the default standard discard button for the prompt.
  
==== Default Cancel Button ====
+
* Warning: '''Ok'''
There also exists a default cancel button, which is activated when the user presses ESC or closes the dialog prompt without pressing one of the dialog prompt buttons. Like the default button, this behavior is inherited from [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/es_dialog.e ES_DIALOG]. The default cancel button is actually automatically determined for all prompts using [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/es_dialog_buttons.e ES_DIALOG_BUTTONS].<eiffel>default_cancel_buttons</eiffel>, which is also used to set the default button for all dialog prompts (remember, least dangerous action rule?)
+
* Information: '''Ok'''
 +
* Question: '''Yes'''
  
You can set the default cancel button just like you can the default button, however setting the default cancel button will not affect the default button even if you have not set the default button. To set the default cancel button use the routine <eiffel>set_default_cancel_button</eiffel>, specifying a button identifier of a button that exists on the dialog prompt. The code below shows how this is done.
+
In addition to being the button who's actions are perform, the discard button also is used to determine if the dialog prompt should save the selected discard state. It is logical to expect that if the user choose to perform an action which is not designated as the the discardable action then the discardable state should never be saved. Imagine the finalization dialog prompt mentioned at the beginning of this page. If the user chose to discard the dialog prompt and selected the '''Keep Assertions''' button, if the discard state was persisted, the next time the user finalizes a project the dialog prompt should not be shown and the assertions would be discarded in the compilation. This is because the '''Discard Assertions''' button is the action performed when the dialog prompt is discarded.
  
<eiffel>
+
=== Discard Message ===
ask_save_changes
+
    -- Ask user if they want to save the changes before continuing
+
  local
+
    l_prompt: ES_QUESTION_PROMPT
+
  do
+
    create l_prompt.make_standard ("Save changes before continuing?")
+
    l_prompt.set_default_button ({ES_DIALOG_BUTTONS}.yes_button)
+
    l_prompt.set_default_cancel_button ({ES_DIALOG_BUTTONS}.no_button)
+
    l_prompt.show_on_active_window
+
  end
+
</eiffel>
+
  
=== Responding to User Interactions ===
+
A discard message is an optional message that can be set on the dialog prompt during creation, through the <eiffel>a_discard_message</eiffel> argument.
[[:Category:EiffelStudio|EiffelStudio]] dialog prompts offer a dual interaction model when responding to user interaction. This frees you from the bounds of choosing one model over the other and lifts the restrictions on using either a single model. Sometimes it may be necessary to use both models. That said, the use of agents if the preferred model inside [[:Category:EiffelStudio|EiffelStudio]].
+
  
==== Agent Assignment ====
+
By default all discardable dialogs prompt have a check option to discard the dialog in the future. When no discard message is set the check option reads '''Do not show again'''. In the case where a discard message is set (a non-empty string) the message will be placed in parenthesis after the '''Do not show again''' check option text. The discard assertions finalization dialog prompt is an example of this, the discard check option reads '''Do not show again (always discard assertions when finalizing)'''. In this case the discard message is ''always discard assertions when finalizing''.
The primary model is the use of [http://docs.eiffel.com/eiffelstudio/general/guided_tour/language/tutorial-12.html agents], assigning them to a button using a button identifier.
+
  
After creating a prompt you may associate an agent to a button using <eiffel>[https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_prompt.e  ES_PROMPT].set_button_action</eiffel>. The routine takes a button identifier, which must be an identifier of a button on the prompt, as well as an agent action.
+
{{Note|Discard messages should indicate what action will be performed when discarded. The messages should be terse but clear and formatted without an initial capital letter as it's part of a sentence, not a new one.}}
  
<eiffel>
+
In the section detailing discard buttons the example was created without a discard message but passing <eiffel>""</eiffel> as an argument for parameter <eiffel>a_discard_message</eiffel> of <eiffel>make_standard</eiffel>. The follow example sets a discard message <eiffel>"always save"</eiffel>:
ask_save_changes
+
    -- Ask user if they want to save the changes before continuing
+
  local
+
    l_prompt: ES_QUESTION_PROMPT
+
  do
+
    create l_prompt.make_standard ("Save changes before continuing?")
+
    l_prompt.set_button_action ({ES_DIALOG_BUTTONS}.yes_button, agent save_changes)
+
    l_prompt.show_on_active_window
+
  end
+
 
+
save_changes
+
    -- Save all changes
+
  do
+
    ...
+
  end
+
</eiffel>
+
 
+
In the example a question prompt was created using the standard set of buttons for question prompts, which in this case are '''Yes''' and '''No''' buttons. Post-creation and initialization the '''Yes''' button is assigned an agent through the call to <eiffel>set_button_action</eiffel>. <eiffel>set_button_action</eiffel> is passed the button identifier <eiffel>yes_button</eiffel>, which is statically accessed from [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/es_dialog_buttons.e ES_DIALOG_BUTTONS]. <eiffel>yes_button</eiffel> could have just as easily been accessed from the <eiffel>dialog_buttons</eiffel> function exported on the prompt class:
+
 
+
<eiffel>
+
l_prompt.set_button_action (l_prompt.dialog_buttons.yes_button, agent save_changes)
+
</eiffel>
+
 
+
However, static access if preferred if appropriate for the situation.
+
 
+
==== Using Dialog Results ====
+
The second model of processing actions or changing execution flow, based on the user's interaction with the dialog prompt, is through the result <eiffel>dialog_result</eiffel>. Like button identifiers, <eiffel>dialog_result</eiffel> is an <eiffel>INTEGER</eiffel> and is set once the dialog has been closed buy the result of a user's interaction.
+
 
+
Here is the same example written using the dialog result model.
+
  
 
<eiffel>
 
<eiffel>
Line 149: Line 85:
 
     -- Ask user if they want to save the changes before continuing
 
     -- Ask user if they want to save the changes before continuing
 
   local
 
   local
     l_prompt: ES_QUESTION_PROMPT
+
     l_prompt: ES_DISCARDABLE_QUESTION_PROMPT
 
   do
 
   do
     create l_prompt.make_standard ("Save changes before continuing?")
+
     create l_prompt.make_standard ("Save changes before continuing?", "always save", "interface.dialog.confirm_save")
 +
    l_prompt.set_discard_button ({ES_DIALOG_BUTTONS}.yes_button)
 
     l_prompt.show_on_active_window
 
     l_prompt.show_on_active_window
 
    if l_prompt.dialog_result = {ES_DIALOG_BUTTONS}.yes_button then
 
      save_changes
 
    end
 
  end
 
 
save_changes
 
    -- Save all changes
 
  do
 
    ...
 
 
   end
 
   end
 
</eiffel>
 
</eiffel>
  
Using static access for the dialog button identifiers also allows you to opt to use the Eiffel <eiffel>inspect</eiffel> construct instead of using <eiffel>if</eiffel>...<eiffel>then</eiffel>...<eiffel>elseif</eiffel>...<eiffel>then</eiffel>...<eiffel>end</eiffel>:
+
[[Image:Discardable dialog prompts example message.png|Setting a discard message to 'always save']]
  
<eiffel>
 
inspect l_prompt.dialog_result
 
when {ES_DIALOG_BUTTONS}.yes_button then
 
  save_changes
 
when {ES_DIALOG_BUTTONS}.no_button then
 
  do_something_else
 
end
 
</eiffel>
 
  
=== Changing Button Labels ===
+
== Extending Discardable Dialog Prompts ==
There are times when a dialog prompt's button labels are not adequate enough to get the full message over to the user, or simply that you want a dialog prompt's buttons to show an extremely terse explaination of their action. Once such dialog in [[:Category:EiffelStudio|EiffelStudio]] is the Discard Assertions question prompt:
+
  
[[Image:Dialog prompts example discard assertions.png|Dialog shown when finalizing an Eiffel project]]
+
Like the regular [[Using Dialog Prompts (Basic)#Extend Dialog Prompts|dialog prompts]], discardable dialog prompts can also be extended. For an example of extension inside EiffelStudio, see the [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_discardable_compile_save_files_prompt.e ES_DISCARDABLE_COMPILE_SAVE_PROMPT] class. Below shows an extended [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_discardable_question_prompt.e ES_DISCARDABLE_QUESTION_PROMPT] class to create a discardable prompt that informs the user about unsaved modifications to one or more classes in the project, prior to a compilation.
 
+
 
+
The discard assertion dialog prompt is a question prompt that has had it's '''Yes''' button label set to '''Discard Assertions''' and '''No''' button label set to '''Keep Assertions'''. There was no need to subclass [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_question_prompt.e ES_QUESTION_PROMPT] (well actually [https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel/interface/new_graphical/dialogs/prompts/es_discardable_question_prompt.e ES_DISCARDABLE_QUESTION_PROMPT] but we have not gotten to discardable dialog prompts yet) and redefine <eiffel>dialog_button_label</eiffel>. Instead <eiffel>set_button_text</eiffel> can be used, in a similar manner as <eiffel>set_button_action</eiffel> is.
+
 
+
<eiffel>
+
ask_save_changes
+
    -- Ask user if they want to save the changes before continuing
+
  local
+
    l_prompt: ES_QUESTION_PROMPT
+
  do
+
    create l_prompt.make_standard ("Save changes before continuing?")
+
    l_prompt.set_button_text ({ES_DIALOG_BUTTONS}.yes_button, "Save Changes")
+
    l_prompt.set_button_action ({ES_DIALOG_BUTTONS}.yes_button, agent save_changes)
+
    l_prompt.set_button_text ({ES_DIALOG_BUTTONS}.no_button, "Continue Without Save")
+
    l_prompt.show_on_active_window
+
  end
+
</eiffel>
+
 
+
[[Image:Dialog prompts example button text.png|Changing button labels]]
+
 
+
 
+
Not only has the text been changed on the dialog prompt but the buttons have also been resized and both resized to match each width, as per the general user interface guidelines related to dialog buttons. This is just one of the new features of the new dialog implementation in [[EiffelStudio_6.1_Releases|6.1]].
+
 
+
In addition the resizing the key bindings have also been altered. On regular question prompts with '''Yes''' and '''No''' buttons pressing the ''Y'' key will select the '''Yes''' button and pressing ''N'' will select the '''No''' button. With the buttons relabeled from their defaults new key bindings are introduced. '''Save Changes''' can be select by pressing ''S'' and '''Continue Without Save''' selected by pressing ''C''.
+
 
+
== Changing the Title, Subtitle and Text ==
+
Most of the dialog prompts in EiffelStudio use a default title, in English it reads "EiffelStudio ''<Type>''" where ''<Type>'' is the type of dialog prompt. The [[:Category:EiffelStudio|EiffelStudio]] [[EiffelDebugger|Debugger]] dialog prompts actually set the title "Debugger ''<Type>''".
+
 
+
Setting the dialog prompt's title is a simple matter of calling <eiffel>set_title</eiffel> with the appropriate text:
+
 
+
<eiffel>
+
ask_save_changes
+
    -- Ask user if they want to save the changes before continuing
+
  local
+
    l_prompt: ES_QUESTION_PROMPT
+
  do
+
    create l_prompt.make_standard ("Save changes before continuing?")
+
    l_prompt.set_title ("Save Changes")
+
    l_prompt.show_on_active_window
+
  end
+
</eiffel>
+
 
+
A subtitle is rarely seen in the [[:Category:EiffelStudio|EiffelStudio]] dialog prompts. It is seen in the unsaved changes dialog prompts however. The subtitle in this case is "You have unsaved changes".
+
  
 
[[Image:Dialog prompts example unsaved list.png|Unsaved changes dialog prompt with a subtitle]]
 
[[Image:Dialog prompts example unsaved list.png|Unsaved changes dialog prompt with a subtitle]]
 
 
Setting the dialog prompt's subtitle can be done by calling <eiffel>set_subtitle</eiffel> with the appropriate text. Setting the subtitle using an empty string will remove the subtitle from the dialog prompt.
 
 
<eiffel>
 
ask_save_changes
 
    -- Ask user if they want to save the changes before continuing
 
  local
 
    l_prompt: ES_QUESTION_PROMPT
 
  do
 
    create l_prompt.make_standard ("Save changes before continuing?")
 
    l_prompt.set_title ("Save Changes")
 
    l_prompt.set_subtitle ("You have unsaved changes")
 
    l_prompt.show_on_active_window
 
  end
 
</eiffel>
 
 
Finally, the actual dialog prompt text can be changed. This is useful if you are reusing a dialog prompt and you need to alter it's text between showings, or if you are using a specialized dialog prompt but you have a need to change the default text. Setting the text can be done by calling <eiffel>set_text</eiffel> on the dialog prompt object.
 
 
== Avoiding Memory Leaks ==
 
When using agents in dialog prompts it's easy to forget to remove those agents, which can result in memory leaks inside [[:Category:EiffelStudio|EiffelStudio]] as the [[Garbage Collector]] still thinks there is a reference of an object. When using the advanced methods of displaying dialog prompts remember to call <eiffel>recycle</eiffel> once you are finished with your prompt.
 
 
<eiffel>
 
ask_save_changes
 
    -- Ask user if they want to save the changes before continuing
 
  local
 
    l_prompt: ES_QUESTION_PROMPT
 
  do
 
    create l_prompt.make_standard ("Save changes before continuing?")
 
    ...
 
    l_prompt.show_on_active_window
 
    l_prompt.recycle
 
  end
 
</eiffel>
 

Revision as of 09:49, 6 September 2007

Construction.png Not Ready for Review: This Page is Under Development!

Showing dialog prompts displaying the same messages over and over again can be annoying for most end-user. Take the security or alert notifications in your browser, most of us just turn them off after we have read them after they have been shown for the first time, we even discard them without reading them in some cases. EiffelStudio another product full of cases where "discardable" dialogs prompts are a necessity, without them we could hinder and annoy end-users.

Getting Started

You should already be familiar with the topics detailed in Using Dialog Prompts (Advanced) as the information there applies to discardable dialogs prompts also.

Before continuing you may also want to check out the following pages:

The Need For Discardable Dialog Prompts

One such example of a need for a discardable dialog is performing a finalization compilation. Finalization asks the end-user if they want to discard or keep assertions. For the most part (95%-99% of cases) assertions are always discarded. It makes sense to offer a way to suppress the dialog in the future and perform a default, commonly used, pre-defined action (discarding assertions in this case) when performing a finalization in the future.

Dialog shown when finalizing an Eiffel project


Introducing Discardable Dialog Prompt Classes

There are, as of EiffelStudio 6.1, three common discardable dialog prompt classes for use which are somewhat self-explanatory.

All dialog prompt classes are based on an abstract implementation ES_DISCARDABLE_PROMPT, which in turn implements parts of ES_PROMPT.

Information.png Note: There is no error variant of a discardable dialog prompt because errors are considered too important to discard. If an error occurs it should always been shown to the user!

Using Discardable Dialog Prompts

There are only a couple of few pieces of information required when using a discardable dialog prompt over the non-discardable variant.

State Preference Persistence

Most importantly is the configuration preference that the discardable states is stored. Upon creation of a discardable dialog prompt you will need to supply the full name of a preference, which is typically in the form interface.dialogs.confirm_xxxx where xxxx represents the name of the dialog.

Information.png Note: For dialog preferences and preference names examine the class EB_DIALOGS_DATA. For a general overview of adding preferences to EiffelStudio see Adding EiffelStudio Preferences.

Not only does the preference record the state of a user-opted discard but it also permits the user to reactive the dialog prompt via the preferences tool.

Default Discard Button

Like non-discardable dialog prompts, discardable prompts require setting of a "Discard Button". the discard button is the button who's actions are performed, and dialog result set to when the the dialog prompt is not show becasue it was selected to be discarded on a previous showing. To set the discard button call set_discard_button on the dialog prompt after it has been created, using a button identifier that corresponds to a button that is available on the dialog prompt:

ask_save_changes
    -- Ask user if they want to save the changes before continuing
  local
    l_prompt: ES_DISCARDABLE_QUESTION_PROMPT
  do
    create l_prompt.make_standard ("Save changes before continuing?", "", "interface.dialog.confirm_save")
    l_prompt.set_discard_button ({ES_DIALOG_BUTTONS}.yes_button)
    l_prompt.show_on_active_window
  end

The discard button is set to Yes


For all of the predefined, common discardable dialogs as discard button is set by default when creating the dialog prompt using either make_standard or make_standard_with_cancel. Below outlines the dialog prompt type and the default standard discard button for the prompt.

  • Warning: Ok
  • Information: Ok
  • Question: Yes

In addition to being the button who's actions are perform, the discard button also is used to determine if the dialog prompt should save the selected discard state. It is logical to expect that if the user choose to perform an action which is not designated as the the discardable action then the discardable state should never be saved. Imagine the finalization dialog prompt mentioned at the beginning of this page. If the user chose to discard the dialog prompt and selected the Keep Assertions button, if the discard state was persisted, the next time the user finalizes a project the dialog prompt should not be shown and the assertions would be discarded in the compilation. This is because the Discard Assertions button is the action performed when the dialog prompt is discarded.

Discard Message

A discard message is an optional message that can be set on the dialog prompt during creation, through the a_discard_message argument.

By default all discardable dialogs prompt have a check option to discard the dialog in the future. When no discard message is set the check option reads Do not show again. In the case where a discard message is set (a non-empty string) the message will be placed in parenthesis after the Do not show again check option text. The discard assertions finalization dialog prompt is an example of this, the discard check option reads Do not show again (always discard assertions when finalizing). In this case the discard message is always discard assertions when finalizing.

Information.png Note: Discard messages should indicate what action will be performed when discarded. The messages should be terse but clear and formatted without an initial capital letter as it's part of a sentence, not a new one.

In the section detailing discard buttons the example was created without a discard message but passing "" as an argument for parameter a_discard_message of make_standard. The follow example sets a discard message "always save":

ask_save_changes
    -- Ask user if they want to save the changes before continuing
  local
    l_prompt: ES_DISCARDABLE_QUESTION_PROMPT
  do
    create l_prompt.make_standard ("Save changes before continuing?", "always save", "interface.dialog.confirm_save")
    l_prompt.set_discard_button ({ES_DIALOG_BUTTONS}.yes_button)
    l_prompt.show_on_active_window
  end

Setting a discard message to 'always save'


Extending Discardable Dialog Prompts

Like the regular dialog prompts, discardable dialog prompts can also be extended. For an example of extension inside EiffelStudio, see the ES_DISCARDABLE_COMPILE_SAVE_PROMPT class. Below shows an extended ES_DISCARDABLE_QUESTION_PROMPT class to create a discardable prompt that informs the user about unsaved modifications to one or more classes in the project, prior to a compilation.

Unsaved changes dialog prompt with a subtitle