+++ /dev/null
-This is a mini howto, describing the steps to add a new dialog box
-to psppire. This is document is only tested for the master branch.
-Gtk3 is uncharted territory ....
-
-
-How to add a new dialog to Psppire
-==================================
-
-
-Before you start.
-
-1. You will need to install Glade (but see the important note
- about which version at the end of this document!
-
-
-
-2. Build and install the lastest pspp master HEAD, with the
- "--with-gui-tools" option passed to configure. Thus:
-
- ./configure --with-gui-tools
- make
- sudo make install
-
- This installs the pspp specific libraries and widgets that glade needs.
-
- For this step, you must build inside the pspp source directory, and
- you must install to the default directory. DO NOT build from
- outside the source, and do not pass a --prefix to configure.
-
-
-Having done the above, you should be able to edit an existing dialog
-definition, thus:
-
- glade src/ui/gui/descriptives.ui
-
-You will probably get a lot of Gtk-Warnings/Criticals most of them
-are harmless.
-
-
-If this works, now you are in a position to start ....
-
-There are two basic steps. Firstly, you need to define the layout of
-the dialog. This is done using glade, which you have installed as
-described above. The second step is to define the behaviour of the
-dialog. For this, you need to define a new object deriving from
-PsppireDialogAction
-
-
-
-Example: Adding a new dialog: foobar
--------------------------------------
-
-
-Defining the layout
-...................
-
-Start glade and create a new GtkBuilder file, thus:
- glade-3 src/ui/gui/foobar.ui
-
-All dialogs need a top level window. For Psppire, this must be an
-instance of PsppireDialog.
-On the left hand side of the Glade window, you will see a category
-headed "Psppire". Click on the first item in that category and a new
-(empty) dialog will be created.
-
-Most dialogs have a vertical button box on the right hand side, so
-click on the "Vertical Button Box" icon. Then on the right hand panel
-of the new dialog. You will be prompted to enter the number of items
-in the button box. For this example, chooose 5.
-
-Note, that by default, the dialog box was created with an "internal
-child" GtkVbox whose "Number of items" property is 2. Change this
-to 4. You should see the extra empty panels appear.
-
-Typically a dialog box needs a DictionaryTreeview in the left hand
-panel. But we normally put that inside a scrolled window, which in
-turn is inside a Frame.
-
-Under the "Containers" category there is a "Frame" item. Click on
-this. Then on the leftmost panel of the dialog box. The new GtkFrame
-widget should appear. Again in the "Containers" category click on
-"Scrolled Window" and then in the frame you have just created.
-This will put a new GtkScrolledWindow inside the GtkFrame.
-
-Now click on the "Dictionary Treeview" widget (unde the "Psppire"
-category, and put that inside the Scrolled window.
-
-You should now have a half complete dialog looking something like
-this:
-
-+---------------+-----------------+----------------+-----------------+
-|Frame1 | | | +--------------+|
-|+-------------+| | | | OK ||
-|| || | | +--------------+|
-|| || | | |
-|| || | | +--------------+|
-|| || | | | Paste ||
-|| || | | +--------------+|
-|| || | | |
-|| || | | +--------------+|
-|| || | | | Cancel ||
-|| || | | +--------------+|
-|| || | | |
-|| || | | +--------------+|
-|| || | | | Reset ||
-|| || | | +--------------+|
-|| || | | |
-|| || | | +--------------+|
-|| || | | | Help ||
-|+-------------+| | | +--------------+|
-+---------------+-----------------+----------------+-----------------+
-
-In the second panel from the left, we might want a selector button.
-However, we don't want to fill the entire panel.
-So we put it in inside a GtkAlignment. From the "Containers" category
-click "Alignment". and then the panel. Such a widget is of course
-not visible, but you will note its presence from the widget hierarchy
-in the top right hand corner of the glade window.
-Now, from the "Psppire" category, click on "Selector Button" and put
-it inside the new GtkAlignment. It will appear to occupy the entire
-panel. To fix this, select the GtkAlignment and change its Horizontal
-Scale and Vertical Scale properties to zero.
-
-If all is well, the dialog box now looks like this:
-
-
-+---------------+-----------------+----------------+-----------------+
-|Frame1 | | | +--------------+|
-|+-------------+| | | | OK ||
-|| || | | +--------------+|
-|| || | | |
-|| || | | +--------------+|
-|| || | | | Paste ||
-|| || | | +--------------+|
-|| || | | |
-|| || |\ | | +--------------+|
-|| || | \ | | | Cancel ||
-|| || | / | | +--------------+|
-|| || |/ | | |
-|| || | | +--------------+|
-|| || | | | Reset ||
-|| || | | +--------------+|
-|| || | | |
-|| || | | +--------------+|
-|| || | | | Help ||
-|+-------------+| | | +--------------+|
-+---------------+-----------------+----------------+-----------------+
-
-
-However you will notice that upon resizing the dialog, the selector
-button's panel expands with it, which is probably not what we want.
-To fix this, select the GtkAlignment which we created above, and set
-its "Expand" packing-property to false.
-
-
-We final panel might require a PsppireVarView widget, again inside a
-GtkScrolled window (and possibly a GtkFrame). Create this, in a
-similar way to which you did the PsppireDictionaryTreeview above.
-
-Now you have a fully populated dialog box. It might need tweaking
-which we can do later. But we are now in a position to display our
-defined dialog box.
-
-
-Displaying the Dialog box in Psppire
-....................................
-
-
-1. Define a new PsppireDialogAction Class
-
-Create a new object class derived from PsppireDialogAction (note that
-PsppireDialogAction itself implements GAction). It's probably
-best if you use an existing example as a template. The minimum you
-require is:
-
-
-#include <config.h>
-#include "psppire-dialog-action-foobar.h"
-#include "psppire-var-view.h"
-#include "psppire-dialog.h"
-#include "builder-wrapper.h"
-
-static void psppire_dialog_action_foobar_init (PsppireDialogActionFoobar *act);
-static void psppire_dialog_action_foobar_class_init (PsppireDialogActionFoobarClass *class);
-
-G_DEFINE_TYPE (PsppireDialogActionFoobar, psppire_dialog_action_foobar, PSPPIRE_TYPE_DIALOG_ACTION);
-
-static gboolean
-dialog_state_valid (gpointer data)
-{
- PsppireDialogActionFoobar *ud = PSPPIRE_DIALOG_ACTION_FOOBAR (data);
-
- // This function is a predicate to determine if the dialog box has
- // been set to a state where it is appropriate to click OK /
- // Paste.
-
- // If it returns FALSE, the OK and PASTE buttons are insensitive
-
-
- return ....;
-}
-
-static void
-refresh (PsppireDialogAction *rd_)
-{
- PsppireDialogActionFoobar *uv = PSPPIRE_DIALOG_ACTION_FOOBAR (rd_);
-
- // This function is called when the Reset Button is clicked.
- // It sets the dialog to its default state
-}
-
-
-// This function is called when the menuitem is activated.
-// It is what pops up the dialog
-static void
-psppire_dialog_action_foobar_activate (GAction *a)
-{
- PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
- PsppireDialogActionFoobar *act = PSPPIRE_DIALOG_ACTION_FOOBAR (a);
-
- // These three lines are (almost) always required
- GtkBuilder *xml = builder_new ("foobar.ui");
- pda->dialog = get_widget_assert (xml, "foobar-dialog");
- pda->source = get_widget_assert (xml, "dict-view");
-
- // ... here you can load any widgets that your dialog uses
- act->this_widget = get_widget_assert (xml, "this_widget");
- act->that_widget = get_widget_assert (xml, "that_widget");
-
- // ... you will most probably need to have these here
- psppire_dialog_action_set_valid_predicate (pda, dialog_state_valid);
- psppire_dialog_action_set_refresh (pda, refresh);
-
-
- // Everything below this line is necessary.
- g_object_unref (xml);
-
- if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_foobar_parent_class)->activate)
- PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_foobar_parent_class)->activate (pda);
-}
-
-
-// Most often this function will not need any changes
-static void
-psppire_dialog_action_foobar_class_init (PsppireDialogActionFoobarClass *class)
-{
- GActionClass *action_class = GTK_ACTION_CLASS (class);
-
- action_class->activate = psppire_dialog_action_foobar_activate;
- PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
-}
-
-
-static void
-psppire_dialog_action_foobar_init (PsppireDialogActionFoobar *act)
-{
- // often, this function can be empty
-}
-
-
-
-static char *
-generate_syntax (PsppireDialogAction *act)
-{
- PsppireDialogActionFoobar *uvd = PSPPIRE_DIALOG_ACTION_FOOBAR (act);
-
- gchar *text = NULL;
- GString *str = g_string_new ("FOOBAR ");
-
- // ... this function generates the syntax to be interpreted by
- // PSPP's backend
-
- g_string_append (str, ".\n");
- text = str->str;
- g_string_free (str, FALSE);
-
- return text;
-}
-
-2. Declare the new PsppireDialogAction Class
-
-You will also need to define the corresponding .h header file. Best
-to copy and search replace on an existing one.
-
-
-3. Adding the entry point for the dialog.
-
-Edit src/ui/gui/data-editor.ui It is possible to do this with Glade,
-but frankly is easier with a text editor. Something like the
-following is typical.
-
-
- <child>
- <object class="PsppireDialogActionFoobar" id="some-menu_foobar">
- <property name="manager">uimanager1</property>
- <property name="name">some-menu_foobar</property>
- <property name="label" translatable="yes">_Foobar</property>
- <property name="stock-id">somemenu-foobar</property>
- </object>
- </child>
-
-
-4. Announce the new object to GtkBuilder.
-
-Add the new PsppireDialogAction's get_type function to to
-src/ui/gui/widgets.c Just have a look there and follow the pattern.
-This is necessary to that GtkBuilder knows about the new object class.
-
-5. Putting it all together.
-
-Don't forget to put any new files you've created in
-src/ui/gui/automake.mk and to rerun make ; make install
-
-
-
-Note! Currently (as of commit fe7682b3c3d36cf9ba3e867588e5b808af833262 )
-psppire is in a transitional phase. Our .ui files come in two mutually
-incompatible varieties. The older variety can be identified by a
-string similar to:
-
- <requires lib="psppire" version="2054.17080"/>
- <!-- interface-requires gtk+ 2.12 -->
- <!-- interface-naming-policy project-wide -->
-
-To edit these files you will need to install Glade version 3.8.4 ---
-ANY OTHER VERSION IS UNLIKELY TO WORK --- I know that 3.18.x does
-not! If your distro doesn't have this version, you will need to
-download it and build it from source.
-
-
-The newer ones contain the string:
-
-<!-- Generated with glade 3.18.3 -->
-<interface>
- <requires lib="gtk+" version="3.12"/>
-
-Like the string suggests Glade version 3.18.x or later will probably
-be ok for these files.
-
-Hopefully the older style .ui files will gradually be converted to new
-style ones.
-
-
-That's about it, I think. Did I forget anything?
-
-