Table of Contents

gEDA Developer Tips, tricks and hints

How to branch correctly using CVS

Here’s a summary of what should happen with development on a branch that is intended to later be merged to the trunk. Suppose the branch is called “mine”.

1) tag the repository (trunk) to create a branch point tag:

 cvs tag mine-base 

2) branch

 cvs tag -b -r mine-base mine

What step #1 does is to keep track of where the “mine” branch started
from. The "-r mine-base” in step #2 says to create the branch starting
from the tag “mine-base”. It is important to do this because you need
to be able to know where each file is rooted (i.e., what version in the
trunk it is derived from).

Usually, it is a good idea to periodically merge changes which have taken
place on the trunk to the branch. This will reduce the amount of work when
the work on the branch is ready to go back to the trunk.

# go to where the trunk is checked out and update it

 cd /to/my/trunk/sources
 cvs update -PdA

# create a temporary tag in case someone commits stuff while you’re
# in the middle of this procedure. This keeps you from losing anything.

 cvs tag merge-mine

# go to your branch source tree

 
 cd /to/my/branch/sources
 cvs update -Pd

# the following says to apply the changes that have taken place on
# the trunk between the version tagged with “mine-base” and “merge-mine”
# to your branch source tree

 cvs update -j mine-base -j merge-mine -dP

# if all goes well, you’ll have no conflicts. It is not uncommon
# for there to be some cases where you have to resolve conflicts by
# hand. In this case the affected files will have a special comment
# showing what your file on the branch had and what the file tagged as
# merge-mine had. You, as the programmer, have to figure out what is
# correct. Once this is all done, proceed.

# checkin with a message like “sync with trunk” or
# “pull up revs #### from the trunk” (if you were pulling up
# a specific change).

 cvs ci

# Now we move the branch point tag to the temporary merge tag
# This is because we have changed what rev each file in the branch
# is based on in the trunk. This is known as re-rooting.

 cvs tag -F -r merge-mine mine-base

# now we don’t need the temporary merge tag anymore so remove it

 cvs tag -d merge-mine

When it is time to merge changes that have taken place on a branch back
to the trunk (usually marking the end of that branch), first do a final
trunk → branch merge as mentioned above. Then do a branch → trunk merge.

Now for a branch to trunk merge you’d do

 cd /to/my/trunk/sources
 cvs update -PdA
 cvs update -j mine-base -j mine -dP

# resolve conflicts

 cvs ci
 cvs tag -F mine-base

This takes any changes between “mine-base” and “mine” and tries to apply
it to the trunk. If it all goes cleanly, you just check it in otherwise you
have to resolve conflicts. Then you move the branch point tag because the trunk
now reflects the lastest in the branch.

The above was contributed by Dan McMahill

Doxygen Comments and styles

Any volunteer for writing some notes?

Dialogs: Design and Behaviour

Dialog Design

There’s a nice document from the gnome guys called Gnome HIG. There are several suggestions on how to design dialogs and how they should behave.

The dialog design is mostly a matter of taste:

Misc:

Modal or Nonmodal dialogs

A modal dialog is required whenever the main application provides data for the dialog.

Example: 
  The dialog is called with a selection list and the dialog only should operate on this selection.

A modal dialog is OK too, if the dialog is only called very seldom. The file open dialog could be nonmodal because it does not require any input from the application.

A modal dialog is not OK if there is a lot of user interaction with the dialog. The component selection is a good example.

Where to place the dialog

A dialog can be put on different places in on the screen. A list of possible places can be found in the GtkReference

The current dialogs are placed either on the mouse position (GTK_WIN_POS_MOUSE) or at no preset position (GTK_WIN_POS_NONE). The Gnome HID does not say anything about that topic.

The default setting is GTK_WIN_POS_NONE for GtkWindow see GtkWindow. The default for GtkDialog is GTK_WIN_POS_CENTER_ON_PARENT ( taken from the GtkDialog source).

Placing dialogs in front of their parent window

Most of the dialogs are placed in front of their parent window using the transient_for property (see. GtkReference). This property should be set for all modal dialogs.

For nonmodal dialogs the setting of transient_for property is not obvious. While in gschem for example the coord dialog should stay above the parent window, the log window does not need to stay in front of it.

Note: There is an older mechanism that keeps the the dialogs in front of gschem. If the raise-dialog-boxes-on-expose variable is set to enable in one of gschem’s configuration files, it may cause problems with some window managers. If dialogs are flickering at 100% CPU load, then disable that setting.

; raise-dialog-boxes-on-expose string
;
; Controls if dialog boxes are raised whenever an expose event happens
; Default is enabled
;
;(raise-dialog-boxes-on-expose "enabled")
(raise-dialog-boxes-on-expose "disabled")

Button order in dialogs

Button order at the bottom of the dialog depends on which operating system the user is using. GTK handles this automatically (require version > 2.6.0) , but requires the developers set the alternative button order. For more information, check the GTK documentation here.

The alternative button order is set with just one call to a GTK function:

#if GTK_CHECK_VERSION (2,6,0)
  /* Set the alternative button order (ok, cancel, help) for other systems */
  gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
					  GTK_RESPONSE_OK,
					  GTK_RESPONSE_NO,
					  GTK_RESPONSE_CANCEL,
					  GTK_RESPONSE_HELP,
					  -1);
#endif

This should be done for every new dialog created, before running it.

Dialog design of the current dialogs

Source template for simple dialogs

This template is not intented to compile, but you can easily copy the code block that you need.

void dialog (TOPLEVEL *w_current)
{
  GtkWidget *vbox, *label, *alignment, *table;
  GtkWidget *dialog;
 
  /* only create the dialog if it is not there yet. This usually is a
     widget pointer in the w_current structure: 
     dialog = w_current->tewindow */
  if (!dialog) {
    dialog = gtk_dialog_new_with_buttons(_("Dialog title"),
					 /* the parent window or NULL */
					 GTK_WINDOW(w_current->main_window), 
					 /* dialog properties */
					 GTK_DIALOG_MODAL, /* 0 for nonmodal dialogs */
					 /* dialog buttons and response signals */
					 GTK_STOCK_CANCEL,
					 GTK_RESPONSE_REJECT,
					 GTK_STOCK_OK,
					 GTK_RESPONSE_ACCEPT,
					 NULL);
 
#if GTK_CHECK_VERSION (2,6,0)
    /* Set the alternative button order (ok, cancel, help) for other systems */
    gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
	  				    GTK_RESPONSE_OK,
					    GTK_RESPONSE_NO,
					    GTK_RESPONSE_CANCEL,
					    GTK_RESPONSE_HELP,
					    -1);
#endif
 
    /* set default response signal. This is usually triggered by the 
       "Return" key */
    gtk_dialog_set_default_response(GTK_DIALOG(dialog),
				    GTK_RESPONSE_ACCEPT);
 
    /* set the function for handling the button responses and dialog close 
       for nonmodal dialogs you can use dialog_run() too.*/
    gtk_signal_connect(GTK_OBJECT(dialog), "response",
		       GTK_SIGNAL_FUNC(dialog_response), w_current);
 
    /* where to place the dialog: GTK_WIN_POS_MOUSE or GTK_WIN_POS_NONE */
    gtk_window_position(GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
 
    /* set the border spacing and the vbox spacing of the dialog */
    vbox = GTK_DIALOG(dialog)->vbox;
    gtk_container_set_border_width(GTK_CONTAINER(dialog),DIALOG_BORDER_SPACING);
    gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
 
    /* create a label (with markup) and pack it into the dialog box */
    label = gtk_label_new(_("<b>Section label</b>"));
    gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
    gtk_misc_set_alignment(GTK_MISC(label),0,0);
    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
 
    /* create a alignment container with the DIALOG_INDENTATION on the left */
    alignment = gtk_alignment_new(0,0,1,1);
    gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 
			      DIALOG_INDENTATION, 0);
    gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
 
    /* a table can store several entries. It is stored in the aligment container.
       Note: the vertical and horizontal cell spacings */
    table = gtk_table_new (3, 2, FALSE);
    gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
    gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
    gtk_container_add(GTK_CONTAINER(alignment), table);
 
    /* a simple text label in one table cell with left alignment. 
       Note: the GTK_FILL in the third line is required */
    label = gtk_label_new(_("Text:"));
    gtk_misc_set_alignment(GTK_MISC(label),0,0);
    gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
 
    /* a simple text entry completes the option row */
    textentry = gtk_entry_new_with_max_length (10);
    gtk_table_attach_defaults(GTK_TABLE(table), textentry, 1,2,0,1);
    gtk_entry_set_activates_default(GTK_ENTRY(textentry), TRUE);
 
    /* ..... more table rows with options, or new sections */
 
    /* create references to all widgets that you need later */
    GLADE_HOOKUP_OBJECT(dialog, sizeentry,"textentry");
 
    /* show all widgets recursivly */
    gtk_widget_show_all(dialog);
  }
 
  else { 
    /* Dialog is already there. Present it to the user. 
       This is only required if you have a nonmodal dialog */
    gtk_window_present(GTK_WINDOW(dialog));
  }
 
  /* always set the current values to the dialog 
     If you're placing that part at the end of the dialog function you can 
     easily create dialogs that can be called, even if they are already open */
  textentry = g_object_get_data(G_OBJECT(dialog), "textentry");
  gtk_entry_set_text(GTK_ENTRY(textentry), string);
  /* select the text region that the user usually likes to overwrite */
  gtk_entry_select_region(GTK_ENTRY(textentry), 0, strlen(string));
}

The response function for such a dialog may look like this:

void dialog_response(GtkWidget *widget, gint response, TOPLEVEL *w_current)
{
  switch (response) {
  case GTK_RESPONSE_ACCEPT:
    /* apply the dialog settings:
       just insert your code here if it is short
       call an extra apply function if the required code is long */
    break;
  case GTK_RESPONSE_REJECT:
  case GTK_RESPONSE_DELETE_EVENT:
    /* for modal dialogs just do nothing,
       for nonmodal dialogs, destroy the dialog and clean up */
    break;
  default:
    /* catch wrong signals signals (paranoid error checking ;-)) */
    printf("dialog_response(): strange signal %d\n", response);
  }
 
  /* for nonmodal dialogs just do nothing,
     for modal dialogs, always destroy the dialog and clean up */
}

Current Dialog Issues in Gschem

Here’s a list of things that could be improved:

Print Dialog
Write Image
Execute Script
Edit Text
Color Dialog
Line Width and Type
Fill Type
Translate Symbol
Page Manager
Component Selector
Single Attribut Editor
Multi Attribute Editor
Add Text
Arc Params
Insert Picture
Picture Replace
Find Text
Hide Text
Show Text
Autonumber Text
Text Size
Snap Grid Spacing
Coord Dialog
About Dialog
Hotkeys