Export: move the single-sheet selection logic out of the savers
[gnumeric.git] / HACKING
bloba95c0255c50154e2567dc469597ef5ac1c05cae1
1 Working on Gnumeric
2 -------------------
4    When writing Gnumeric our priorities are
6         1) Correctness.
7         2) Maintainable & Documented
8         3) Modular and well designed
9         and a distant
10         4) Fast
12     When you submit code to me for inclusion in Gnumeric, or when you commit
13 code directly to the Git 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 by 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). 
36    
37    Emacs users can get the default indentation style with this:
38   (set-c-style "K&R")
39   (setq c-basic-offset 8)
41    On top of that, you will have to:
43         - Follow the Gtk+ cleanliness conventions for function
44           prototypes.
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
80           style;
81                 /* ie. use this for
82                  * multi-line comments
83                  */
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
126   an example.
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
155   them alone.
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
164   presses <Enter>.
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.
187   
188   For modal GnomeDialogs, gnumeric_dialog_run (workbook, dialog) takes
189   care of this. For other dialogs, use gnumeric_set_transient
190   (context, window).
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
197   in glade, yet.
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
216   0.
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)