1 #ifndef _LinkText_h_
2 #define _LinkText_h_
3 
4 #include <GG/TextControl.h>
5 
6 #include <boost/signals2/signal.hpp>
7 
8 
9 /// A class that can be subclassed to give types of links decorations in link text.
10 /// "Decorations" here mean mostly wrapping the text in some styling tag or other,
11 /// but a decorator is free to manipulate the decorated text in any way.
12 class LinkDecorator {
13 public:
14     /** \name Structors */ //@{
LinkDecorator()15     LinkDecorator() {};
~LinkDecorator()16     virtual ~LinkDecorator() {};
17     //@}
18 
19     /// Gets called for each link of the type this decorator is assigned to.
20     /// The return value is shown to the user as the link.
21     /// The default implementation wraps content in an rgba tag that colors it by ClientUI::DefaultLinkColor
22     /// \param target The target of the link. Usually an id of something or the name of an encyclopedia entry.
23     /// \param content The text the link tag was wrapped around.
24     /// \returns The text that should be shown to the user in the place of content
25     virtual std::string Decorate(const std::string& target, const std::string& content) const;
26 
27     /// Gets called when the mouse hovers over a link of the type this decorator is assigned to.
28     /// The return value is shown to the user as the link.
29     /// The default implementation wraps content in an rgba tag that colors it by ClientUI::RolloverLinkColor
30     /// \param target The target of the link. Usually an id of something or the name of an encyclopedia entry.
31     /// \param content The text the link tag was wrapped around.
32     /// \returns The text that should be shown to the user in the place of content
33     virtual std::string DecorateRollover(const std::string& target, const std::string& content) const;
34 
35 protected:
36     /// Try to convert str to int. Returns -1 if \param str conversion to an
37     /// int fails.  Helper for interpreting \param str as an ID of an object
38     /// in the game universe.
39     static int CastStringToInt(const std::string& str);
40 };
41 
42 // Should be unique_ptr, but we don't have c++11
43 typedef std::shared_ptr<LinkDecorator> LinkDecoratorPtr;
44 
45 class ColorByOwner: public LinkDecorator {
46 public:
47     std::string Decorate(const std::string& object_id_str, const std::string& content) const override;
48 };
49 
50 class PathTypeDecorator : public LinkDecorator {
51 public:
52     std::string Decorate(const std::string& path_type, const std::string& content) const override;
53     std::string DecorateRollover(const std::string& path_type, const std::string& content) const override;
54 };
55 
56 class TextLinker {
57 public:
58     /** \name Structors */ //@{
59     TextLinker();
60     virtual ~TextLinker();
61     //@}
62 
63     /// Sets the link decorator for a link type.
64     /// \param link_type The link type (tag) to be decorated. Eg. "planet"
65     /// \param decorator The decorator to use. Assumes ownership.
66     void SetDecorator(const std::string& link_type, LinkDecorator* decorator);
67 
68     ///< link clicked signals: first string is the link type, second string is the specific item clicked
69     mutable boost::signals2::signal<void (const std::string&, const std::string&)> LinkClickedSignal;
70     mutable boost::signals2::signal<void (const std::string&, const std::string&)> LinkDoubleClickedSignal;
71     mutable boost::signals2::signal<void (const std::string&, const std::string&)> LinkRightClickedSignal;
72 
73     static const std::string ENCYCLOPEDIA_TAG;
74     static const std::string GRAPH_TAG;
75     static const std::string URL_TAG;
76     /** Tag for clickable link to open users file manager at a specified directory */
77     static const std::string BROWSE_PATH_TAG;
78 
79 protected:
80     void Render_();
81     void LClick_(const GG::Pt& pt, GG::Flags<GG::ModKey> mod_keys);
82     void RClick_(const GG::Pt& pt, GG::Flags<GG::ModKey> mod_keys);
83     void LDoubleClick_(const GG::Pt& pt, GG::Flags<GG::ModKey> mod_keys);
84     void MouseHere_(const GG::Pt& pt, GG::Flags<GG::ModKey> mod_keys);
85     void MouseLeave_();
86 
87     virtual const std::vector<GG::Font::LineData>&  GetLineData() const = 0;
88     virtual const std::shared_ptr<GG::Font>&        GetFont() const = 0;
89 
90     virtual GG::Pt              TextUpperLeft() const = 0;
91     virtual GG::Pt              TextLowerRight() const = 0;
92     virtual void                SetLinkedText(const std::string& str) = 0;
93     virtual const std::string&  RawText() const = 0;    ///< returns text being displayed before any link formatting is added
94 
95     void FindLinks();                       ///< finds the links in the text, with which to populate m_links.
96     void LocateLinks();                     ///< calculates the physical locations of the links in m_links
97     void MarkLinks();                       ///< wraps text for each link in text formatting tags so that the links appear visually distinct from other text
98     int  GetLinkUnderPt(const GG::Pt& pt);  ///< returns the index of the link under screen coordinate \a pt, or -1 if none
99 private:
100     struct Link;
101 
102     std::string LinkDefaultFormatTag(const Link& link, const std::string& content) const;
103     std::string LinkRolloverFormatTag(const Link& link, const std::string& content) const;
104 
105     std::vector<Link>                       m_links;
106     int                                     m_rollover_link;
107     std::map<std::string, LinkDecoratorPtr> m_decorators;
108     static const LinkDecorator DEFAULT_DECORATOR;
109 };
110 
111 /** Allows text that the user sees to emit signals when clicked, and indicates
112   * to the user visually which text represents a link.  There is one type of
113   * signal for each type of ZoomTo*() method in ClientUI.  This allows any text
114   * that refers to game elements to be tagged as such and clicked by the user,
115   * with the appropriate ClientUI response function called.
116   * The followig tags are currently supported:
117   * \verbatim
118   * <planet ID>
119   * <system ID>
120   * <fleet ID>
121   * <ship ID>
122   * <building ID>
123   * <empire ID>
124   * <tech [string]>
125   * <buildingtype [string]>
126   * <special [string]>
127   * <shiphull [string]>
128   * <shippart [string]>
129   * <species [string]>
130   * <encyclopedia [string]>\endverbatim
131   * The ID parameters refer to the UniverseObjects that should be zoomed to for
132   * each link.  Encyclopedia entries and content items are referred to by strings.
133   * <br><br>Note that for link tags to be correctly handled, they must not
134   * overlap each other at all, even though overlap with regular GG::Font tags
135   * is fine. */
136 class LinkText : public GG::TextControl, public TextLinker {
137 public:
138     /** \name Structors */ //@{
139     LinkText(GG::X x, GG::Y y, GG::X w, const std::string& str, const std::shared_ptr<GG::Font>& font, GG::Flags<GG::TextFormat> format = GG::FORMAT_NONE, GG::Clr color = GG::CLR_BLACK); ///< ctor taking a font directly
140 
141     /** ctor that does not require window size.
142         Window size is determined from the string and font; the window will be large enough to fit the text as rendered,
143         and no larger.  \see DynamicText::DynamicText() */
144     LinkText(GG::X x, GG::Y y, const std::string& str, const std::shared_ptr<GG::Font>& font, GG::Clr color = GG::CLR_BLACK);
145     //@}
146 
147     /** \name Accessors */ //@{
148     GG::Pt TextUpperLeft() const override;
149     GG::Pt TextLowerRight() const override;
150 
151     const std::vector<GG::Font::LineData>& GetLineData() const override;
152     const std::shared_ptr<GG::Font>& GetFont() const override;
153 
154     /** Returns text displayed before link formatting is added. */
155     const std::string& RawText() const override;
156     //@}
157 
158     /** \name Mutators */ //@{
159     void Render() override;
160     void LClick(const GG::Pt& pt, GG::Flags<GG::ModKey> mod_keys) override;
161     void RClick(const GG::Pt& pt, GG::Flags<GG::ModKey> mod_keys) override;
162     void MouseHere(const GG::Pt& pt, GG::Flags<GG::ModKey> mod_keys) override;
163     void MouseLeave() override;
164     void SizeMove(const GG::Pt& ul, const GG::Pt& lr) override;
165 
166     /** sets the text to \a str; may resize the window.  If the window was
167         constructed to fit the size of the text (i.e. if the second ctor type
168         was used), calls to this function cause the window to be resized to
169         whatever space the newly rendered text occupies. */
170     void SetText(const std::string& str) override;
171     //@}
172 
173 private:
174     void SetLinkedText(const std::string& str) override;
175 
176     std::string     m_raw_text;
177 };
178 
179 
180 /// Helper for generating a link string with content from a stringtable entry
181 std::string LinkTaggedText(const std::string& tag, const std::string& stringtable_entry);
182 
183 /// Helper for generating a link string
184 std::string LinkTaggedIDText(const std::string& tag, int id, const std::string& text);
185 
186 /// Helper for generating a link string with preset display text (not to be looked up in stringtable)
187 std::string LinkTaggedPresetText(const std::string& tag, const std::string& stringtable_entry, const std::string& display_text);
188 
189 /// Free function to register link tags that TextLinker knows of.  This allows GG::Font to remove
190 /// them so that they will not be rendered.  Must be called at least once before text with embedded
191 /// XML tags is handled by GG::Font
192 void RegisterLinkTags();
193 
194 #endif // _LinkText_h_
195