#include "BulmaTheme.h" #include "BoostLog.h" #include #include #include #include #include #include #include namespace std { std::ostream &operator<<(std::ostream &os, Wt::DomElementType type); } void BulmaTheme::init(Wt::WApplication *app) const { Wt::WString v = app->metaHeader(Wt::MetaHeaderType::Meta, "viewport"); if (v.empty()) { // app->addMetaHeader("viewport", "width=device-width, initial-scale=1"); app->doJavaScript(R"( var meta = document.createElement('meta'); meta.name = 'viewport'; meta.content = 'width=device-width, initial-scale=1'; document.getElementsByTagName('head')[0].appendChild(meta); )"); } } std::string BulmaTheme::disabledClass() const { return ""; } std::string BulmaTheme::activeClass() const { return ""; } std::string BulmaTheme::utilityCssClass(int utilityCssClassRole) const { return ""; } std::vector BulmaTheme::styleSheets() const { std::vector result; std::string themeDir = resourcesUrl(); if (m_global) { result.push_back(Wt::WLinkedCssStyleSheet(Wt::WLink(std::format("{}base.css", themeDir)))); } result.push_back(Wt::WLinkedCssStyleSheet(Wt::WLink(std::format("{}prefixed.css", themeDir)))); return result; } bool BulmaTheme::canStyleAnchorAsButton() const { return true; } void BulmaTheme::apply(Wt::WWidget *widget, Wt::WWidget *child, int widgetRole) const { using namespace Wt; if (!widget->isThemeStyleEnabled()) return; switch (widgetRole) { case DialogContent: { child->addStyleClass("bulma-modal-content"); break; } case DialogCoverWidget: { child->addStyleClass("bulma-modal-backdrop"); break; } case DialogTitleBar: { child->addStyleClass("bulma-modal-card-head"); child->setAttributeValue("style", "justify-content: space-between"); break; } case DialogBody: { child->addStyleClass("bulma-modal-card-body"); break; } case DialogFooter: { child->addStyleClass("bulma-modal-card-foot bulma-buttons"); break; } case DialogCloseIcon: { auto parent = dynamic_cast(child->parent()); auto self = parent->removeWidget(child); parent->addWidget(std::move(self)); child->addStyleClass("bulma-delete"); break; } default: break; } } void BulmaTheme::apply(Wt::WWidget *widget, Wt::DomElement &element, int elementRole) const { bool creating = element.mode() == Wt::DomElement::Mode::Create; if (!widget->isThemeStyleEnabled()) return; { Wt::WPopupWidget *popup = dynamic_cast(widget); if (popup) element.addPropertyWord(Wt::Property::Class, "Wt-outset"); } switch (element.type()) { case Wt::DomElementType::BUTTON: { if (creating) { element.addPropertyWord(Wt::Property::Class, "bulma-button"); } break; } case Wt::DomElementType::DIV: { if (Wt::WDialog *dialog = dynamic_cast(widget); dialog != nullptr) { element.addPropertyWord(Wt::Property::Class, "bulma-modal bulma-is-active"); return; } else if (auto text = dynamic_cast(widget); text != nullptr) { element.addPropertyWord(Wt::Property::Class, "is-size-6"); return; } break; } default: LOG(warning) << "elemnet[" << element.type() << "] need style."; break; } LOG(info) << "BulmaTheme::apply"; } void BulmaTheme::applyValidationStyle(Wt::WWidget *widget, const Wt::WValidator::Result &validation, Wt::WFlags flags) const { using namespace Wt; if (flags.test(ValidationStyleFlag::InvalidStyle)) { widget->addStyleClass("bulma-is-danger"); } } bool BulmaTheme::canBorderBoxElement(const Wt::DomElement &element) const { return true; } std::string BulmaTheme::name() const { return m_name; } BulmaTheme::BulmaTheme(const std::string &name, bool global) : m_name(name), m_global(global) { } namespace std { std::ostream &operator<<(std::ostream &os, Wt::DomElementType type) { using namespace Wt; switch (type) { case DomElementType::A: os << "A"; break; case DomElementType::BR: os << "BR"; break; case DomElementType::BUTTON: os << "BUTTON"; break; case DomElementType::COL: os << "COL"; break; case DomElementType::COLGROUP: os << "COLGROUP"; break; case DomElementType::DIV: os << "DIV"; break; case DomElementType::FIELDSET: os << "FIELDSET"; break; case DomElementType::FORM: os << "FORM"; break; case DomElementType::H1: os << "H1"; break; case DomElementType::H2: os << "H2"; break; case DomElementType::H3: os << "H3"; break; case DomElementType::H4: os << "H4"; break; case DomElementType::H5: os << "H5"; break; case DomElementType::H6: os << "H6"; break; case DomElementType::IFRAME: os << "IFRAME"; break; case DomElementType::IMG: os << "IMG"; break; case DomElementType::INPUT: os << "INPUT"; break; case DomElementType::LABEL: os << "LABEL"; break; case DomElementType::LEGEND: os << "LEGEND"; break; case DomElementType::LI: os << "LI"; break; case DomElementType::OL: os << "OL"; break; case DomElementType::OPTION: os << "OPTION"; break; case DomElementType::UL: os << "UL"; break; case DomElementType::SCRIPT: os << "SCRIPT"; break; case DomElementType::SELECT: os << "SELECT"; break; case DomElementType::SPAN: os << "SPAN"; break; case DomElementType::TABLE: os << "TABLE"; break; case DomElementType::TBODY: os << "TBODY"; break; case DomElementType::THEAD: os << "THEAD"; break; case DomElementType::TFOOT: os << "TFOOT"; break; case DomElementType::TH: os << "TH"; break; case DomElementType::TD: os << "TD"; break; case DomElementType::TEXTAREA: os << "TEXTAREA"; break; case DomElementType::OPTGROUP: os << "OPTGROUP"; break; case DomElementType::TR: os << "TR"; break; case DomElementType::P: os << "P"; break; case DomElementType::CANVAS: os << "CANVAS"; break; case DomElementType::MAP: os << "MAP"; break; case DomElementType::AREA: os << "AREA"; break; case DomElementType::STYLE: os << "STYLE"; break; case DomElementType::OBJECT: os << "OBJECT"; break; case DomElementType::PARAM: os << "PARAM"; break; case DomElementType::AUDIO: os << "AUDIO"; break; case DomElementType::VIDEO: os << "VIDEO"; break; case DomElementType::SOURCE: os << "SOURCE"; break; case DomElementType::B: os << "B"; break; case DomElementType::STRONG: os << "STRONG"; break; case DomElementType::EM: os << "EM"; break; case DomElementType::I: os << "I"; break; case DomElementType::HR: os << "HR"; break; case DomElementType::DATALIST: os << "DATALIST"; break; case DomElementType::UNKNOWN: os << "UNKNOWN"; break; case DomElementType::OTHER: os << "OTHER"; break; default: os << "UNKNOWN"; break; } return os; } } // namespace std