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 WWEB_WIDGET_H_ 8 #define WWEB_WIDGET_H_ 9 10 #include <set> 11 #include <bitset> 12 13 #include <Wt/WString.h> 14 #include <Wt/WWidget.h> 15 #include <Wt/WEvent.h> 16 17 #ifdef WT_CNOR 18 #include <Wt/WJavaScript.h> 19 #endif // WT_CNOR 20 21 namespace Wt { 22 23 class WStringStream; 24 class WApplication; 25 26 /*! \brief Enumeration for a DOM element type. 27 * 28 * For internal use only. 29 */ 30 enum class DomElementType { 31 A, BR, BUTTON, COL, 32 COLGROUP, 33 DIV, FIELDSET, FORM, 34 H1, H2, H3, H4, 35 36 H5, H6, IFRAME, IMG, 37 INPUT, LABEL, LEGEND, LI, 38 OL, 39 40 OPTION, UL, SCRIPT, SELECT, 41 SPAN, TABLE, TBODY, THEAD, 42 TFOOT, TH, TD, TEXTAREA, 43 OPTGROUP, 44 45 TR, P, CANVAS, 46 MAP, AREA, STYLE, 47 48 OBJECT, PARAM, 49 50 AUDIO, VIDEO, SOURCE, 51 52 B, STRONG, EM, I, HR, 53 UNKNOWN, 54 OTHER 55 }; 56 57 class WCssDecorationStyle; 58 class WContainerWidget; 59 class DomElement; 60 61 #ifndef WT_CNOR 62 template <typename... A> class JSignal; 63 #endif 64 65 #ifdef WT_TARGET_JAVA 66 struct HandleWidgetMethod { 67 HandleWidgetMethod(); 68 HandleWidgetMethod(void (*)(WWidget*)); 69 void handle(WWidget *) const; 70 }; 71 #endif // WT_TARGET_JAVA 72 73 /*! \class WWebWidget Wt/WWebWidget.h Wt/WWebWidget.h 74 * \brief A base class for widgets with an HTML counterpart. 75 * 76 * All descendants of %WWebWidget implement a widget which corresponds 77 * almost one-on-one with an HTML element. These widgets provide most 78 * capabilities of these HTML elements, but rarely make no attempt to 79 * do anything more. 80 * 81 * \sa WCompositeWidget 82 */ 83 class WT_API WWebWidget : public WWidget 84 { 85 public: 86 /*! \brief Construct a WebWidget. 87 */ 88 WWebWidget(); 89 virtual ~WWebWidget() override; 90 91 virtual std::vector<WWidget *> children() const override; 92 93 /*! \brief %Signal emitted when children have been added or removed. 94 * 95 * \sa children() 96 */ 97 Signal<>& childrenChanged(); 98 99 virtual void setPositionScheme(PositionScheme scheme) override; 100 virtual PositionScheme positionScheme() const override; 101 virtual void setOffsets(const WLength& offset, 102 WFlags<Side> sides = AllSides) override; 103 virtual WLength offset(Side s) const override; 104 virtual void resize(const WLength& width, const WLength& height) override; 105 virtual WLength width() const override; 106 virtual WLength height() const override; 107 virtual void setMinimumSize(const WLength& width, const WLength& height) override; 108 virtual WLength minimumWidth() const override; 109 virtual WLength minimumHeight() const override; 110 virtual void setMaximumSize(const WLength& width, const WLength& height) override; 111 virtual WLength maximumWidth() const override; 112 virtual WLength maximumHeight() const override; 113 virtual void setLineHeight(const WLength& height) override; 114 virtual WLength lineHeight() const override; 115 virtual void setFloatSide(Side s) override; 116 virtual Side floatSide() const override; 117 virtual void setClearSides(WFlags<Side> sides) override; 118 virtual WFlags<Side> clearSides() const override; 119 virtual void setMargin(const WLength& margin, WFlags<Side> sides = AllSides) 120 override; 121 virtual WLength margin(Side side) const override; 122 virtual void setHiddenKeepsGeometry(bool enabled) override; 123 virtual bool hiddenKeepsGeometry() const override; 124 virtual void setHidden(bool hidden, const WAnimation& animation = WAnimation()) override; 125 virtual bool isHidden() const override; 126 virtual bool isVisible() const override; 127 virtual void setDisabled(bool disabled) override; 128 virtual bool isDisabled() const override; 129 virtual bool isEnabled() const override; 130 virtual void setPopup(bool popup) override; 131 virtual bool isPopup() const override; 132 virtual void setInline(bool isInline) override; 133 virtual bool isInline() const override; 134 virtual void setDecorationStyle(const WCssDecorationStyle& style) override; 135 virtual WCssDecorationStyle& decorationStyle() override; 136 virtual const WCssDecorationStyle& decorationStyle() const override; 137 virtual void setStyleClass(const WT_USTRING& styleClass) override; 138 void setStyleClass(const char *styleClass); 139 virtual WT_USTRING styleClass() const override; 140 virtual void addStyleClass(const WT_USTRING& styleClass, 141 bool force = false) override; 142 void addStyleClass(const char *styleClass, bool force = false); 143 virtual void removeStyleClass(const WT_USTRING& styleClass, 144 bool force = false) override; 145 void removeStyleClass(const char *styleClass, bool force = false); 146 virtual bool hasStyleClass(const WT_USTRING& styleClass) const override; 147 virtual void setVerticalAlignment(AlignmentFlag alignment, 148 const WLength& length = WLength()) override; 149 virtual AlignmentFlag verticalAlignment() const override; 150 virtual WLength verticalAlignmentLength() const override; 151 virtual void setToolTip(const WString& text, 152 TextFormat textFormat = TextFormat::Plain) 153 override; 154 virtual void setDeferredToolTip(bool enable, 155 TextFormat textFormat = TextFormat::Plain) 156 override; 157 virtual WString toolTip() const override; 158 virtual void refresh() override; 159 virtual void setAttributeValue(const std::string& name, 160 const WT_USTRING& value) override; 161 virtual WT_USTRING attributeValue(const std::string& name) const override; 162 virtual void setJavaScriptMember(const std::string& name, 163 const std::string& value) override; 164 virtual std::string javaScriptMember(const std::string& name) const override; 165 virtual void callJavaScriptMember(const std::string& name, 166 const std::string& args) override; 167 virtual void load() override; 168 virtual bool loaded() const override; 169 virtual int zIndex() const override; 170 171 virtual void setId(const std::string& id) override; 172 virtual WWidget *find(const std::string& name) override; 173 virtual WWidget *findById(const std::string& id) override; 174 virtual void setSelectable(bool selectable) override; 175 virtual void doJavaScript(const std::string& javascript) override; 176 virtual const std::string id() const override; 177 178 #ifdef WT_TARGET_JAVA 179 /*! \brief Create DOM element for widget 180 * 181 * This is an internal function, and should not be called directly, 182 * or be overridden! 183 */ 184 #endif 185 virtual DomElement *createDomElement(WApplication *app); 186 #ifdef WT_TARGET_JAVA 187 /*! \brief Get DOM changes for this widget 188 * 189 * This is an internal function, and should not be called directly, 190 * or be overridden! 191 */ 192 #endif 193 virtual void getDomChanges(std::vector<DomElement *>& result, 194 WApplication *app); 195 virtual DomElementType domElementType() const = 0; 196 197 DomElement *createStubElement(WApplication *app); 198 DomElement *createActualElement(WWidget *self, WApplication *app); 199 200 /*! \brief Change the way the widget is loaded when invisible. 201 * 202 * By default, invisible widgets are loaded only after visible content. 203 * For tiny widgets this may lead to a performance loss, instead of the 204 * expected increase, because they require many more DOM manipulations 205 * to render, reducing the overall responsiveness of the application. 206 * 207 * Therefore, this is disabled for some widgets like WImage, or 208 * empty WContainerWidgets. 209 * 210 * You may also want to disable deferred loading when JavaScript event 211 * handling expects the widget to be loaded. 212 * 213 * Usually the default settings are fine, but you may want to change 214 * the behaviour. 215 * 216 * \sa WApplication::setTwoPhaseRenderingThreshold() 217 */ 218 void setLoadLaterWhenInvisible(bool); 219 220 /*! 221 * \brief returns the current html tag name 222 * 223 * \sa setHtmlTagName() 224 */ 225 std::string htmlTagName() const; 226 227 /*! 228 * \brief set the custom HTML tag name 229 * 230 * The custom tag will replace the actual tag. 231 * The tag is not tested to see if 232 * it is a valid one and a closing tag will always be added. 233 * 234 * \sa htmlTagName() 235 */ 236 void setHtmlTagName(const std::string & tag); 237 238 static WString escapeText(const WString& text, bool newlinesToo = false); 239 static std::string& escapeText(std::string& text, bool newlinestoo = false); 240 static std::string& unescapeText(std::string& text); 241 #ifdef WT_TARGET_JAVA 242 static std::string& doUnescapeText(std::string& text); 243 #endif // WT_TARGET_JAVA 244 static bool removeScript(WString& text); 245 246 /*! \brief Turn a CharEncoding::UTF8 encoded string into a JavaScript string literal 247 * 248 * The \p delimiter may be a single or double quote. 249 */ 250 static std::string jsStringLiteral(const std::string& v, 251 char delimiter = '\''); 252 static std::string jsStringLiteral(const WString& v, 253 char delimiter = '\''); 254 255 static std::string resolveRelativeUrl(const std::string& url); 256 257 void setFormObject(bool how); 258 static bool canOptimizeUpdates(); 259 void setZIndex(int zIndex); 260 261 bool isRendered() const; 262 263 virtual void setCanReceiveFocus(bool enabled) override; 264 virtual bool canReceiveFocus() const override; 265 virtual bool setFirstFocus() override; 266 virtual void setFocus(bool focus) override; 267 virtual bool hasFocus() const override; 268 virtual void setTabIndex(int index) override; 269 virtual int tabIndex() const override; 270 271 /*! \brief %Signal emitted when the widget lost focus. 272 * 273 * This signals is only emitted for a widget that canReceiveFocus() 274 */ 275 EventSignal<>& blurred(); 276 277 /*! \brief %Signal emitted when the widget recieved focus. 278 * 279 * This signals is only emitted for a widget that canReceiveFocus() 280 */ 281 EventSignal<>& focussed(); 282 283 #ifndef WT_TARGET_JAVA 284 using WWidget::setFocus; 285 #endif 286 287 virtual bool scrollVisibilityEnabled() const final override; 288 virtual void setScrollVisibilityEnabled(bool enabled) final override; 289 virtual int scrollVisibilityMargin() const final override; 290 virtual void setScrollVisibilityMargin(int margin) final override; 291 virtual Signal<bool> &scrollVisibilityChanged() final override; 292 virtual bool isScrollVisible() const final override; 293 294 virtual void setThemeStyleEnabled(bool enabled) final override; 295 virtual bool isThemeStyleEnabled() const final override; 296 297 virtual void setObjectName(const std::string& name) override; 298 299 virtual int baseZIndex() const final override; 300 void setBaseZIndex(int zIndex); 301 302 protected: 303 typedef std::map<std::string, WObject *> FormObjectsMap; 304 #ifndef WT_TARGET_JAVA 305 typedef std::function<void (WWidget *)> HandleWidgetMethod; 306 #endif 307 308 void repaint(WFlags<RepaintFlag> flags = None); 309 310 virtual void iterateChildren(const HandleWidgetMethod& method) const; 311 virtual void getFormObjects(FormObjectsMap& formObjects); 312 virtual void doneRerender(); 313 virtual void updateDom(DomElement& element, bool all); 314 virtual bool domCanBeSaved() const; 315 virtual void propagateRenderOk(bool deep = true); 316 virtual std::string renderRemoveJs(bool recursive) override; 317 318 virtual void propagateSetEnabled(bool enabled) override; 319 virtual void propagateSetVisible(bool visible) override; 320 virtual bool isStubbed() const override; 321 virtual void enableAjax() override; 322 323 virtual void setHideWithOffsets(bool how = true) override; 324 virtual WStatelessSlot *getStateless(Method method) override; 325 326 WWidget *selfWidget(); 327 328 void doLoad(WWidget *w); 329 void widgetAdded(WWidget *child); 330 void widgetRemoved(WWidget *child, bool renderRemove); 331 332 #ifndef WT_TARGET_JAVA 333 template <class Widget> manageWidget(std::unique_ptr<Widget> & managed,std::unique_ptr<Widget> w)334 std::unique_ptr<WWidget> manageWidget(std::unique_ptr<Widget>& managed, 335 std::unique_ptr<Widget> w) 336 #else // WT_TARGET_JAVA 337 std::unique_ptr<WWidget> manageWidget(std::unique_ptr<WWidget> managed, std::unique_ptr<WWidget> w) 338 #endif // WT_TARGET_JAVA 339 { 340 if (managed) 341 widgetRemoved(managed.get(), true); 342 std::unique_ptr<WWidget> result = std::move(managed); 343 managed = std::move(w); 344 if (managed) 345 widgetAdded(managed.get()); 346 return result; 347 } 348 349 virtual void render(WFlags<RenderFlag> flags) override; 350 351 virtual void signalConnectionsChanged() override; 352 353 void beingDeleted(); 354 355 private: 356 /* 357 * Booleans packed in a bitset. 358 */ 359 static const int BIT_INLINE = 0; 360 static const int BIT_HIDDEN = 1; 361 static const int BIT_LOADED = 2; 362 static const int BIT_RENDERED = 3; 363 static const int BIT_STUBBED = 4; 364 static const int BIT_FORM_OBJECT = 5; 365 static const int BIT_FLEX_BOX = 6; 366 static const int BIT_FLEX_BOX_CHANGED = 7; 367 static const int BIT_GEOMETRY_CHANGED = 8; 368 static const int BIT_HIDE_WITH_OFFSETS = 9; 369 static const int BIT_BEING_DELETED = 10; 370 static const int BIT_DONOT_STUB = 11; 371 static const int BIT_FLOAT_SIDE_CHANGED = 12; 372 static const int BIT_REPAINT_TO_AJAX = 13; 373 static const int BIT_HIDE_WITH_VISIBILITY = 14; 374 static const int BIT_HIDDEN_CHANGED = 15; 375 static const int BIT_ENABLED = 16; // caches isEnabled() for WInteractWidget 376 static const int BIT_TOOLTIP_CHANGED = 17; 377 static const int BIT_MARGINS_CHANGED = 18; 378 static const int BIT_STYLECLASS_CHANGED = 19; 379 static const int BIT_SET_UNSELECTABLE = 20; 380 static const int BIT_SET_SELECTABLE = 21; 381 static const int BIT_SELECTABLE_CHANGED = 22; 382 static const int BIT_WIDTH_CHANGED = 23; 383 static const int BIT_HEIGHT_CHANGED = 24; 384 static const int BIT_DISABLED = 25; 385 static const int BIT_DISABLED_CHANGED = 26; 386 static const int BIT_CONTAINS_LAYOUT = 27; 387 static const int BIT_ZINDEX_CHANGED = 28; 388 static const int BIT_TOOLTIP_DEFERRED = 29; 389 static const int BIT_GOT_FOCUS = 30; 390 static const int BIT_TABINDEX_CHANGED = 31; 391 static const int BIT_SCROLL_VISIBILITY_ENABLED = 32; 392 // BIT_SCROLL_VISIBILITY_LOADED makes sure that scrollVisibility.remove is never 393 // called for widgets that never had scroll visibility enabled 394 static const int BIT_SCROLL_VISIBILITY_LOADED = 33; 395 static const int BIT_IS_SCROLL_VISIBLE = 34; // tracks whether the widget is currently "scroll visible" 396 // Tracks whether scroll visibility is enabled/disabled, and whether the 397 // scroll visibility margin has been modified. 398 static const int BIT_SCROLL_VISIBILITY_CHANGED = 35; 399 static const int BIT_THEME_STYLE_DISABLED = 36; 400 static const int BIT_OBJECT_NAME_CHANGED = 37; 401 402 static const char *FOCUS_SIGNAL; 403 static const char *BLUR_SIGNAL; 404 405 static const int DEFAULT_BASE_Z_INDEX; 406 static const int Z_INDEX_INCREMENT; 407 408 std::string elementTagName_; 409 410 #ifndef WT_TARGET_JAVA 411 static const std::bitset<38> AllChangeFlags; 412 #endif // WT_TARGET_JAVA 413 414 void loadToolTip(); 415 416 /* 417 * Frequently used attributes. 418 */ 419 std::bitset<38> flags_; 420 std::unique_ptr<WLength> width_; 421 std::unique_ptr<WLength> height_; 422 423 /* 424 * id_ is separate instead of in OtherImpl, 425 * because it is accessed when OtherImpl is being destroyed, 426 * from the destructor of jsScrollVisibilityChanged_ 427 */ 428 std::unique_ptr<std::string> id_; 429 430 /* 431 * Data only stored transiently, during event handling. 432 */ 433 struct TransientImpl { 434 std::vector<std::string> childRemoveChanges_; 435 std::vector<WT_USTRING> addedStyleClasses_, removedStyleClasses_; 436 std::vector<std::string> attributesSet_; 437 438 int addedChildren_; 439 bool specialChildRemove_; 440 WAnimation animation_; 441 442 TransientImpl(); 443 ~TransientImpl(); 444 }; 445 446 std::unique_ptr<TransientImpl> transientImpl_; 447 448 struct LayoutImpl { 449 PositionScheme positionScheme_; 450 Side floatSide_; 451 WFlags<Side> clearSides_; 452 WLength offsets_[4]; // left, right, top, bottom 453 WLength minimumWidth_, minimumHeight_, maximumWidth_, maximumHeight_; 454 int baseZIndex_; 455 int zIndex_; // -1 = wants popup 456 AlignmentFlag verticalAlignment_; 457 WLength verticalAlignmentLength_, margin_[4], lineHeight_; 458 459 LayoutImpl(); 460 }; 461 462 std::unique_ptr<LayoutImpl> layoutImpl_; 463 464 struct LookImpl { 465 std::unique_ptr<WCssDecorationStyle> decorationStyle_; 466 WT_USTRING styleClass_; 467 std::unique_ptr<WString> toolTip_; 468 TextFormat toolTipTextFormat_; 469 JSignal<> loadToolTip_; 470 471 LookImpl(WWebWidget *w); 472 ~LookImpl(); 473 }; 474 475 mutable std::unique_ptr<LookImpl> lookImpl_; 476 477 struct DropMimeType { 478 WT_USTRING hoverStyleClass; 479 480 DropMimeType(); 481 DropMimeType(const WT_USTRING& hoverStyleClass); 482 }; 483 484 enum class JavaScriptStatementType { 485 SetMember, 486 CallMethod, 487 Statement 488 }; 489 490 struct OtherImpl { 491 struct Member { 492 std::string name; 493 std::string value; 494 }; 495 496 struct JavaScriptStatement { 497 JavaScriptStatement(JavaScriptStatementType type, 498 const std::string& data); 499 500 JavaScriptStatementType type; 501 std::string data; 502 }; 503 504 std::unique_ptr<std::string> elementTagName_; 505 std::unique_ptr<std::map<std::string, WT_USTRING> > attributes_; 506 std::unique_ptr<std::vector<Member> > jsMembers_; 507 std::unique_ptr<std::vector<JavaScriptStatement> > jsStatements_; 508 std::unique_ptr<JSignal<int, int> > resized_; 509 int tabIndex_; 510 511 // drag source id, drag mime type 512 std::unique_ptr<JSignal<std::string, std::string, WMouseEvent> > dropSignal_; 513 std::unique_ptr<JSignal<std::string, std::string, WTouchEvent> > dropSignal2_; 514 515 typedef std::map<std::string, DropMimeType> MimeTypesMap; 516 std::unique_ptr<MimeTypesMap> acceptedDropMimeTypes_; 517 Signal<> childrenChanged_; 518 519 int scrollVisibilityMargin_; 520 Signal<bool> scrollVisibilityChanged_; 521 std::unique_ptr<JSignal<bool> > jsScrollVisibilityChanged_; 522 523 OtherImpl(WWebWidget *const self); 524 ~OtherImpl(); 525 }; 526 527 std::unique_ptr<OtherImpl> otherImpl_; 528 529 void renderOk(); 530 void calcZIndex(); 531 532 virtual bool needsToBeRendered() const override; 533 virtual void getSDomChanges(std::vector<DomElement *>& result, 534 WApplication *app) override; 535 void getSFormObjects(FormObjectsMap& formObjects); 536 537 WWebWidget *parentWebWidget() const; 538 539 /* 540 * Drag & drop stuff. 541 */ 542 bool setAcceptDropsImpl(const std::string& mimeType, 543 bool accept, 544 const WT_USTRING& hoverStyleClass); 545 void setImplementLayoutSizeAware(bool aware); 546 JSignal<int, int>& resized(); 547 548 void addJavaScriptStatement(JavaScriptStatementType type, 549 const std::string& data); 550 int indexOfJavaScriptMember(const std::string& name) const; 551 void declareJavaScriptMember(DomElement& element, 552 const std::string& name, 553 const std::string& value); 554 WString storedToolTip() const; 555 void undoSetFocus(); 556 557 void jsScrollVisibilityChanged(bool visible); 558 559 void emitChildrenChanged(); 560 561 protected: 562 virtual void setParentWidget(WWidget *parent) override; 563 void setRendered(bool rendered); 564 565 void setId(DomElement *element, WApplication *app); webWidget()566 virtual WWebWidget *webWidget() override { return this; } 567 568 EventSignal<> *voidEventSignal(const char *name, bool create); 569 EventSignal<WKeyEvent> *keyEventSignal(const char *name, bool create); 570 EventSignal<WMouseEvent> *mouseEventSignal(const char *name, bool create); 571 EventSignal<WScrollEvent> *scrollEventSignal(const char *name, bool create); 572 EventSignal<WTouchEvent> *touchEventSignal(const char *name, bool create); 573 EventSignal<WGestureEvent> *gestureEventSignal(const char *name, bool create); 574 575 void updateSignalConnection(DomElement& element, EventSignalBase& signal, 576 const char *name, bool all); 577 578 virtual void parentResized(WWidget *parent, WFlags<Orientation> directions); 579 void containsLayout(); 580 void setFlexBox(bool enabled); 581 582 /* 583 * WWebWidget ended up with more friends than me... 584 */ 585 friend class WebRenderer; 586 friend class WebSession; 587 588 friend class WApplication; 589 friend class WCompositeWidget; 590 friend class WContainerWidget; 591 friend class WCssDecorationStyle; 592 friend class WCssTemplateRule; 593 friend class WDialog; 594 friend class WFont; 595 friend class WGLWidget; 596 friend class WInteractWidget; 597 friend class WLeafletMap; 598 friend class JSlot; 599 friend class WTable; 600 friend class WViewWidget; 601 friend class WWidget; 602 friend class WTemplate; 603 friend class WWidgetItem; 604 friend class FlexLayoutImpl; 605 }; 606 607 } 608 609 #endif // WWEB_WIDGET_H_ 610