4 When writing Gnumeric our priorities are
7 2) Maintainable & Documented
8 3) Modular and well designed
12 When you submit code to me for inclusion in Gnumeric, or when you modify
13 the sources directly on the CVS repository, please keep those things in mind.
14 While performance is important please note that we do not want to hand tune
15 code to shave milliseconds at this point. Well designed algorithms and data
16 strucutures are fertile areas for development, obfuscated code to make a loop
17 3% faster is not. Specifically, this means:
19 - Clarity of design and function are paramount
20 - Make sure your code does not generate warnings at all.
21 - Please follow the coding style used Gnumeric.
23 The Gnumeric coding style.
24 --------------------------
26 The coding style of Gnumeric is a mix of various styles, make
27 yourself familiar with the GNU coding standards (shipped with most
28 GNU/Linux systems as the standards.info file), then read the Linux
29 kernel coding standards and ignore Linus' jokes. Then look at the
30 Gtk+ header files to get aquainted on how to write nice header files
31 that are almost self documenting.
33 Remember: Use 8 space tabs for indentation: that will keep your
34 code honest as you will be forced to split your routines in more
35 modular chunks (as detailed by Linus).
37 Emacs users can get the default indentation style with this:
39 (setq c-basic-offset 8)
41 On top of that, you will have to:
43 - Follow the Gtk+ cleanliness conventions for function
46 - Follow the Gtk+ namespace convention for function names.
47 module_submodule_operation
49 - Make sure your code does not have a single warning (with the
50 default strong warnings that Gnumeric compiles with) before
51 your code is submited. (Although we do not advocate -Werror)
53 - Every entry point to a public routine should use the
54 g_return_if_fail and g_return_val_if_fail macros to verify
55 that the parameters passed are valid.
57 - Under no circunstances use magic variables. Use typedef
58 enum { ... } type; to create enumerations. Do not use
59 integers to hold references to enumerations, the compiler
60 can help catch various errors.
62 - Use g_warning to mark spots that need to be reviewed or are
63 not finished to let me fix it eventually.
65 - It is more important to be correct than to be fast.
67 - Do not optimize unnecesarly. Do profile, do look for the
68 weak spots before applying "optimization by feeling". This
69 is not a Ouija-based project.
71 - It is more important to keep the code maintainable and
72 readable than to be fast. If you have a great idea about
73 optimizing the code, make sure it is implemented cleanly,
74 that there is a clean and maintainable way to do it:
76 - Fast code that is difficult to maintain has no place in
77 Gnumeric and will be dropped.
79 - Follow the Gnumeric commenting style, which is not the Gtk
85 - Gnumeric is intended to be run in various countries with
86 different currency conventions, number formatting
87 conventions and different languages. Use the locale
88 functions to make sure your code will work on countries that
89 have different conventions than your country.
91 All of this is to ensure the Gnumeric code will be kept within
92 reasonable margins of maintainability for the future: Remember, in two
93 years you will probably be far too busy to maintain your own
94 contributions, and they might become a burden to the program maintainers.
96 Gnumeric is the foundation for a large spreadsheet project and
97 various other projects in the GNOME desktop (the document model and
98 CORBA service provision).
100 Cleaning code in Gnumeric is more important than trying not to break
101 existing code. By all means, code clean ups are always welcome.
103 Extra Spreadsheet functions
104 ---------------------------
106 When you write new functions, keep the following in mind:
108 - Be compatible with the Excel functions as much as possible.
110 - Provide an online help description. If you can provide
111 examples of use in the documentation, that is even better.
114 Things that are usually missed
115 ------------------------------
117 Make sure that dialogs work well without using the mouse. GnomeDialog
118 solves some of this automatically, but by no means all. Some dialogs
119 aren't GnomeDialogs at all, and you have to do more work manually.
121 - Pressing the escape key should dismiss the dialog.
123 GnomeDialog does this. If your dialog does not inherit from
124 GnomeDialog, write a handler like src/file.c:fs_key_event and
125 connect it to "key_press_event". See src/file.c:workbook_save_as for
128 - Initial keyboard focus should be assigned.
130 This means that when the dialog pops up, keystrokes should go to one
131 of the widgets in the dialog, often the top left widget. In glade,
132 you set initial focus by selecting "Has Focus" in the "Basic" panel
133 of the Property Editor. In C, you use gtk_widget_grab_focus (widget).
135 In multipage dialogs (druid, notebook, propertybox), you have to set
136 initial focus each time you switch pages. This means that you have
137 to do it from C, even if it's a glade dialog.
139 You also have to do it from C in OK/warning/error dialogs.
141 - There should be a keyboard accelerator for each widget.
143 The user can navigate to the widget with Alt + <letter>, where
144 <letter> is an underlined letter in the widget label. It should
145 ideally be the first, but that's often not possible.
147 In glade, you define the accelerator by inserting an "_" in the
148 label. Like this: "_File" makes F the accelerator. To make an
149 accelerator for a text field, insert an "_" in the label, and make
150 the field the "focus target" of the label. This can be done in the
151 widget panel of the property editor.
153 It's rather awkward to define accelerators for the "OK", "Cancel",
154 etc. buttons in a GnomeDialog using glade, and so far we have left
157 There's a problem with accelerators in notebooks: You cannot use the
158 same letter in two different pages. This is either a bug in gtk or
159 in glade. For simple dialogs, it's possible to work around the
160 limitation, but for complex cases it is probably best to ignore it
161 and assume that it will eventually be fixed.
163 - There should be a default button. This is activated when the user
166 In glade, you achieve this with the "can default" and "has default"
167 properties in the "basic" pane of the property editor. Glade sets
168 "can default" on all buttons in the action area. This makes the
169 rightmost button the default. If you want another default, enable
170 "has default" on that button. Do not hesitate to make "OK" the
171 default, unless the operation is destructive.
173 In a druid, setting the default button from glade doesn't work.
175 In C, you use gtk_widget_grab_default (widget).
177 - Pressing <Enter> in text fields should activate the default button.
179 This behavior isn't enabled by default. Invoke
180 gnome_dialog_editable_enters (dialog, editable) on all text fields,
181 including the entry fields of spinboxes and combos. If the dialog
182 does not inherit from GnomeDialog, use gnumeric_editable_enters
183 (window, editable) instead.
185 - The dialog should be a transient child of the window it was popped up
186 for. Most window managers will then iconize it with the parent.
188 For modal GnomeDialogs, gnumeric_dialog_run (workbook, dialog) takes
189 care of this. For other dialogs, use gnumeric_set_transient
192 - Clist headers should only be active if they do something useful.
194 Keep them active e.g. if it is possible to change the sort order by
195 clicking on the header. Otherwise, make them passive with
196 gtk_clist_column_titles_passive (clist). There is no way to do this
199 - Dialogs shouldn't flicker when popping up.
201 glade dialogs should have the "visible" property in the "basic" pane
202 set to "No". You should also not call gtk_widget_show / show_all on
203 the dialog before calling gnumeric_dialog_run / gnome_dialog_run,
204 because the dialog_run functions reposition the dialog.
206 Guidelines for designing dialogs
207 --------------------------------
209 Spacing and border properties can be used to tidy a dialog, but this
210 is not much use if everyone uses different values for these properties
211 everywhere. For consistency the following rules have been made, all
212 dialogs in Gnumeric should adhere to these rules :
214 - Any container which can contain only a single widget (GtkWindow,
215 GtkFrame, etc..) should not have it's border set to anything other than
218 - Widgets which can host multiple other widgets must have a border of 4,
219 but only when it's not a child of a widget that already has border (or
220 spacing) set or the (indirect) child of a GtkWindow (this to avoid a
221 superfluous dialog border)
223 - Spacing should always be set to 4 for GtkTable, VBoxes and HBoxes,
224 except for the toplevel VBox or HBox on a dialog which should have a
225 spacing of 8. (we don't want to mess with GnomeDialogs default setup)