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> registerSubTopic()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: name()225 const char* name() const override { return HelpText::name; } title()226 const char* title() const override { return HelpText::title; } 227 228 protected: helpText()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() name()251 const char* name() const override { return HelpText::name; } 252 //! \copydoc gmx::AbstractCompositeHelpTopic::title() title()253 const char* title() const override { return HelpText::title; } 254 255 protected: 256 //! \copydoc gmx::AbstractCompositeHelpTopic::helpText() helpText()257 std::string helpText() const override { return joinStrings(HelpText::text, "\n"); } 258 }; 259 260 } // namespace gmx 261 262 #endif 263