Re: a Wizard/Druid/Assistant widget for gtk



Am Mon, 2003-08-18 um 22.52 schrieb Jonathan Blandford:
> Matthias Clasen <maclas gmx de> writes:
> 
> > Over the last few days, I have started to work on a wizard widget for
> > GTK+, GtkAssistant. I looked at GnomeDruid, EggDruid and GtkNotebook for
> > prior art and at the Java LAF
> > (http://java.sun.com/products/jlf/at/book/index.html) for requirements.
> 
> Rock!  This and GnomeApp are two of the major things keeping libgnomeui
> around.  Getting this into GTK+ would be really nice.
> 
> > The main difference to GnomeDruid is that I avoided GnomeDruidPage and
> > its subclasses. Instead, pages are arbitrary widgets, and their page
> > type (introduction page, content page, confirmation page, summary page
> > in the terminology of the Java LAF) is determined by a child property.
> 
> This probably is the right thing to do.  People had a lot of trouble
> with that aspect of GnomeDruid system.  I don't think the flexibility
> you get by doing that is worth the confusion.  It does mean that
> converting branching code that used GnomeDruid will be more complicated
> than s/GnomeDruid/GtkAssistant/.
> 
> That being said, having a function like:
> 
> void prepare (GtkAssistant *assistant, GtkWidget *page, MyData *data)
> {
>   if (page == data->page_one)
>     prepare_page_one (page, data)
>   else if (page == data->page_two)
>     prepare_page_two (page, data)
>   else if (page == data->page_three)
>     prepare_page_three (page, data)
> ...
> }
> 
> seems ugly.  I personally liked having the signals on the pages
> themselves as libglade saved me from this type of nastiness.
> 

Yes, I agree it's a bit ugly. Unfortunately, we don't have "child
signals", so we have to choose between eliminating GnomeDruidPage from
the public api and having nice per-page signals.

> > As a consequence, the ::back, ::next and other signals from
> > GnomeDruidPage are now signals on the assistant itself.
> 
> Just to confirm, are we happy with "next" and "back" as terminology?  To
> me, forward/back and next/previous are logical language pairings.  It
> would be good to get confirmation from the UI team before writing this
> in an API.

Yes, I also thought about this inconsistency, but didn't come up with
something sufficently better (the Java LAF examples also use Back/Next,
the Aqua HIG example uses Go Back/Continue).

> > The assistant decides which buttons to display, based on the page type:
> > 
> > introduction page/initial content page: cancel, next
> > content page: cancel, back, next
> > confirmation page/final content page: cancel, back, finish
> > summary page: close
> 
> This seems a little inflexible.  I've seen pages which change types
> based upon a toggle button.  As an example, take a wizard in which you
> have a list of items to select from.  There's a '[ ] Select custom
> properties' button at the bottom that toggles between 'Next' and
> 'Finish'.  This way you can either create a simple object, or set up all
> the I can mock something up if this was unclear.  Also, some

To support changing page type on the fly, we would just need to
hide/show the appropriate buttons in gtk_assistant_set_page_type() if
the page being changed is the current one. I hadn't thought of this, but
it should be easy.

> dialogs like adding their own buttons.  'Help' is an obvious one, but
> sometimes applications add other buttons.  I vaguely recall bug-buddy
> had a 'Get Backtrace' button or something.
> 

I decided to omit the help button which was in GnomeDruid, since the HIG
rightly argues that you have already missed the #1 goal of a wizard if
your wizard is complicated enough to warrant a help buttons. Neither the
Java LAF nor the Aqua HIG mention help buttons for wizards. The Aqua HIG
does recommend to display a progress bar for long operations in the
button area, so there is some precedent for having some from of
action_area.

> Other thoughts:
> 
>  * Does the GtkAssistant take care of drawing the decorations?  Are we
>    going to have problems when people want to make their own assistants?
>    Would it make sense to have GtkAssistant/GtkAssistantPage that
>    handled drawing all the decorations.  It would let us hedge against
>    changes in best-practices/fashion here.

Is your proposal to reintroduce GtkAssistantPage and move the drawing
code there ?  

>  * One thing that confused people about GnomeDruid was that it didn't
>    inherit from GnomeDialog ("you mean I have to put it in its own
>    window?").  While the rationale for that was so that it could be
>    embedded more easily in another app, in practice no one else has ever
>    done that.  I don't know if having the "reponse" style API is good
>    here, but it does provide us with a well-known way to add extra
>    buttons, handle secondary buttons, etc.

I guess embedding an assistant into something other than a dialog is
rare enough that we should just turn GtkAssistant into a dialog. 
> 
>  * Do we have a proposed look for the Assistant?  I think we need that
>    before we write the look API.  There's a danger here of ending up
>    with the current problem with GtkMessageDialog API with no way to do
>    Primary/Secondary text nicely.  Additionally, I am pretty sure that
>    people found the GnomeDruidPageStandard API limiting, though I can't
>    remember the specifics.  Perhaps they just found it ugly, as they
>    kept modifying the canvas directly. (-;

My current code was directly lifted from Anders' EggDruid. It provides a
sidebar where an image can be displayed and a header which contains a
title, a description and a smaller logo. I've attached a demo (sorry for
the silly images).

> 
>  * How will control-flow work?  How would you handle hitting next and
>    preventing it from automagically going to the next page?  Would you
>    have to call set_page() to the current page?  Will that retrigger
>    "prepare"?  Do you stop the signal emission.  For example, consider
>    an app with a slow operation.  You might want to popup a dialog
>    "Searching for new hardware [ Cancel ]" and not actually switch pages
>    until that task is finished.  When they hit next, you basically want
>    the Assistant to do nothing.

You can just return TRUE, no need to set_page() to the current page;
set_page() to the current page won't retrigger ::prepare. Regarding the
slow operation, I was assuming that one would do that like the Java LAF
recommends: have a confirmation page with a finish button, followed by a
progress page. The ::finish handler wouldn't wait for the completion of
the slow operation, but return early to let the assistant switch to the
progress page, and the operation would update the progress until it is
completed. The back/next buttons on the progress page should be made
insensitive until the operation is completed or aborted.

> [Some comments on the API ]
> 
> > void gtk_assistant_set_buttons_sensitive (GtkAssistant  *assistant,
> >                                           gboolean       back_sensitive,
> >                                           gboolean      
> > forward_sensitive, 
> >                                           gboolean      
> > cancel_sensitive);
> 
> What about finish?  Is that a different button?

I think I explained that in the docs further down: Since only on
forward-going (i.e. next/finish/close) button will be displayed at a
time, it is enough to have one flag controlling their visibility. 

> 
> > /* managing pages */
> > void gtk_assistant_insert_page (GtkAssistant  *assistant,
> >                                 GtkWidget     *sibling,
> >                                 GtkWidget     *page);
> 
> Is sibling before or after page when this is done?  I did insert_column
> with an integer in gtktreeview.h.  How about
> gtk_assistant_insert_page_{before,after} that take a sibling while
> insert takes an int?


/**
 * gtk_assistant_insert_page:
 * @assistant: a #GtkAssistant
 * @sibling: a #GtkWidget which is already added as a page of    
 *           @assistant, or %NULL to insert @page at the end
 * @page: a widget to insert before @sibling 
 * 
 * Adds a page to a #GtkAssistant. The page is inserted before @sibling.
 **/

> > /* child properties */
> > void gtk_assistant_set_page_type (GtkAssistant        *assistant,
> >                                   GtkWidget           *page,
> >                                   GtkAssistantPageType type);
> > GtkAssistantPageType gtk_assistant_get_page_type (GtkAssistant 
> > *assistant,
> >                                                   GtkWidget     *page);
> > void gtk_assistant_set_page_title (GtkAssistant  *assistant,
> >                                    GtkWidget     *page,
> >                                    const gchar   *title);
> > gchar *gtk_assistant_get_page_title (GtkAssistant  *assistant,
> >                                      GtkWidget     *page);
> 
> Is this persistent for a given page?  Is there a way to go back to the
> default title?  Is there a default title?

Maybe there should be a "default_page_title" property on GtkAssistant,
and gtk_assistant_set_page_title (assistant, page, NULL); should switch
back to it.

Matthias

PS I have now attached my current code to
http://bugzilla.gnome.org/show_bug.cgi?id=115348

Attachment: assi.png
Description: PNG image



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]