044a15c0d0ef8ca6786d11a52edd84ddca4def63
[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,2018,2019, 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     const char* name() const override  = 0;
72     const char* title() const override = 0;
73
74     bool              hasSubTopics() const override;
75     const IHelpTopic* findSubTopic(const char* name) const override;
76
77     void writeHelp(const HelpWriterContext& context) const override;
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     ~AbstractCompositeHelpTopic() override;
111
112     const char* name() const override  = 0;
113     const char* title() const override = 0;
114
115     bool              hasSubTopics() const override;
116     const IHelpTopic* findSubTopic(const char* name) const override;
117
118     void writeHelp(const HelpWriterContext& context) const override;
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, const std::string& title) const;
174
175 private:
176     class Impl;
177
178     PrivateImplPointer<Impl> impl_;
179 };
180
181 /*! \cond libapi */
182 /*! \libinternal \brief
183  * Smart pointer type to manage a AbstractCompositeHelpTopic object.
184  *
185  * \inlibraryapi
186  */
187 typedef std::unique_ptr<AbstractCompositeHelpTopic> CompositeHelpTopicPointer;
188 //! \endcond
189
190 /*! \libinternal \brief
191  * Template for simple implementation of AbstractSimpleHelpTopic.
192  *
193  * \tparam HelpText Struct that defines the data for the topic.
194  *
195  * \p HelpText should have public static members \c "const char name[]",
196  * \c "const char title[]" and \c "const char *const text[]".
197  *
198  * Typical use:
199  * \code
200    struct ExampleHelpText
201    {
202        static const char name[];
203        static const char title[];
204        static const char *const text[];
205    };
206
207    const char ExampleHelpText::name[] = "example";
208    const char ExampleHelpText::title[] =
209        "Example title";
210    const char *const ExampleHelpText::text[] = {
211        "Text for the topic.",
212        "More text for the topic."
213    };
214
215    typedef SimpleHelpTopic<ExampleHelpText> ExampleHelpTopic;
216  * \endcode
217  *
218  * \inlibraryapi
219  * \ingroup module_onlinehelp
220  */
221 template<class HelpText>
222 class SimpleHelpTopic : public AbstractSimpleHelpTopic
223 {
224 public:
225     const char* name() const override { return HelpText::name; }
226     const char* title() const override { return HelpText::title; }
227
228 protected:
229     std::string helpText() const override { return joinStrings(HelpText::text, "\n"); }
230 };
231
232 /*! \libinternal \brief
233  * Template for simple implementation of AbstractCompositeHelpTopic.
234  *
235  * \tparam HelpText Struct that defines the data for the topic.
236  *
237  * Used similarly to SimpleHelpTopic.
238  * \p HelpText should satisfy the same criteria as for SimpleHelpTopic.
239  *
240  * \see SimpleHelpTopic
241  *
242  * \inlibraryapi
243  * \ingroup module_onlinehelp
244  */
245 template<class HelpText>
246 class CompositeHelpTopic : public AbstractCompositeHelpTopic
247 {
248 public:
249     // copydocs are needed with Doxygen 1.8.10, but not 1.8.5...
250     //! \copydoc gmx::AbstractCompositeHelpTopic::name()
251     const char* name() const override { return HelpText::name; }
252     //! \copydoc gmx::AbstractCompositeHelpTopic::title()
253     const char* title() const override { return HelpText::title; }
254
255 protected:
256     //! \copydoc gmx::AbstractCompositeHelpTopic::helpText()
257     std::string helpText() const override { return joinStrings(HelpText::text, "\n"); }
258 };
259
260 } // namespace gmx
261
262 #endif