f67bc8e993b17702412700a44210bcda92154e9c
[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, 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 and functions for implementing
38  * gmx::HelpTopicInterface.
39  *
40  * \author Teemu Murtola <teemu.murtola@gmail.com>
41  * \inlibraryapi
42  * \ingroup module_onlinehelp
43  */
44 #ifndef GMX_ONLINEHELP_HELPTOPIC_H
45 #define GMX_ONLINEHELP_HELPTOPIC_H
46
47 #include "../utility/common.h"
48 #include "../utility/stringutil.h"
49 #include "../utility/uniqueptr.h"
50
51 #include "helptopicinterface.h"
52
53 namespace gmx
54 {
55
56 /*! \cond libapi */
57 /*! \libinternal \brief
58  * Helper for writing simple help text.
59  *
60  * \param[in] context Context for writing the help.
61  * \param[in] topic   Topic to write the help for (used for title).
62  * \param[in] text    Text to write for the topic.
63  * \throws    std::bad_alloc if out of memory.
64  * \throws    FileIOError on any I/O error.
65  *
66  * Formats basic help by writing a title (obtained from \p topic), followed by
67  * \p text with markup substituted and lines properly wrapped.
68  *
69  * \inlibraryapi
70  */
71 void writeBasicHelpTopic(const HelpWriterContext  &context,
72                          const HelpTopicInterface &topic,
73                          const std::string        &text);
74 //! \endcond
75
76 /*! \libinternal \brief
77  * Abstract base class for help topics that have simple text and no subtopics.
78  *
79  * This class implements subtopic-related methods from HelpTopicInterface such
80  * that there are no subtopics.  writeHelp() is also implemented such that it
81  * uses writeBasicHelpTopic() to write out the text returned by a new virtual
82  * method helpText().
83  *
84  * \see SimpleHelpTopic
85  *
86  * \inlibraryapi
87  * \ingroup module_onlinehelp
88  */
89 class AbstractSimpleHelpTopic : public HelpTopicInterface
90 {
91     public:
92         virtual const char *name() const  = 0;
93         virtual const char *title() const = 0;
94
95         virtual bool hasSubTopics() const;
96         virtual const HelpTopicInterface *findSubTopic(const char *name) const;
97
98         virtual void writeHelp(const HelpWriterContext &context) const;
99
100     protected:
101         /*! \brief
102          * Returns the help text for this topic.
103          *
104          * writeHelp() calls this method to obtain the actual text to format
105          * for the topic.  Markup substitution etc. is done automatically by
106          * writeHelp().
107          */
108         virtual std::string helpText() const = 0;
109 };
110
111 /*! \libinternal \brief
112  * Abstract base class for help topics that have simple text and subtopics.
113  *
114  * This class implements an internal container for subtopics and provides
115  * public methods for adding subtopics (as HelpTopicInterface objects).
116  * Subtopic-related methods from HelpTopicInterface are implemented to access
117  * the internal container.  writeHelp() is also implemented such that it
118  * uses writeBasicHelpTopic() to write out the text returned by a new virtual
119  * method helpText(), and a list of subtopics is written after the actual text.
120  *
121  * \see CompositeHelpTopic
122  *
123  * \inlibraryapi
124  * \ingroup module_onlinehelp
125  */
126 class AbstractCompositeHelpTopic : public HelpTopicInterface
127 {
128     public:
129         AbstractCompositeHelpTopic();
130         virtual ~AbstractCompositeHelpTopic();
131
132         virtual const char *name() const  = 0;
133         virtual const char *title() const = 0;
134
135         virtual bool hasSubTopics() const;
136         virtual const HelpTopicInterface *findSubTopic(const char *name) const;
137
138         virtual void writeHelp(const HelpWriterContext &context) const;
139
140         /*! \brief
141          * Adds a given topic as a subtopic of this topic.
142          *
143          * \param   topic  Topis to add.
144          * \throws  std::bad_alloc if out of memory.
145          *
146          * This topic takes ownership of the object.
147          *
148          * \see registerSubTopic()
149          */
150         void addSubTopic(HelpTopicPointer topic);
151         /*! \brief
152          * Registers a subtopic of a certain type to this topic.
153          *
154          * \tparam  Topic  Type of topic to register.
155          * \throws  std::bad_alloc if out of memory.
156          *
157          * \p Topic must be default-constructible and implement
158          * HelpTopicInterface.
159          *
160          * This method is provided as a convenient alternative to addSubTopic()
161          * for cases where each topic is implemented by a different type
162          * (which is a common case outside unit tests).
163          */
164         template <class Topic>
165         void registerSubTopic()
166         {
167             addSubTopic(HelpTopicPointer(new Topic));
168         }
169
170     protected:
171         //! \copydoc gmx::AbstractSimpleHelpTopic::helpText()
172         virtual std::string helpText() const = 0;
173
174         /*! \brief
175          * Writes the list of subtopics.
176          *
177          * \param[in] context Context for writing the help.
178          * \param[in] title  Title for the written list.
179          * \returns   true if anything was printed.
180          * \throws    std::bad_alloc if out of memory.
181          * \throws    FileIOError on any I/O error.
182          *
183          * Subtopics with empty titles are skipped from the list.
184          * If there would be no subtopics in the list, \p title is not printed
185          * either.
186          *
187          * This method is provided for cases where helpText() does not provide
188          * the needed flexibility and the derived class needs to override
189          * writeHelp().  This method can then be called to print the same
190          * subtopic list that is printed by the default writeHelp()
191          * implementation.
192          */
193         bool writeSubTopicList(const HelpWriterContext &context,
194                                const std::string       &title) const;
195
196     private:
197         class Impl;
198
199         PrivateImplPointer<Impl> impl_;
200 };
201
202 /*! \cond libapi */
203 /*! \libinternal \brief
204  * Smart pointer type to manage a AbstractCompositeHelpTopic object.
205  *
206  * \inlibraryapi
207  */
208 typedef gmx_unique_ptr<AbstractCompositeHelpTopic>::type
209     CompositeHelpTopicPointer;
210 //! \endcond
211
212 /*! \libinternal \brief
213  * Template for simple implementation of AbstractSimpleHelpTopic.
214  *
215  * \tparam HelpText Struct that defines the data for the topic.
216  *
217  * \p HelpText should have public static members \c "const char name[]",
218  * \c "const char title[]" and \c "const char *const text[]".
219  *
220  * Typical use:
221  * \code
222    struct ExampleHelpText
223    {
224        static const char name[];
225        static const char title[];
226        static const char *const text[];
227    };
228
229    const char ExampleHelpText::name[] = "example";
230    const char ExampleHelpText::title[] =
231        "Example title";
232    const char *const ExampleHelpText::text[] = {
233        "Text for the topic.",
234        "More text for the topic."
235    };
236
237    typedef SimpleHelpTopic<ExampleHelpText> ExampleHelpTopic;
238  * \endcode
239  *
240  * \inlibraryapi
241  * \ingroup module_onlinehelp
242  */
243 template <class HelpText>
244 class SimpleHelpTopic : public AbstractSimpleHelpTopic
245 {
246     public:
247         virtual const char *name() const
248         {
249             return HelpText::name;
250         }
251         virtual const char *title() const
252         {
253             return HelpText::title;
254         }
255
256     protected:
257         virtual std::string helpText() const
258         {
259             return concatenateStrings(HelpText::text);
260         }
261 };
262
263 /*! \libinternal \brief
264  * Template for simple implementation of AbstractCompositeHelpTopic.
265  *
266  * \tparam HelpText Struct that defines the data for the topic.
267  *
268  * Used similarly to SimpleHelpTopic.
269  * \p HelpText should satisfy the same criteria as for SimpleHelpTopic.
270  *
271  * \see SimpleHelpTopic
272  *
273  * \inlibraryapi
274  * \ingroup module_onlinehelp
275  */
276 template <class HelpText>
277 class CompositeHelpTopic : public AbstractCompositeHelpTopic
278 {
279     public:
280         virtual const char *name() const
281         {
282             return HelpText::name;
283         }
284         virtual const char *title() const
285         {
286             return HelpText::title;
287         }
288
289     protected:
290         virtual std::string helpText() const
291         {
292             return concatenateStrings(HelpText::text);
293         }
294 };
295
296 } // namespace gmx
297
298 #endif