1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2008 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef WANCHOR_H_ 8 #define WANCHOR_H_ 9 10 #include <Wt/WContainerWidget.h> 11 #include <Wt/WJavaScript.h> 12 #include <Wt/WImage.h> 13 #include <Wt/WLink.h> 14 15 namespace Wt { 16 17 namespace Impl { 18 class AreaWidget; 19 } 20 21 /*! \class WAnchor Wt/WAnchor.h Wt/WAnchor.h 22 * \brief A widget that represents an HTML anchor (to link to other documents). 23 * 24 * Use an anchor to link to another web page, document, internal 25 * application path or a resource (which specifies 26 * application-dependent content that may be generated by your 27 * application on demand). The anchor may contain a label text, an 28 * image, or any other widget (as it inherits from 29 * WContainerWidget). 30 * 31 * If you link to a document or external url, and do not want the 32 * application to terminate when the user follows the anchor, you must 33 * use \link WLink.setTarget(LinkTarget) 34 * link.setTarget(LinkTarget::NewWindow)\endlink. Even for non-HTML 35 * documents, this may be important since pending Ajax requests are 36 * cancelled if documents are not served within the browser window in 37 * certain browsers. 38 * 39 * \if cpp 40 * Usage example: 41 * \code 42 * WAnchor *a; 43 * 44 * // Create an anchor that links to a URL 45 * a = addWidget(std::make_unique<Wt::WAnchor>("https://www.webtoolkit.eu/", "Wt web toolkit")); 46 * 47 * // Create an anchor that links to an internal path 48 * a = addWidget(std::make_unique<Wt::WAnchor>( 49 * WLink(LinkType::InternalPath, "/docs/" + myDocName()), "Doc")); 50 * // and listen to the corresponding change in internal path 51 * WApplication::instance()->internalPathChanged().connect(this, &DocsListWidget::onInternalPathChange); 52 * 53 * // Create an anchor that links to a resource 54 * WResource *r = addChild(std::make_unique<PdfResource>()); // serializes to a PDF file. 55 * a = addWidget(std::make_unique<Wt::WAnchor>(r, "PDF version")); 56 * \endcode 57 * \endif 58 * 59 * %WAnchor is an \link WWidget::setInline(bool) inline \endlink widget. 60 * 61 * <h3>CSS</h3> 62 * 63 * The widget corresponds to the HTML <tt><a></tt> tag and does 64 * not provide styling. It can be styled using inline or external CSS 65 * as appropriate. 66 */ 67 class WT_API WAnchor : public WContainerWidget 68 { 69 public: 70 /*! \brief Creates an anchor. 71 */ 72 WAnchor(); 73 74 /*! \brief Creates an anchor for the given link. 75 * 76 * The \p link may point to a URL, a dynamic resource, or an 77 * internal path. 78 * 79 * \sa setLink() 80 */ 81 WAnchor(const WLink& link); 82 83 /*! \brief Creates an anchor for the given link with a text. 84 * 85 * The \p link may point to a URL, a dynamic resource, or an 86 * internal path. 87 * 88 * \sa setLink(), setText() 89 */ 90 WAnchor(const WLink& link, const WString& text); 91 92 /*! \brief Creates an anchor for the given link with an image. 93 * 94 * \if cpp 95 * Ownership of the image is transferred to the anchor. 96 * \endif 97 * 98 * \sa setLink(), setImage() 99 */ 100 WAnchor(const WLink& link, std::unique_ptr<WImage> image); 101 102 /*! \brief Sets the link. 103 * 104 * The link may hold a URL, a resource, or an internal path. 105 * 106 * When the link points to a \link LinkType::Resource resource\endlink, 107 * the contents of the link may be generated by your application on 108 * demand. 109 * 110 * When the link points to an \link LinkType::InternalPath internal 111 * path\endlink, activating the anchor will change the \link 112 * WApplication::internalPath() application's internal path\endlink 113 * or open a new session with the given path as \link 114 * WEnvironment::internalPath() initial path\endlink). This is the 115 * easiest way to let the application participate in browser 116 * history, and generate URLs that are bookmarkable and search 117 * engine friendly. 118 */ 119 void setLink(const WLink& link); 120 121 /*! \brief Returns the link. 122 * 123 * \sa setLink() 124 */ link()125 const WLink& link() const { return linkState_.link; } 126 127 /*! \brief Sets the label text 128 * 129 * If no text was previously set, a new WText widget is added using 130 * addWidget(). 131 */ 132 void setText(const WString& text); 133 134 /*! \brief Returns the label text. 135 * 136 * Returns an empty string if no label was set. 137 * 138 * \sa setText() 139 */ 140 const WString& text() const; 141 142 /*! \brief Configures text word wrapping. 143 * 144 * When \p wordWrap is \c true, the text set with setText() may be 145 * broken up over multiple lines. When \p wordWrap is \c false, the 146 * text will displayed on a single line, unless the text contains 147 * <tt><br /></tt> tags or other block-level tags. 148 * 149 * The default value is \c true. 150 * 151 * \sa wordWrap() 152 */ 153 void setWordWrap(bool wordWrap); 154 155 /*! \brief Configures the text format. 156 * 157 * The default text format is TextFormat::XHTML. 158 * 159 * \sa WText::setTextFormat() 160 */ 161 void setTextFormat(TextFormat format); 162 163 /*! \brief Returns the text format. 164 * 165 * \sa setTextFormat() 166 */ 167 TextFormat textFormat() const; 168 169 /*! \brief Returns whether the widget may break lines. 170 * 171 * \sa setWordWrap(bool) 172 */ 173 bool wordWrap() const; 174 175 /*! \brief Sets an image. 176 * 177 * If an image was previously set, it is deleted. The \p image 178 * is added using addWidget(). 179 */ 180 void setImage(std::unique_ptr<WImage> image); 181 182 /*! \brief Returns the image. 183 * 184 * Returns \c 0 if no image is set. 185 * 186 * \sa setImage() 187 */ image()188 WImage *image() const { return image_.get(); } 189 190 virtual bool canReceiveFocus() const override; 191 virtual int tabIndex() const override; 192 virtual bool setFirstFocus() override; 193 194 private: 195 static const int BIT_LINK_CHANGED = 0; 196 static const int BIT_TARGET_CHANGED = 1; 197 198 struct WT_API LinkState { 199 LinkState(); 200 ~LinkState(); 201 202 WLink link; 203 JSlot *clickJS; 204 }; 205 206 LinkState linkState_; 207 208 observing_ptr<WText> text_; 209 observing_ptr<WImage> image_; 210 std::bitset<2> flags_; 211 212 void resourceChanged(); 213 214 static bool renderHRef(WInteractWidget *widget, 215 LinkState& linkState, DomElement& element); 216 static void renderHTarget(LinkState& linkState, DomElement& element, 217 bool all); 218 static void renderUrlResolution(WWidget *widget, DomElement& element, 219 bool all); 220 221 protected: 222 virtual void updateDom(DomElement& element, bool all) override; 223 virtual DomElementType domElementType() const override; 224 virtual void propagateRenderOk(bool deep) override; 225 virtual void propagateSetEnabled(bool enabled) override; 226 virtual void enableAjax() override; 227 228 friend class WAbstractArea; 229 friend class WPushButton; 230 friend class Impl::AreaWidget; 231 }; 232 233 } 234 235 #endif // WANCHOR_H_ 236