36cae329801cf80bdb1e27900a4a102bf7fc9998
[alexxy/gromacs.git] / src / gromacs / onlinehelp / helptopic.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2014,2015, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \libinternal \file
36  * \brief
37  * Declares helper classes for implementing gmx::IHelpTopic.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inlibraryapi
41  * \ingroup module_onlinehelp
42  */
43 #ifndef GMX_ONLINEHELP_HELPTOPIC_H
44 #define GMX_ONLINEHELP_HELPTOPIC_H
45
46 #include <memory>
47
48 #include "gromacs/onlinehelp/ihelptopic.h"
49 #include "gromacs/utility/classhelpers.h"
50 #include "gromacs/utility/stringutil.h"
51
52 namespace gmx
53 {
54
55 /*! \libinternal \brief
56  * Abstract base class for help topics that have simple text and no subtopics.
57  *
58  * This class implements subtopic-related methods from IHelpTopic such
59  * that there are no subtopics.  writeHelp() is also implemented such that it
60  * uses HelpTopicContext::writeTextBlock() to write out the text returned by a
61  * new virtual method helpText().
62  *
63  * \see SimpleHelpTopic
64  *
65  * \inlibraryapi
66  * \ingroup module_onlinehelp
67  */
68 class AbstractSimpleHelpTopic : public IHelpTopic
69 {
70     public:
71         virtual const char *name() const  = 0;
72         virtual const char *title() const = 0;
73
74         virtual bool hasSubTopics() const;
75         virtual const IHelpTopic *findSubTopic(const char *name) const;
76
77         virtual void writeHelp(const HelpWriterContext &context) const;
78
79     protected:
80         /*! \brief
81          * Returns the help text for this topic.
82          *
83          * writeHelp() calls this method to obtain the actual text to format
84          * for the topic.  Markup substitution etc. is done automatically by
85          * writeHelp().
86          */
87         virtual std::string helpText() const = 0;
88 };
89
90 /*! \libinternal \brief
91  * Abstract base class for help topics that have simple text and subtopics.
92  *
93  * This class implements an internal container for subtopics and provides
94  * public methods for adding subtopics (as IHelpTopic objects).
95  * Subtopic-related methods from IHelpTopic are implemented to access
96  * the internal container.  writeHelp() is also implemented such that it
97  * uses HelpTopicContext::writeTextBlock() to write out the text returned by a
98  * new virtual method helpText(), and a list of subtopics is written after the
99  * actual text.
100  *
101  * \see CompositeHelpTopic
102  *
103  * \inlibraryapi
104  * \ingroup module_onlinehelp
105  */
106 class AbstractCompositeHelpTopic : public IHelpTopic
107 {
108     public:
109         AbstractCompositeHelpTopic();
110         virtual ~AbstractCompositeHelpTopic();
111
112         virtual const char *name() const  = 0;
113         virtual const char *title() const = 0;
114
115         virtual bool hasSubTopics() const;
116         virtual const IHelpTopic *findSubTopic(const char *name) const;
117
118         virtual void writeHelp(const HelpWriterContext &context) const;
119
120         /*! \brief
121          * Adds a given topic as a subtopic of this topic.
122          *
123          * \param   topic  Topis to add.
124          * \throws  std::bad_alloc if out of memory.
125          *
126          * This topic takes ownership of the object.
127          *
128          * \see registerSubTopic()
129          */
130         void addSubTopic(HelpTopicPointer topic);
131         /*! \brief
132          * Registers a subtopic of a certain type to this topic.
133          *
134          * \tparam  Topic  Type of topic to register.
135          * \throws  std::bad_alloc if out of memory.
136          *
137          * \p Topic must be default-constructible and implement
138          * IHelpTopic.
139          *
140          * This method is provided as a convenient alternative to addSubTopic()
141          * for cases where each topic is implemented by a different type
142          * (which is a common case outside unit tests).
143          */
144         template <class Topic>
145         void registerSubTopic()
146         {
147             addSubTopic(HelpTopicPointer(new Topic));
148         }
149
150     protected:
151         //! \copydoc gmx::AbstractSimpleHelpTopic::helpText()
152         virtual std::string helpText() const = 0;
153
154         /*! \brief
155          * Writes the list of subtopics.
156          *
157          * \param[in] context Context for writing the help.
158          * \param[in] title  Title for the written list.
159          * \returns   true if anything was printed.
160          * \throws    std::bad_alloc if out of memory.
161          * \throws    FileIOError on any I/O error.
162          *
163          * Subtopics with empty titles are skipped from the list.
164          * If there would be no subtopics in the list, \p title is not printed
165          * either.
166          *
167          * This method is provided for cases where helpText() does not provide
168          * the needed flexibility and the derived class needs to override
169          * writeHelp().  This method can then be called to print the same
170          * subtopic list that is printed by the default writeHelp()
171          * implementation.
172          */
173         bool writeSubTopicList(const HelpWriterContext &context,
174                                const std::string       &title) const;
175
176     private:
177         class Impl;
178
179         PrivateImplPointer<Impl> impl_;
180 };
181
182 /*! \cond libapi */
183 /*! \libinternal \brief
184  * Smart pointer type to manage a AbstractCompositeHelpTopic object.
185  *
186  * \inlibraryapi
187  */
188 typedef std::unique_ptr<AbstractCompositeHelpTopic>
189     CompositeHelpTopicPointer;
190 //! \endcond
191
192 /*! \libinternal \brief
193  * Template for simple implementation of AbstractSimpleHelpTopic.
194  *
195  * \tparam HelpText Struct that defines the data for the topic.
196  *
197  * \p HelpText should have public static members \c "const char name[]",
198  * \c "const char title[]" and \c "const char *const text[]".
199  *
200  * Typical use:
201  * \code
202    struct ExampleHelpText
203    {
204        static const char name[];
205        static const char title[];
206        static const char *const text[];
207    };
208
209    const char ExampleHelpText::name[] = "example";
210    const char ExampleHelpText::title[] =
211        "Example title";
212    const char *const ExampleHelpText::text[] = {
213        "Text for the topic.",
214        "More text for the topic."
215    };
216
217    typedef SimpleHelpTopic<ExampleHelpText> ExampleHelpTopic;
218  * \endcode
219  *
220  * \inlibraryapi
221  * \ingroup module_onlinehelp
222  */
223 template <class HelpText>
224 class SimpleHelpTopic : public AbstractSimpleHelpTopic
225 {
226     public:
227         virtual const char *name() const
228         {
229             return HelpText::name;
230         }
231         virtual const char *title() const
232         {
233             return HelpText::title;
234         }
235
236     protected:
237         virtual std::string helpText() const
238         {
239             return joinStrings(HelpText::text, "\n");
240         }
241 };
242
243 /*! \libinternal \brief
244  * Template for simple implementation of AbstractCompositeHelpTopic.
245  *
246  * \tparam HelpText Struct that defines the data for the topic.
247  *
248  * Used similarly to SimpleHelpTopic.
249  * \p HelpText should satisfy the same criteria as for SimpleHelpTopic.
250  *
251  * \see SimpleHelpTopic
252  *
253  * \inlibraryapi
254  * \ingroup module_onlinehelp
255  */
256 template <class HelpText>
257 class CompositeHelpTopic : public AbstractCompositeHelpTopic
258 {
259     public:
260         // copydocs are needed with Doxygen 1.8.10, but not 1.8.5...
261         //! \copydoc gmx::AbstractCompositeHelpTopic::name()
262         virtual const char *name() const
263         {
264             return HelpText::name;
265         }
266         //! \copydoc gmx::AbstractCompositeHelpTopic::title()
267         virtual const char *title() const
268         {
269             return HelpText::title;
270         }
271
272     protected:
273         //! \copydoc gmx::AbstractCompositeHelpTopic::helpText()
274         virtual std::string helpText() const
275         {
276             return joinStrings(HelpText::text, "\n");
277         }
278 };
279
280 } // namespace gmx
281
282 #endif