void WAbstractMedia::getDomChanges(std::vector<DomElement *>& result, WApplication *app) { if (!mediaId_.empty()) { DomElement *media = DomElement::getForUpdate(mediaId_, DomElement_DIV); updateMediaDom(*media, false); if (sourcesChanged_) { // Updating source elements seems to be ill-supported in at least FF, // so we delete them all and reinsert them. // Delete source elements that are no longer required for (std::size_t i = 0; i < sourcesRendered_; ++i) media->callJavaScript (WT_CLASS ".remove('" + mediaId_ + "s" + boost::lexical_cast<std::string>(i) + "');", true); sourcesRendered_ = 0; for (std::size_t i = 0; i < sources_.size(); ++i) { DomElement *src = DomElement::createNew(DomElement_SOURCE); src->setId(mediaId_ + "s" + boost::lexical_cast<std::string>(i)); renderSource(src, *sources_[i], i + 1 >= sources_.size()); media->addChild(src); } sourcesRendered_ = sources_.size(); sourcesChanged_ = false; // Explicitly request rerun of media selection algorithm // 4.8.9.2 says it should happen automatically, but FF doesn't media->callJavaScript(jsMediaRef() + ".load();"); } result.push_back(media); } WInteractWidget::getDomChanges(result, app); }
void WWidgetCanvasPainter::createContents(DomElement *result, WPaintDevice *device) { std::string wstr = boost::lexical_cast<std::string>(widget_->renderWidth_); std::string hstr = boost::lexical_cast<std::string>(widget_->renderHeight_); result->setProperty(PropertyStylePosition, "relative"); result->setProperty(PropertyStyleOverflowX, "hidden"); result->setProperty(PropertyStyleOverflowY, "hidden"); DomElement *canvas = DomElement::createNew(DomElement_CANVAS); canvas->setId('c' + widget_->id()); canvas->setProperty(PropertyStyleDisplay, "block"); canvas->setAttribute("width", wstr); canvas->setAttribute("height", hstr); result->addChild(canvas); widget_->sizeChanged_ = false; WCanvasPaintDevice *canvasDevice = dynamic_cast<WCanvasPaintDevice *>(device); DomElement *text = 0; if (canvasDevice->textMethod() == WCanvasPaintDevice::DomText) { text = DomElement::createNew(DomElement_DIV); text->setId('t' + widget_->id()); text->setProperty(PropertyStylePosition, "absolute"); text->setProperty(PropertyStyleZIndex, "1"); text->setProperty(PropertyStyleTop, "0px"); text->setProperty(PropertyStyleLeft, "0px"); } DomElement *el = text ? text : result; bool hasJsObjects = widget_->jsObjects_.size() > 0; if (hasJsObjects) { WStringStream ss; WApplication *app = WApplication::instance(); ss << "new " WT_CLASS ".WPaintedWidget(" << app->javaScriptClass() << "," << widget_->jsRef() << ");"; widget_->jsObjects_.updateJs(ss); el->callJavaScript(ss.str()); } canvasDevice->render('c' + widget_->id(), el); if (hasJsObjects) { WStringStream ss; ss << widget_->objJsRef() << ".repaint=function(){"; ss << canvasDevice->recordedJs_.str(); ss << "};"; el->callJavaScript(ss.str()); } if (text) result->addChild(text); delete device; }
void WTextEdit::updateDom(DomElement& element, bool all) { WTextArea::updateDom(element, all); if (element.type() == DomElement_TEXTAREA) element.removeProperty(PropertyStyleDisplay); // we are creating the actual element if (all && element.type() == DomElement_TEXTAREA) { std::stringstream config; config << "{"; bool first = true; for (SettingsMapType::const_iterator it = configurationSettings_.begin(); it != configurationSettings_.end(); ++it) { if (it->first == "plugins") continue; if (!first) config << ','; first = false; config << it->first << ": " << Impl::asJSLiteral(it->second, XHTMLUnsafeText); } if (!first) config << ','; config << "plugins: '" << plugins() << "'"; config << ",init_instance_callback: obj.init" "}"; DomElement dummy(DomElement::ModeUpdate, DomElement_TABLE); updateDom(dummy, true); element.callJavaScript("(function() { " """var obj = $('#" + id() + "').data('obj');" """obj.render(" + config.str() + "," + jsStringLiteral(dummy.cssStyle()) + "," + (changed().isConnected() ? "true" : "false") + ");" "})();"); contentChanged_ = false; } if (!all && contentChanged_) { element.callJavaScript(jsRef() + ".ed.load();"); contentChanged_ = false; } }
void WWidgetItemImpl::createComponent(DomElement *parentContainer) { DomElement *e = item_->widget()->createSDomElement(WApplication::instance()); e->setProperty(PropertyStyle, e->getProperty(PropertyStyle) + "position:absolute;left:-10000px;top:-10000px;" "visibility:hidden;"); Container *c = dynamic_cast<Container *>(item_->widget()); if (!c) { std::stringstream js; js << "var " << var_ << "=new Ext.BoxComponent({id:'" << id_ << "',applyTo:'" << item_->widget()->id() << "'"; addConfig(js); Container::setSizeConfig(js, item_->widget()); js << "});{var s=" << item_->widget()->jsRef() << ";s.style.position='';" "s.style.left='';" "s.style.top='';" "s.style.visibility='';}"; e->callJavaScript(js.str()); } parentContainer->addChild(e); }
void WWidgetCanvasPainter::updateContents(std::vector<DomElement *>& result, WPaintDevice *device) { WCanvasPaintDevice *canvasDevice = dynamic_cast<WCanvasPaintDevice *>(device); if (widget_->sizeChanged_) { DomElement *canvas = DomElement::getForUpdate('c' + widget_->id(), DomElement_CANVAS); canvas->setAttribute("width", boost::lexical_cast<std::string>(widget_->renderWidth_)); canvas->setAttribute("height", boost::lexical_cast<std::string>(widget_->renderHeight_)); result.push_back(canvas); widget_->sizeChanged_ = false; } bool domText = canvasDevice->textMethod() == WCanvasPaintDevice::DomText; DomElement *el = DomElement::getForUpdate(domText ? 't' + widget_->id() : widget_->id(), DomElement_DIV); if (domText) el->removeAllChildren(); bool hasJsObjects = widget_->jsObjects_.size() > 0; if (hasJsObjects) { WStringStream ss; widget_->jsObjects_.updateJs(ss); el->callJavaScript(ss.str()); } canvasDevice->render('c' + widget_->id(), el); if (hasJsObjects) { WStringStream ss; ss << widget_->objJsRef() << ".repaint=function(){"; ss << canvasDevice->recordedJs_.str(); ss << "};"; el->callJavaScript(ss.str()); } result.push_back(el); delete device; }
void WFormWidget::updateDom(DomElement& element, bool all) { const WEnvironment& env = WApplication::instance()->environment(); bool onChangeHandledElsewhere = dynamic_cast<WAbstractToggleButton *>(this); if (!onChangeHandledElsewhere) { EventSignal<> *s = voidEventSignal(CHANGE_SIGNAL, false); if (s) updateSignalConnection(element, *s, "change", all); } if (flags_.test(BIT_ENABLED_CHANGED) || all) { if (!all || !isEnabled()) element.setProperty(Wt::PropertyDisabled, isEnabled() ? "false" : "true"); if (!all && isEnabled() && env.agentIsIE()) { /* * FIXME: implement a workaround for IE, reenabling a checkbox makes * the input box loose interactivity. */ } flags_.reset(BIT_ENABLED_CHANGED); } if (flags_.test(BIT_READONLY_CHANGED) || all) { if (!all || isReadOnly()) element.setProperty(Wt::PropertyReadOnly, isReadOnly() ? "true" : "false"); flags_.reset(BIT_READONLY_CHANGED); } if (flags_.test(BIT_TABINDEX_CHANGED) || all) { if (!all || tabIndex_) element.setProperty(PropertyTabIndex, boost::lexical_cast<std::string>(tabIndex_)); flags_.reset(BIT_TABINDEX_CHANGED); } if (isEnabled()) { if (all && flags_.test(BIT_GOT_FOCUS)) flags_.set(BIT_INITIAL_FOCUS); if (flags_.test(BIT_GOT_FOCUS) || (all && flags_.test(BIT_INITIAL_FOCUS))) { element.callJavaScript("setTimeout(function() {" """var f = " + jsRef() + ";" """if (f) try { f.focus(); } catch (e) { } }, " + (env.agentIsIElt(9) ? "500" : "10") + ");"); flags_.reset(BIT_GOT_FOCUS); } } WInteractWidget::updateDom(element, all); }
DomElement *Widget::createDomElement(WApplication *app) { DomElement *result = DomElement::createNew(domElementType()); setId(result, app); std::stringstream js; createExtElement(js, result); result->callJavaScript(js.str()); return result; }
DomElement *WGLWidget::createDomElement(WApplication *app) { DomElement *result = 0; if (app->environment().agentIsIElt(9) || app->environment().agent() == WEnvironment::MobileWebKitAndroid) { // Shortcut: IE misbehaves when it encounters a canvas element result = DomElement::createNew(DomElement_DIV); if (alternative_) result->addChild(alternative_->createSDomElement(app)); } else { result = DomElement::createNew(DomElement_CANVAS);; if (alternative_) { result->addChild(alternative_->createSDomElement(app)); } } setId(result, app); std::stringstream tmp; tmp << "{\n" """var o = new " WT_CLASS ".WGLWidget(" << app->javaScriptClass() << "," << jsRef() << ");\n" """o.discoverContext(function(){" << webglNotAvailable_.createCall() << "});\n"; js_.str(""); initializeGL(); tmp << """o.initializeGL=function(){\n" //"""debugger;\n" """var obj=" << glObjJsRef() << ";\n" """var ctx=obj.ctx; if(!ctx) return;\n" << "" << js_.str() << """obj.initialized = true;\n" // updates are queued until initialization is complete """var key;\n" """for(key in obj.updates) obj.updates[key]();\n" """obj.updates = new Array();\n" // Similar, resizeGL is not executed until initialized """obj.resizeGL();\n" "};\n" "}\n"; tmp << delayedJavaScript_.str(); delayedJavaScript_.str(""); result->callJavaScript(tmp.str()); repaintGL(PAINT_GL | RESIZE_GL); updateDom(*result, true); return result; }
void Widget::getDomChanges(std::vector<DomElement *>& result, WApplication *app) { std::string el = elRef() + ".el.dom"; DomElement *e = DomElement::updateGiven(el, domElementType()); updateExt(); if (!jsUpdates_.empty()) { e->callJavaScript("var " + elVar() + "=" + elRef() + ";" + jsUpdates_); jsUpdates_.clear(); } updateDom(*e, false); e->removeProperty(PropertyStyleDisplay); result.push_back(e); }
void FlexLayoutImpl::updateDom(DomElement& parent) { WApplication *app = WApplication::instance(); DomElement *div = DomElement::getForUpdate(elId_, DomElementType::DIV); Orientation orientation = getOrientation(); std::vector<int> orderedInserts; for (unsigned i = 0; i < addedItems_.size(); ++i) orderedInserts.push_back(indexOf(addedItems_[i], orientation)); Utils::sort(orderedInserts); int totalStretch = getTotalStretch(orientation); for (unsigned i = 0; i < orderedInserts.size(); ++i) { int pos = orderedInserts[i]; DomElement *el = createElement(orientation, pos, totalStretch, app); div->insertChildAt(el, pos); } addedItems_.clear(); for (unsigned i = 0; i < removedItems_.size(); ++i) div->callJavaScript(WT_CLASS ".remove('" + removedItems_[i] + "');", true); removedItems_.clear(); WStringStream js; js << "layout.adjust(" << grid_.horizontalSpacing_ << ")"; div->callMethod(js.str()); parent.addChild(div); }
void WAnchor::updateDom(DomElement& element, bool all) { if (element.type() != DomElement_A) { WContainerWidget::updateDom(element, all); return; } if (flags_.test(BIT_CHANGE_TAG)) { if (!all) element.callJavaScript(WT_CLASS ".changeTag(" + jsRef() + ",'a');"); flags_.reset(BIT_CHANGE_TAG); } bool needsUrlResolution = false; if (flags_.test(BIT_LINK_CHANGED) || all) { WApplication *app = WApplication::instance(); std::string url = link_.resolveUrl(app); /* * From 但浩亮: setRefInternalPath() and setTarget(TargetNewWindow) * does not work without the check below: */ if (target_ == TargetSelf) changeInternalPathJS_ = link_.manageInternalPathChange(app, this, changeInternalPathJS_); else { delete changeInternalPathJS_; changeInternalPathJS_ = 0; } url = app->encodeUntrustedUrl(url); std::string href = resolveRelativeUrl(url); element.setAttribute("href", href); needsUrlResolution = !app->environment().hashInternalPaths() && href.find("://") == std::string::npos && href[0] != '/'; flags_.reset(BIT_LINK_CHANGED); } if (flags_.test(BIT_TARGET_CHANGED) || all) { switch (target_) { case TargetSelf: if (!all) element.setProperty(PropertyTarget, "_self"); break; case TargetThisWindow: element.setProperty(PropertyTarget, "_top"); break; case TargetNewWindow: element.setProperty(PropertyTarget, "_blank"); } flags_.reset(BIT_TARGET_CHANGED); } WContainerWidget::updateDom(element, all); if (needsUrlResolution) { if (all) element.setProperty(PropertyClass, Utils::addWord(styleClass().toUTF8(), "Wt-rr")); else element.callJavaScript("$('#" + id() + "').addClass('Wt-rr');"); } }
/* * fitWidth, fitHeight: * - from setLayout(AlignLeft | AlignTop) * is being deprecated but still needs to be implemented * - nested layouts: handles as other layout items */ DomElement *StdGridLayoutImpl2::createDomElement(bool fitWidth, bool fitHeight, WApplication *app) { needAdjust_ = needConfigUpdate_ = needRemeasure_ = false; addedItems_.clear(); removedItems_.clear(); const unsigned colCount = grid_.columns_.size(); const unsigned rowCount = grid_.rows_.size(); int margin[] = { 0, 0, 0, 0}; int maxWidth = 0, maxHeight = 0; if (layout()->parentLayout() == 0) { #ifndef WT_TARGET_JAVA layout()->getContentsMargins(margin + 3, margin, margin + 1, margin + 2); #else // WT_TARGET_JAVA margin[3] = layout()->getContentsMargin(Left); margin[0] = layout()->getContentsMargin(Top); margin[1] = layout()->getContentsMargin(Right); margin[2] = layout()->getContentsMargin(Bottom); #endif // WT_TARGET_JAVA maxWidth = pixelSize(container()->maximumWidth()); maxHeight = pixelSize(container()->maximumHeight()); } WStringStream js; js << app->javaScriptClass() << ".layouts2.add(new " WT_CLASS ".StdLayout2(" << app->javaScriptClass() << ",'" << id() << "',"; if (layout()->parentLayout()) js << "'" << getImpl(layout()->parentLayout())->id() << "',"; else js << "null,"; bool progressive = !app->environment().ajax(); js << (fitWidth ? '1' : '0') << "," << (fitHeight ? '1' : '0') << "," << (progressive ? '1' : '0') << ","; js << maxWidth << "," << maxHeight << ",[" << grid_.horizontalSpacing_ << "," << margin[3] << "," << margin[1] << "],[" << grid_.verticalSpacing_ << "," << margin[0] << "," << margin[2] << "],"; streamConfig(js, app); DomElement *div = DomElement::createNew(DomElement_DIV); div->setId(id()); div->setProperty(PropertyStylePosition, "relative"); DomElement *table = 0, *tbody = 0, *tr = 0; if (progressive) { table = DomElement::createNew(DomElement_TABLE); WStringStream style; if (maxWidth) style << "max-width: " << maxWidth << "px;"; if (maxHeight) style << "max-height: " << maxHeight << "px;"; style << "width: 100%;"; table->setProperty(PropertyStyle, style.str()); int totalColStretch = 0; for (unsigned col = 0; col < colCount; ++col) totalColStretch += std::max(0, grid_.columns_[col].stretch_); for (unsigned col = 0; col < colCount; ++col) { DomElement *c = DomElement::createNew(DomElement_COL); int stretch = std::max(0, grid_.columns_[col].stretch_); if (stretch || totalColStretch == 0) { char buf[30]; double pct = totalColStretch == 0 ? 100.0 / colCount : (100.0 * stretch / totalColStretch); WStringStream ss; ss << "width:" << Utils::round_css_str(pct, 2, buf) << "%;"; c->setProperty(PropertyStyle, ss.str()); } table->addChild(c); } tbody = DomElement::createNew(DomElement_TBODY); } #ifndef WT_TARGET_JAVA std::vector<bool> overSpanned(colCount * rowCount, false); #else std::vector<bool> overSpanned; overSpanned.insert(0, colCount * rowCount, false); #endif // WT_TARGET_JAVA int prevRowWithItem = -1; for (unsigned row = 0; row < rowCount; ++row) { if (table) tr = DomElement::createNew(DomElement_TR); bool rowVisible = false; int prevColumnWithItem = -1; for (unsigned col = 0; col < colCount; ++col) { Impl::Grid::Item& item = grid_.items_[row][col]; if (!overSpanned[row * colCount + col]) { for (int i = 0; i < item.rowSpan_; ++i) for (int j = 0; j < item.colSpan_; ++j) if (i + j > 0) overSpanned[(row + i) * colCount + col + j] = true; AlignmentFlag hAlign = item.alignment_ & AlignHorizontalMask; AlignmentFlag vAlign = item.alignment_ & AlignVerticalMask; DomElement *td = 0; if (table) { bool itemVisible = hasItem(row, col); rowVisible = rowVisible || itemVisible; td = DomElement::createNew(DomElement_TD); if (itemVisible) { int padding[] = { 0, 0, 0, 0 }; int nextRow = nextRowWithItem(row, col); int prevRow = prevRowWithItem; int nextCol = nextColumnWithItem(row, col); int prevCol = prevColumnWithItem; if (prevRow == -1) padding[0] = margin[0]; else padding[0] = (grid_.verticalSpacing_+1) / 2; if (nextRow == (int)rowCount) padding[2] = margin[2]; else padding[2] = grid_.verticalSpacing_ / 2; if (prevCol == -1) padding[3] = margin[3]; else padding[3] = (grid_.horizontalSpacing_ + 1)/2; if (nextCol == (int)colCount) padding[1] = margin[1]; else padding[1] = (grid_.horizontalSpacing_)/2; WStringStream style; if (app->layoutDirection() == RightToLeft) std::swap(padding[1], padding[3]); if (padding[0] == padding[1] && padding[0] == padding[2] && padding[0] == padding[3]) { if (padding[0] != 0) style << "padding:" << padding[0] << "px;"; } else style << "padding:" << padding[0] << "px " << padding[1] << "px " << padding[2] << "px " << padding[3] << "px;"; if (vAlign != 0) switch (vAlign) { case AlignTop: style << "vertical-align:top;"; break; case AlignMiddle: style << "vertical-align:middle;"; break; case AlignBottom: style << "vertical-align:bottom;"; default: break; } td->setProperty(PropertyStyle, style.str()); if (item.rowSpan_ != 1) td->setProperty(PropertyRowSpan, boost::lexical_cast<std::string>(item.rowSpan_)); if (item.colSpan_ != 1) td->setProperty(PropertyColSpan, boost::lexical_cast<std::string>(item.colSpan_)); prevColumnWithItem = col; } } DomElement *c = 0; if (!table) { if (item.item_) { c = createElement(item.item_, app); div->addChild(c); } } else if (item.item_) c = getImpl(item.item_)->createDomElement(true, true, app); if (table) { if (c) { if (!app->environment().agentIsIElt(9)) c->setProperty(PropertyStyleBoxSizing, "border-box"); if (hAlign == 0) hAlign = AlignJustify; switch (hAlign) { case AlignCenter: { DomElement *itable = DomElement::createNew(DomElement_TABLE); itable->setProperty(PropertyClass, "Wt-hcenter"); if (vAlign == 0) itable->setProperty(PropertyStyle, "height:100%;"); DomElement *irow = DomElement::createNew(DomElement_TR); DomElement *itd = DomElement::createNew(DomElement_TD); if (vAlign == 0) itd->setProperty(PropertyStyle, "height:100%;"); bool haveMinWidth = !c->getProperty(PropertyStyleMinWidth).empty(); itd->addChild(c); if (app->environment().agentIsIElt(9)) { // IE7 and IE8 do support min-width but do not enforce it // properly when in a table. // see http://stackoverflow.com/questions/2356525 // /css-min-width-in-ie6-7-and-8 if (haveMinWidth) { DomElement *spacer = DomElement::createNew(DomElement_DIV); spacer->setProperty(PropertyStyleWidth, c->getProperty(PropertyStyleMinWidth)); spacer->setProperty(PropertyStyleHeight, "1px"); itd->addChild(spacer); } } irow->addChild(itd); itable->addChild(irow); c = itable; break; } case AlignRight: if (!c->isDefaultInline()) c->setProperty(PropertyStyleFloat, "right"); else td->setProperty(PropertyStyleTextAlign, "right"); break; case AlignLeft: if (!c->isDefaultInline()) c->setProperty(PropertyStyleFloat, "left"); else td->setProperty(PropertyStyleTextAlign, "left"); break; default: break; } td->addChild(c); if (app->environment().agentIsIElt(9)) { // IE7 and IE8 do support min-width but do not enforce it properly // when in a table. // see http://stackoverflow.com/questions/2356525 // /css-min-width-in-ie6-7-and-8 if (!c->getProperty(PropertyStyleMinWidth).empty()) { DomElement *spacer = DomElement::createNew(DomElement_DIV); spacer->setProperty(PropertyStyleWidth, c->getProperty(PropertyStyleMinWidth)); spacer->setProperty(PropertyStyleHeight, "1px"); td->addChild(spacer); } } } tr->addChild(td); } } } if (tr) { if (!rowVisible) tr->setProperty(PropertyStyleDisplay, "hidden"); else prevRowWithItem = row; tbody->addChild(tr); } } js << "));"; if (table) { table->addChild(tbody); div->addChild(table); } div->callJavaScript(js.str()); return div; }
void StdGridLayoutImpl2::updateDom(DomElement& parent) { WApplication *app = WApplication::instance(); if (needConfigUpdate_) { needConfigUpdate_ = false; DomElement *div = DomElement::getForUpdate(this, DomElement_DIV); for (unsigned i = 0; i < addedItems_.size(); ++i) { WLayoutItem *item = addedItems_[i]; DomElement *c = createElement(item, app); div->addChild(c); } addedItems_.clear(); for (unsigned i = 0; i < removedItems_.size(); ++i) parent.callJavaScript(WT_CLASS ".remove('" + removedItems_[i] + "');", true); removedItems_.clear(); parent.addChild(div); WStringStream js; js << app->javaScriptClass() << ".layouts2.updateConfig('" << id() << "',"; streamConfig(js, app); js << ");"; app->doJavaScript(js.str()); } if (needRemeasure_) { needRemeasure_ = false; WStringStream js; js << app->javaScriptClass() << ".layouts2.setDirty('" << id() << "');"; app->doJavaScript(js.str()); } if (needAdjust_) { needAdjust_ = false; WStringStream js; js << app->javaScriptClass() << ".layouts2.adjust('" << id() << "', ["; bool first = true; const unsigned colCount = grid_.columns_.size(); const unsigned rowCount = grid_.rows_.size(); for (unsigned row = 0; row < rowCount; ++row) for (unsigned col = 0; col < colCount; ++col) if (grid_.items_[row][col].update_) { grid_.items_[row][col].update_ = false; if (!first) js << ","; first = false; js << "[" << (int)row << "," << (int)col << "]"; } js << "]);"; app->doJavaScript(js.str()); } const unsigned colCount = grid_.columns_.size(); const unsigned rowCount = grid_.rows_.size(); for (unsigned i = 0; i < rowCount; ++i) { for (unsigned j = 0; j < colCount; ++j) { WLayoutItem *item = grid_.items_[i][j].item_; if (item) { WLayout *nested = item->layout(); if (nested) (dynamic_cast<StdLayoutImpl *>(nested->impl()))->updateDom(parent); } } } }
void WGLWidget::updateDom(DomElement &element, bool all) { if (webGlNotAvailable_) return; DomElement *el = &element; if (all || sizeChanged_) { el->setAttribute("width", boost::lexical_cast<std::string>(renderWidth_)); el->setAttribute("height", boost::lexical_cast<std::string>(renderHeight_)); sizeChanged_ = false; } if (updateGL_ || updateResizeGL_ || updatePaintGL_) { std::stringstream tmp; tmp << "var o = " << glObjJsRef() << ";\n" "if(o.ctx){\n"; if (updateGL_) { js_.str(""); updateGL(); tmp << "var update =function(){\n" "var obj=" << glObjJsRef() << ";\n" "var ctx=obj.ctx;if (!ctx) return;\n" << js_.str() << "\n};\n" // cannot execute updates before initializeGL is executed "o.updates.push(update);"; } if (updateResizeGL_) { js_.str(""); resizeGL(renderWidth_, renderHeight_); tmp << "o.resizeGL=function(){\n" "var obj=" << glObjJsRef() << ";\n" "var ctx=obj.ctx;if (!ctx) return;\n" << js_.str() << "};"; } if (updatePaintGL_) { js_.str(""); paintGL(); // TG: cannot overwrite paint before update is executed // therefore overwrite paintgl in a deferred function through the // tasks queue tmp << "var updatePaint = function(){\n"; tmp << "var obj=" << glObjJsRef() << ";\n"; tmp << "obj.paintGL=function(){\n" "var obj=" << glObjJsRef() << ";\n" "var ctx=obj.ctx;if (!ctx) return;\n" << js_.str() << "};"; tmp << "};\n"; tmp << "o.updates.push(updatePaint);"; } js_.str(""); // Make sure textures are loaded before we render tmp << "}\n"; // Preloading images and buffers const bool preloadingSomething = preloadImages_.size()>0 || preloadArrayBuffers_.size() >0; if (preloadingSomething) { if (preloadImages_.size() > 0) { tmp << //"debugger;" "o.preloadingTextures++;" "new Wt._p_.ImagePreloader(["; for (unsigned i = 0; i < preloadImages_.size(); ++i) { if (i != 0) tmp << ','; tmp << '\'' << resolveRelativeUrl(preloadImages_[i].second) << '\''; } tmp << "],function(images){\n" //"debugger;\n" "var o=" << glObjJsRef() << ";\n" "var ctx=null;\n" "if(o) ctx=o.ctx;\n" "if(ctx == null) return;\n"; for (unsigned i = 0; i < preloadImages_.size(); ++i) { std::string texture = preloadImages_[i].first; tmp << texture << "=ctx.createTexture();\n" << texture << ".image=images[" << i << "];\n"; } tmp << "o.preloadingTextures--;\n" << "o.handlePreload();\n" << "});"; preloadImages_.clear(); } // now check for buffers to preload if (preloadArrayBuffers_.size() > 0) { tmp << "o.preloadingBuffers++;" "new Wt._p_.ArrayBufferPreloader(["; for (unsigned i = 0; i < preloadArrayBuffers_.size(); ++i) { if (i != 0) tmp << ','; //preloadingStream << '\'' << resolveRelativeUrl(preloadBufferResources_[i].second) << '\''; tmp << '\'' << wApp->makeAbsoluteUrl(preloadArrayBuffers_[i].second) << '\''; } tmp << "],function(bufferResources){\n" //"debugger;\n" "var o=" << glObjJsRef() << ";\n" "var ctx=null;\n" " if(o) ctx=o.ctx;\n" "if(ctx == null) return;\n"; for (unsigned i = 0; i < preloadArrayBuffers_.size(); ++i) { std::string bufferResource = preloadArrayBuffers_[i].first; // setup datatype tmp << bufferResource << "={data:0};\n"; // set the data tmp << bufferResource << ".data=bufferResources[" << i << "];\n"; } tmp << "o.preloadingBuffers--;" << "o.handlePreload();\n" << "});"; preloadArrayBuffers_.clear(); } } else { // No textures or buffers to load - go and paint tmp << "o.handlePreload();"; } el->callJavaScript(tmp.str()); updateGL_ = updatePaintGL_ = updateResizeGL_ = false; } WInteractWidget::updateDom(element, all); }
void WGLWidget::updateDom(DomElement &element, bool all) { if (webGlNotAvailable_) return; DomElement *el = &element; if (all || sizeChanged_) { el->setAttribute("width", boost::lexical_cast<std::string>(renderWidth_)); el->setAttribute("height", boost::lexical_cast<std::string>(renderHeight_)); sizeChanged_ = false; } if (updateGL_ || updateResizeGL_ || updatePaintGL_) { std::stringstream tmp; tmp << "var o = " << glObjJsRef() << ";\n" "if(o.ctx){\n"; if (updateGL_) { js_.str(""); updateGL(); tmp << "var update =function(){\n" "var obj=" << glObjJsRef() << ";\n" "var ctx=obj.ctx;if (!ctx) return;\n" << js_.str() << "\n};\n" // cannot execute updates before initializeGL is executed "o.updates.push(update);"; } if (updateResizeGL_) { js_.str(""); resizeGL(renderWidth_, renderHeight_); tmp << "o.resizeGL=function(){\n" "var obj=" << glObjJsRef() << ";\n" "var ctx=obj.ctx;if (!ctx) return;\n" << js_.str() << "};"; } if (updatePaintGL_) { js_.str(""); paintGL(); tmp << "o.paintGL=function(){\n" "var obj=" << glObjJsRef() << ";\n" "var ctx=obj.ctx;if (!ctx) return;\n" << js_.str() << "};"; } js_.str(""); // Make sure textures are loaded before we render tmp << "}\n"; if (preloadImages_.size() > 0) { //tmp << "debugger;\n"; tmp << "o.preloadingTextures=true;" "new Wt._p_.ImagePreloader(["; for (unsigned i = 0; i < preloadImages_.size(); ++i) { if (i != 0) tmp << ','; tmp << '\'' << resolveRelativeUrl(preloadImages_[i].second) << '\''; } tmp << "],function(images){\n" "var o=" << glObjJsRef() << ";\n" "var ctx=null;\n" " if(o) ctx=o.ctx;\n" "o.preloadingTextures=false;" "if(ctx == null) return;\n"; for (unsigned i = 0; i < preloadImages_.size(); ++i) { std::string texture = preloadImages_[i].first; tmp << texture << "=ctx.createTexture();\n" << texture << ".image=images[" << i << "];\n"; } tmp << "if(o.initialized){" // Delay calling of update() to after textures are loaded """var key;" """for(key in o.updates) o.updates[key]();" """o.updates = new Array();" // Delay calling of resizeGL() to after updates are executed """o.resizeGL();" """o.paintGL();" "} else {" // initializeGL will call updates and resizeGL """o.initializeGL();\n" """o.resizeGL();\n" """o.paintGL();\n" "}});"; preloadImages_.clear(); } else { // No textures to load - go and paint tmp << "if(!o.preloadingTextures){" // It's not ok to execute an update method or initialize if we're // waiting for texture to load; this will result in undefined // symbols in JS. After textures are loaded, the code sequence below // is executed from there. """if(o.initialized) {" "" "var key;" "" "for(key in o.updates) o.updates[key]();" "" "o.updates = new Array();" "" "o.resizeGL();" "" "o.paintGL();" """} else {" "" "o.initializeGL();" "" "o.resizeGL();" "" "o.paintGL();" """}" "}"; } el->callJavaScript(tmp.str()); updateGL_ = updatePaintGL_ = updateResizeGL_ = false; } WInteractWidget::updateDom(element, all); }
void WFormWidget::updateDom(DomElement& element, bool all) { const WEnvironment& env = WApplication::instance()->environment(); bool onChangeHandledElsewhere = dynamic_cast<WAbstractToggleButton *>(this); if (!onChangeHandledElsewhere) { EventSignal<> *s = voidEventSignal(CHANGE_SIGNAL, false); if (s) updateSignalConnection(element, *s, "change", all); } if (flags_.test(BIT_ENABLED_CHANGED) || all) { if (!all || !isEnabled()) element.setProperty(Wt::PropertyDisabled, isEnabled() ? "false" : "true"); if (!all && isEnabled() && env.agentIsIE()) { /* * FIXME: implement a workaround for IE, reenabling a checkbox makes * the input box loose interactivity. */ } flags_.reset(BIT_ENABLED_CHANGED); } if (flags_.test(BIT_READONLY_CHANGED) || all) { if (!all || isReadOnly()) element.setProperty(Wt::PropertyReadOnly, isReadOnly() ? "true" : "false"); flags_.reset(BIT_READONLY_CHANGED); } if (flags_.test(BIT_TABINDEX_CHANGED) || all) { if (!all || tabIndex_) element.setProperty(PropertyTabIndex, boost::lexical_cast<std::string>(tabIndex_)); flags_.reset(BIT_TABINDEX_CHANGED); } if (flags_.test(BIT_GOT_FOCUS)) { WApplication *app = WApplication::instance(); element.callJavaScript("setTimeout(function() {" """var o = " + jsRef() + ";" """if (o) {" "" "if (!$(o).hasClass('" + app->theme()->disabledClass() + "')) {" "" "try { " "" "o.focus();" "" "} catch (e) {}" "" "}" """}" "}, " + (env.agentIsIElt(9) ? "500" : "10") + ");"); flags_.reset(BIT_GOT_FOCUS); } WInteractWidget::updateDom(element, all); if (flags_.test(BIT_VALIDATION_CHANGED)) { if (validationToolTip_.empty()) element.setAttribute("title", toolTip().toUTF8()); else element.setAttribute("title", validationToolTip_.toUTF8()); } }