Menu

Doxygen_documentation_guidelines

Doxygen Documentation Guidelines

OWLNext uses Doxygen to generate the Reference Documentation and the Compiled HTML Help file. This page documents how we use Doxygen features in OWLNext. The complete manual for Doxygen can be found on the Doxygen site.



Configuration

The Doxygen project files "documentation/*.doxyfile" contain the settings used to generate the OWLNext documentation. The make-file "documentation/makefile" parses the OWLNext version number from the source code and invokes Doxygen to build the documentation. Two targets are available: html (for the online HTML documentation) and html-help (for the self-contained Windows HTML Help file). By default, the make-file will build both. The style sheet file "customdoxygen.css" contains formatting specifications. There are two subdirectories:

  • documentation/images — contains the images included in the generated documentation.
  • documentation/additional — contains general help pages which are not linked to particular OWLNext classes or functions; for example library overviews and concepts.

The rest of the documentation is generated based on Doxygen-style code comments in the source and header files.


General documentation style and standard

The documentation text should use generally accepted writing style as regards capitalisation and punctuation. In particular, Doxygen uses the first full sentence of the documentation block to generate the brief description of an entity, so it is important that it is terminated by a period (full stop).

For inspiration on writing style and standard, look to the Windows API documentation as an example to follow.


Documentation tags

The documentation is contained in special comment blocks. Doxygen supports several styles of comment blocks, but only the triple-slash style should be used in the OWLNext source code. For example:

//
/// Brief description.
/// Detailed description goes here.
//
class _OWLCLASS TFoo {...};

Note that we have configured Doxygen to use the first sentence (until period) as the brief description, so you do not have to use the Doxygen command \brief, and you do not need to separate the brief description from the detailed description. However, for readability in the source code, it is recommended you do so when the brief description spans several lines in the source code.

//
/// The brief description of this foo-ntastic class has been elaborated on
/// over several lines of source code - I should learn to keep things short.
///
/// Detailed description goes here.
//
class _OWLCLASS TFoo {...};

Try to make the brief description helpful, rather than stating the obvious, and don't repeat the name of the entity documented (it is redundant, and must be updated when the entity is renamed, thus increasing maintenance burden). A brief description such as "Defines the TFoo class" is useless. A brief description such as "Derived from TSoyMilk, encapsulates the food stuff also known as bean curd" is good.

By default, a Doxygen documentation block should precede the entity that is documented. However, in some cases, usually for fields and enum values, it is better to put the documentation on the same line, after the entity, in which case the comment should start with ///<. For example:

enum TFooBar
{
  fbItem1, ///< Item 1 has value 0.
  fbItem2, ///< Item 2 has value 1.
  ...


File description comment

It is recommended that all files use the following file description comment at the top of the file:

//
/// \file
/// <description>
//
// Part of OWLNext - the next generation Object Windows Library
// <copyright notices>
//
// For more information, including license details, see
// https://sourceforge.net/projects/owlnext
//

Do not add terms that are incompatible with our license.


Pages

General help pages, which are used for the overview of OWL, are stored in the folder "documentation/additional". Pages are created with the \page tag, followed by an unique page identifier (which should not contain spaces) and followed by the page title. The adopted convention is for the identifier to be same as the title, but in lower-case and with spaces and special symbols removed. This way it is easy to identify links to that page. For example:

/// \page usingpersistentstreamsclasses Using persistent streams classes
/// To persist is to hold to a state or a goal. In computer programs, an example of
...

A page can be divided in sections by using the \section tag, followed by section identifier and title. For example:

/// \section thepersistentstreamsclasslibrary The persistent streams class library
/// This section describes Borland's object streaming support, then explains how to
/// make your objects streamable.
...


Modules

OWLNext classes are logically grouped into modules. These modules are defined and described in the file "trunk/documentation/Additional/modules.dox" by using the tag \defgroup GROUPID GROUPNAME. For example:

/// \defgroup base Base classes
/// TEventHandler, TStreamableBase, and TGdiBase are important base classes. All
/// ...

After defining a module, a class can be added to it using the tag \addtogroup GROUPID and enclosing the class by block tags @{ and @}. For example:

/// \addtogroup commctrl 
/// @{
...
class _OWLCLASS TAnimateCtrl : public TControl 
{
...
}; // end of class declaration.
...
/// @}


Classes

Classes are documented by placing comments preceding the class declaration. For example:

//
/// Encapsulates a button standard control.
/// TButton is an interface class derived from TControl that represents a pushbutton
/// interface element. You must use a TButton to create a button control in a parent
/// ...
//
class _OWLCLASS TButton : public TControl


Functions

Just like the documentation for classes, functions are documented with a Doxygen block including brief and detailed descriptions preceding the function definition. Function parameters are documented with the \param command and referred to by preceding a reference with the \p command. Template parameters are documented with the tparam command. Return values are documented with the \returns command, and exceptions with the \exception command. Important notes can be generated with the \note command. Code examples can be included with the \code and \endcode commands. References to further reading can be made with the \sa command ("see also").

A standard brief description for overloaded functions can be generated using the \overload command.

To show all this in action, here is an example of a documentation block for an overloaded member function:

//
/// \overload
///
/// \tparam TContiguousRangeOfWord could be a std::initializer_list, a
/// C array, a std::array, a std::vector, or any other type that
/// contains a contiguous range of WORD values, and supports std::data
/// and std::size for retrieving the elements and element count,
/// respectively.
///
/// \param glyphs is a contiguous range of glyph indices for the string,
/// which extents are to be retrieved.
/// \param maxExtent is the maximum allowable width, in logical units,
/// of the formatted string.
/// \param extent (optional) is a previous result, passed for recycling
/// of allocated storage.
///
/// The \p extent parameter allows a series of calls to avoid making
/// repeated dynamic allocation. By passing the result of a previous
/// call into the next call, the function will reuse the allocated
/// storage, if possible. Note that the function takes ownership of
/// the resources in the passed argument. Therefore, you must pass the
/// argument using `std::move`.
///
/// \code
/// auto glyphs = std::vector<WORD>{}; // Ready for reuse.
/// auto extent = TTextExtent{}; // Ready for reuse.
/// for (auto& s : strings)
/// {
///   glyphs = dc.GetGlyphIndices(s, GGI_MARK_NONEXISTING_GLYPHS, std::move(glyphs));
///   extent = dc.GetTextExtentExPointI(glyphs, maxExtent, std::move(extent));
///   // ...processing...
/// }
/// \endcode
///
/// \returns On success, TPartialGlyphTextExtent is returned. It
/// encapsulates the dimensions of the bounding box around the glyphs
/// that could fit within the given maximum horizontal extent, and a
/// vector with partial extents of these glyphs. A partial extent is
/// the horizontal extent from the beginning of the string up to, and
/// including, the corresponding glyph.
///
/// \note For rotated text, note that the extent is calculated as if
/// the text is horizontal. The returned extent must be transformed to
/// the rotated text orientation (escapement), if any, explicitly by
/// the caller. However, for the GM_ADVANCED graphics mode and 90
/// degrees orientation the returned extent does not follow this rule.
/// See the Windows API documentation for details.
///          
/// \exception TXGdi is thrown on failure.
///
/// \sa GetTextExtentExPointI(const LPWORD glyphString, int glyphStringSize, int maxExtent, LPINT ncFit, LPINT ncGlyphExtents, TSize &resultSize) const
//

When a class contains many member functions, they can be logically separated into groups named with the Doxygen command \name NAME and enclosed by block tags @{ and @}. For example:

/// \name Accessors
/// @{
int GetNumLines() const;
int GetLineLength(int lineNumber) const;
bool GetLine(LPTSTR str, int strSize, int lineNumber) const;
tstring GetLine(int lineNumber) const;
...
/// @}


Formatting

For a full list of formatting tags, refer to the Doxygen Manual. The following sections describe commonly used tags in the OWLNext documentation.


Don't use vertical alignment

Do not try to pretty the source code by vertically aligning parameters, list items, or anything else in the documentation blocks. It is brittle and won't stand the test of time and maintenance. Use sequential text flow, with line breaks and normal (fixed) indentation, as shown in the examples in this guide. For more about the ills of vertical alignment in source code, see Programming Style at Wikipedia.


Lists

Unordered lists are created by preceding the comment text with a hyphen -. For example:

/// As the common base class for all interface objects, TWindow provides uniform ways to
///
/// - maintain the relationship between interface objects and interface elements,
/// including creating and destroying the objects and elements,
/// - handle parent-child relationships between interface objects, and
/// - register new Windows window classes.
///

Ordered lists are created by using a hyphen followed by hash -#". For example:

/// Abstract classes are classes with pure virtual member functions that you must
/// override to provide some behavior. They serve two main purposes:
///
/// -# They provide a conceptual framework on which to build other classes.
/// -# On a practical level, they reduce coding effort.
///

Lists must be separated from text that follows by placing one empty comment line after the list.


Code examples

Example code is enclosed between \code and \endcode tags. For example:

/// Usage:
/// \code
/// TButton b(parent, IDC_BUTTON1);
/// \endcode


Images

Images are included by using the \image tag. For example:

/// \image html bm60.BMP

The image file must exist and be placed in the folder "documentation/images".


Tables

Tables can be defined using HTML syntax. Note that the table headers should use <th> elements.


Doxygen will autogenerate links to other entities it recognises in all text. For these rules, see Automatic link generation in the Doxygen documentation. In particular, if you want an automatic link generated to another function overload, you need to include the full function signature (which includes const behind the parameter list, if it is a const-member-function).

Explicit links to documented entities can be made using Markdown syntax [link text](@ref entity). Explicit links to external URLs can be created with the Markdown syntax [link text](URL) or the HTML <a> tag.

For more ways to link and create references, see Markdown support in the Doxygen documentation.

Note: Doxygen detects explicit references to symbols in the global namespace that are made using the prefix :: as an explicit request for auto-linking. For example, Doxygen will try to auto-link the reference to EndDialog in the following text: Destroy calls the Window function ::EndDialog. Throughout the OWLNext documentation, Windows API functions are usually referred to this way. To avoid Doxygen warning about failed auto-linking on such references, you should prefix the function name by the percent character. For example: Destroy calls the Windows function ::%EndDialog.


Related

Feature Requests: #172
Feature Requests: #193
Wiki: Coding_Standards
Wiki: Contributing

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.