EventSignal<WMouseEvent>& WInteractWidget::mouseWheel() { if (WApplication::instance()->environment().agentIsIElt(9)) { return *mouseEventSignal(MOUSE_WHEEL_SIGNAL, true); } else { return *mouseEventSignal(WHEEL_SIGNAL, true); } }
void WInteractWidget::setMouseOverDelay(int delay) { mouseOverDelay_ = delay; EventSignal<WMouseEvent> *mouseOver = mouseEventSignal(MOUSE_OVER_SIGNAL, false); if (mouseOver) mouseOver->senderRepaint(); }
void WAbstractToggleButton::updateDom(DomElement& element, bool all) { WApplication *app = WApplication::instance(); const WEnvironment& env = app->environment(); DomElement *input = 0; DomElement *span = 0; DomElement *label = 0; // Already apply theme here because it may determine its organization if (all) app->theme()->apply(this, element, 1); if (element.type() == DomElement_INPUT) input = &element; else { if (all) { input = DomElement::createNew(DomElement_INPUT); input->setName("in" + id()); span = DomElement::createNew(DomElement_SPAN); span->setName("t" + id()); if (element.type() != DomElement_LABEL) { label = DomElement::createNew(DomElement_LABEL); label->setName("l" + id()); } } else { input = DomElement::getForUpdate("in" + id(), DomElement_INPUT); span = DomElement::getForUpdate("t" + id(), DomElement_SPAN); } } if (all) updateInput(*input, all); EventSignal<> *check = voidEventSignal(CHECKED_SIGNAL, false); EventSignal<> *uncheck = voidEventSignal(UNCHECKED_SIGNAL, false); EventSignal<> *change = voidEventSignal(CHANGE_SIGNAL, false); EventSignal<WMouseEvent> *click = mouseEventSignal(M_CLICK_SIGNAL, false); /* * We piggy-back the checked and uncheck signals on the change signal. * * If agent is IE, then we piggy-back the change on the clicked signal. */ bool piggyBackChangeOnClick = env.agentIsIE(); bool needUpdateChangeSignal = (change && change->needsUpdate(all)) || (check && check->needsUpdate(all)) || (uncheck && uncheck->needsUpdate(all)); bool needUpdateClickedSignal = (click && click->needsUpdate(all)) || (piggyBackChangeOnClick && needUpdateChangeSignal); WFormWidget::updateDom(*input, all); /* * Copy all properties to the exterior element, as they relate to style, * etc... We ignore here attributes (except for tooltip), * see WWebWidget: other attributes need not be moved. * * But -- bug #423, disabled and readonly are properties that should be * kept on the interior element. */ if (&element != input) { if (element.properties().find(PropertyClass) != element.properties().end()) input->addPropertyWord(PropertyClass, element.getProperty(PropertyClass)); element.setProperties(input->properties()); input->clearProperties(); std::string v = element.getProperty(Wt::PropertyDisabled); if (!v.empty()) { input->setProperty(Wt::PropertyDisabled, v); element.removeProperty(Wt::PropertyDisabled); } v = element.getProperty(Wt::PropertyReadOnly); if (!v.empty()) { input->setProperty(Wt::PropertyReadOnly, v); element.removeProperty(Wt::PropertyReadOnly); } v = input->getAttribute("title"); if (!v.empty()) element.setAttribute("title", v); } if (flags_.test(BIT_STATE_CHANGED) || all) { input->setProperty(Wt::PropertyChecked, state_ == Unchecked ? "false" : "true"); if (supportsIndeterminate(env)) input->setProperty(Wt::PropertyIndeterminate, state_ == PartiallyChecked ? "true" : "false"); else input->setProperty(Wt::PropertyStyleOpacity, state_ == PartiallyChecked ? "0.5" : ""); flags_.reset(BIT_STATE_CHANGED); } std::vector<DomElement::EventAction> changeActions; if (needUpdateChangeSignal || (piggyBackChangeOnClick && needUpdateClickedSignal) || all) { std::string dom = "o"; if (check) { if (check->isConnected()) changeActions.push_back (DomElement::EventAction(dom + ".checked", check->javaScript(), check->encodeCmd(), check->isExposedSignal())); check->updateOk(); } if (uncheck) { if (uncheck->isConnected()) changeActions.push_back (DomElement::EventAction("!" + dom + ".checked", uncheck->javaScript(), uncheck->encodeCmd(), uncheck->isExposedSignal())); uncheck->updateOk(); } if (change) { if (change->isConnected()) changeActions.push_back (DomElement::EventAction(std::string(), change->javaScript(), change->encodeCmd(), change->isExposedSignal())); change->updateOk(); } if (!piggyBackChangeOnClick) { if (!(all && changeActions.empty())) input->setEvent("change", changeActions); } } if (needUpdateClickedSignal || all) { if (piggyBackChangeOnClick) { if (click) { changeActions.push_back (DomElement::EventAction(std::string(), click->javaScript(), click->encodeCmd(), click->isExposedSignal())); click->updateOk(); } if (!(all && changeActions.empty())) input->setEvent(CLICK_SIGNAL, changeActions); } else if (click) updateSignalConnection(*input, *click, CLICK_SIGNAL, all); } if (span) { if (all || flags_.test(BIT_TEXT_CHANGED)) { span->setProperty(PropertyInnerHTML, text_.formattedText()); if(all || flags_.test(BIT_WORD_WRAP_CHANGED)) { span->setProperty(PropertyStyleWhiteSpace, flags_.test(BIT_WORD_WRAP) ? "normal" : "nowrap"); flags_.reset(BIT_WORD_WRAP_CHANGED); } flags_.reset(BIT_TEXT_CHANGED); } } if (&element != input) { if (label) { label->addChild(input); label->addChild(span); element.addChild(label); } else { element.addChild(input); element.addChild(span); } } }
void WAbstractToggleButton::updateDom(DomElement& element, bool all) { WApplication *app = WApplication::instance(); const WEnvironment& env = app->environment(); DomElement *input = 0; DomElement *span = 0; if (element.type() == DomElement_LABEL) { if (all) { input = DomElement::createNew(DomElement_INPUT); input->setName("in" + id()); span = DomElement::createNew(DomElement_SPAN); span->setName("l" + id()); } else { input = DomElement::getForUpdate("in" + id(), DomElement_INPUT); span = DomElement::getForUpdate("l" + id(), DomElement_SPAN); } } else input = &element; if (all) updateInput(*input, all); EventSignal<> *check = voidEventSignal(CHECKED_SIGNAL, false); EventSignal<> *uncheck = voidEventSignal(UNCHECKED_SIGNAL, false); EventSignal<> *change = voidEventSignal(CHANGE_SIGNAL, false); EventSignal<WMouseEvent> *click = mouseEventSignal(M_CLICK_SIGNAL, false); /* * We piggy-back the checked and uncheck signals on the change signal. * * If agent is IE, then we piggy-back the change on the clicked signal. */ bool piggyBackChangeOnClick = env.agentIsIE(); bool needUpdateChangeSignal = (change && change->needsUpdate(all)) || (check && check->needsUpdate(all)) || (uncheck && uncheck->needsUpdate(all)); bool needUpdateClickedSignal = (click && click->needsUpdate(all)) || (piggyBackChangeOnClick && needUpdateChangeSignal); WFormWidget::updateDom(*input, all); /* * Copy all properties to the exterior element, as they relate to style, * etc... We ignore here attributes, see WWebWidget: there seems not to * be attributes that sensibly need to be moved. * * But -- bug #423, disabled and readonly are properties that should be * kept on the interior element. */ if (&element != input) { element.setProperties(input->properties()); input->clearProperties(); std::string v = element.getProperty(Wt::PropertyDisabled); if (!v.empty()) { input->setProperty(Wt::PropertyDisabled, v); element.removeProperty(Wt::PropertyDisabled); } v = element.getProperty(Wt::PropertyReadOnly); if (!v.empty()) { input->setProperty(Wt::PropertyReadOnly, v); element.removeProperty(Wt::PropertyReadOnly); } } if (stateChanged_ || all) { input->setProperty(Wt::PropertyChecked, state_ == Unchecked ? "false" : "true"); if (supportsIndeterminate(env)) input->setProperty(Wt::PropertyIndeterminate, state_ == PartiallyChecked ? "true" : "false"); else input->setProperty(Wt::PropertyStyleOpacity, state_ == PartiallyChecked ? "0.5" : ""); stateChanged_ = false; } std::vector<DomElement::EventAction> changeActions; if (needUpdateChangeSignal || (piggyBackChangeOnClick && needUpdateClickedSignal) || all) { std::string dom = "o"; if (check) { if (check->isConnected()) changeActions.push_back (DomElement::EventAction(dom + ".checked", check->javaScript(), check->encodeCmd(), check->isExposedSignal())); check->updateOk(); } if (uncheck) { if (uncheck->isConnected()) changeActions.push_back (DomElement::EventAction("!" + dom + ".checked", uncheck->javaScript(), uncheck->encodeCmd(), uncheck->isExposedSignal())); uncheck->updateOk(); } if (change) { if (change->needsUpdate(all)) changeActions.push_back (DomElement::EventAction(std::string(), change->javaScript(), change->encodeCmd(), change->isExposedSignal())); change->updateOk(); } if (!piggyBackChangeOnClick) { if (!(all && changeActions.empty())) input->setEvent("change", changeActions); } } if (needUpdateClickedSignal || all) { if (piggyBackChangeOnClick) { if (click) { changeActions.push_back (DomElement::EventAction(std::string(), click->javaScript(), click->encodeCmd(), click->isExposedSignal())); click->updateOk(); } if (!(all && changeActions.empty())) input->setEvent(CLICK_SIGNAL, changeActions); } else if (click) updateSignalConnection(*input, *click, CLICK_SIGNAL, all); } if (span) { if (all || textChanged_) { span->setProperty(PropertyInnerHTML, text_.formattedText()); textChanged_ = false; } } if (&element != input) { element.addChild(input); element.addChild(span); } }
void WInteractWidget::updateDom(DomElement& element, bool all) { bool updateKeyDown = false; WApplication *app = WApplication::instance(); /* * -- combine enterPress, escapePress and keyDown signals */ EventSignal<> *enterPress = voidEventSignal(ENTER_PRESS_SIGNAL, false); EventSignal<> *escapePress = voidEventSignal(ESCAPE_PRESS_SIGNAL, false); EventSignal<WKeyEvent> *keyDown = keyEventSignal(KEYDOWN_SIGNAL, false); updateKeyDown = (enterPress && enterPress->needsUpdate(all)) || (escapePress && escapePress->needsUpdate(all)) || (keyDown && keyDown->needsUpdate(all)); if (updateKeyDown) { std::vector<DomElement::EventAction> actions; if (enterPress) { if (enterPress->needsUpdate(true)) { /* * prevent enterPressed from triggering a changed event on all * browsers except for Opera and IE */ std::string extraJS; const WEnvironment& env = app->environment(); if (dynamic_cast<WFormWidget *>(this) && !env.agentIsOpera() && !env.agentIsIE()) extraJS = "var g=this.onchange;" "" "this.onchange=function(){this.onchange=g;};"; actions.push_back (DomElement::EventAction("e.keyCode && (e.keyCode == 13)", enterPress->javaScript() + extraJS, enterPress->encodeCmd(), enterPress->isExposedSignal())); } enterPress->updateOk(); } if (escapePress) { if (escapePress->needsUpdate(true)) { actions.push_back (DomElement::EventAction("e.keyCode && (e.keyCode == 27)", escapePress->javaScript(), escapePress->encodeCmd(), escapePress->isExposedSignal())); } escapePress->updateOk(); } if (keyDown) { if (keyDown->needsUpdate(true)) { actions.push_back (DomElement::EventAction(std::string(), keyDown->javaScript(), keyDown->encodeCmd(), keyDown->isExposedSignal())); } keyDown->updateOk(); } if (!actions.empty()) element.setEvent("keydown", actions); else if (!all) element.setEvent("keydown", std::string(), std::string()); } /* * -- allow computation of dragged mouse distance */ EventSignal<WMouseEvent> *mouseDown = mouseEventSignal(MOUSE_DOWN_SIGNAL, false); EventSignal<WMouseEvent> *mouseUp = mouseEventSignal(MOUSE_UP_SIGNAL, false); EventSignal<WMouseEvent> *mouseMove = mouseEventSignal(MOUSE_MOVE_SIGNAL, false); EventSignal<WMouseEvent> *mouseDrag = mouseEventSignal(MOUSE_DRAG_SIGNAL, false); bool updateMouseMove = (mouseMove && mouseMove->needsUpdate(all)) || (mouseDrag && mouseDrag->needsUpdate(all)); bool updateMouseDown = (mouseDown && mouseDown->needsUpdate(all)) || updateMouseMove; bool updateMouseUp = (mouseUp && mouseUp->needsUpdate(all)) || updateMouseMove; std::string CheckDisabled = "if($(o).hasClass('" + app->theme()->disabledClass() + "')){" WT_CLASS ".cancelEvent(e);return;}"; if (updateMouseDown) { /* * when we have a mouseUp event, we also need a mouseDown event * to be able to compute dragDX/Y. * * When we have: * - a mouseDrag * - or a mouseDown + (mouseMove or mouseUp), * we need to capture everything after on mouse down, and keep track of the * down button if we have a mouseMove or mouseDrag */ WStringStream js; js << CheckDisabled; if (mouseUp && mouseUp->isConnected()) js << app->javaScriptClass() << "._p_.saveDownPos(event);"; if ((mouseDrag && mouseDrag->isConnected()) || (mouseDown && mouseDown->isConnected() && ((mouseUp && mouseUp->isConnected()) || (mouseMove && mouseMove->isConnected())))) js << WT_CLASS ".capture(this);"; if ((mouseMove && mouseMove->isConnected()) || (mouseDrag && mouseDrag->isConnected())) js << WT_CLASS ".mouseDown(e);"; if (mouseDown) { js << mouseDown->javaScript(); element.setEvent("mousedown", js.str(), mouseDown->encodeCmd(), mouseDown->isExposedSignal()); mouseDown->updateOk(); } else element.setEvent("mousedown", js.str(), std::string(), false); } if (updateMouseUp) { WStringStream js; /* * when we have a mouseMove or mouseDrag event, we need to keep track * of unpressing the button. */ js << CheckDisabled; if ((mouseMove && mouseMove->isConnected()) || (mouseDrag && mouseDrag->isConnected())) js << WT_CLASS ".mouseUp(e);"; if (mouseUp) { js << mouseUp->javaScript(); element.setEvent("mouseup", js.str(), mouseUp->encodeCmd(), mouseUp->isExposedSignal()); mouseUp->updateOk(); } else element.setEvent("mouseup", js.str(), std::string(), false); } if (updateMouseMove) { /* * We need to mix mouseDrag and mouseMove events. */ std::vector<DomElement::EventAction> actions; if (mouseMove) { actions.push_back (DomElement::EventAction(std::string(), mouseMove->javaScript(), mouseMove->encodeCmd(), mouseMove->isExposedSignal())); mouseMove->updateOk(); } if (mouseDrag) { actions.push_back (DomElement::EventAction(WT_CLASS ".buttons", mouseDrag->javaScript() + WT_CLASS ".drag(e);", mouseDrag->encodeCmd(), mouseDrag->isExposedSignal())); mouseDrag->updateOk(); } element.setEvent("mousemove", actions); } /* * -- mix mouseClick and mouseDblClick events in mouseclick since we * only want to fire one of both */ EventSignal<WMouseEvent> *mouseClick = mouseEventSignal(M_CLICK_SIGNAL, false); EventSignal<WMouseEvent> *mouseDblClick = mouseEventSignal(DBL_CLICK_SIGNAL, false); bool updateMouseClick = (mouseClick && mouseClick->needsUpdate(all)) || (mouseDblClick && mouseDblClick->needsUpdate(all)); if (updateMouseClick) { WStringStream js; js << CheckDisabled; if (mouseDrag) js << "if (" WT_CLASS ".dragged()) return;"; if (mouseDblClick && mouseDblClick->needsUpdate(all)) { /* * Click: if timer is running: * - clear timer, dblClick() * - start timer, clear timer and click() */ /* We have to prevent this immediately ! */ if (mouseClick) { if (mouseClick->defaultActionPrevented() || mouseClick->propagationPrevented()) { js << WT_CLASS ".cancelEvent(e"; if (mouseClick->defaultActionPrevented() && mouseClick->propagationPrevented()) js << ");"; else if (mouseClick->defaultActionPrevented()) js << ",0x2);"; else js << ",0x1);"; } } js << "if(" WT_CLASS ".isDblClick(o, e)) {" << mouseDblClick->javaScript(); if (mouseDblClick->isExposedSignal()) js << app->javaScriptClass() << "._p_.update(o,'" << mouseDblClick->encodeCmd() << "',e,true);"; mouseDblClick->updateOk(); js << "}else{" """if (" WT_CLASS ".isIElt9 && document.createEventObject) " "" "e = document.createEventObject(e);" """o.wtE1 = e;" """o.wtClickTimeout = setTimeout(function() {" "" "o.wtClickTimeout = null; o.wtE1 = null;"; if (mouseClick) { js << mouseClick->javaScript(); if (mouseClick->isExposedSignal()) { js << app->javaScriptClass() << "._p_.update(o,'" << mouseClick->encodeCmd() << "',e,true);"; } mouseClick->updateOk(); } const Configuration& conf = app->environment().server()->configuration(); js << "}," << conf.doubleClickTimeout() << ");}"; } else { if (mouseClick && mouseClick->needsUpdate(all)) { js << mouseClick->javaScript(); if (mouseClick->isExposedSignal()) { js << app->javaScriptClass() << "._p_.update(o,'" << mouseClick->encodeCmd() << "',e,true);"; } mouseClick->updateOk(); } } element.setEvent(CLICK_SIGNAL, js.str(), mouseClick ? mouseClick->encodeCmd() : ""); if (mouseDblClick) { if (app->environment().agentIsIElt(9)) element.setEvent("dblclick", "this.onclick()"); } } /* * -- mouseOver with delay */ EventSignal<WMouseEvent> *mouseOver = mouseEventSignal(MOUSE_OVER_SIGNAL, false); EventSignal<WMouseEvent> *mouseOut = mouseEventSignal(MOUSE_OUT_SIGNAL, false); bool updateMouseOver = mouseOver && mouseOver->needsUpdate(all); if (mouseOverDelay_) { if (updateMouseOver) { WStringStream js; js << "o.over=setTimeout(function() {" << "o.over = null;" << mouseOver->javaScript(); if (mouseOver->isExposedSignal()) { js << app->javaScriptClass() << "._p_.update(o,'" << mouseOver->encodeCmd() << "',e,true);"; } js << "}," << mouseOverDelay_ << ");"; element.setEvent("mouseover", js.str(), ""); mouseOver->updateOk(); if (!mouseOut) mouseOut = mouseEventSignal(MOUSE_OUT_SIGNAL, true); element.setEvent("mouseout", "clearTimeout(o.over); o.over=null;" + mouseOut->javaScript(), mouseOut->encodeCmd(), mouseOut->isExposedSignal()); mouseOut->updateOk(); } } else { if (updateMouseOver) { element.setEventSignal("mouseover", *mouseOver); mouseOver->updateOk(); } bool updateMouseOut = mouseOut && mouseOut->needsUpdate(all); if (updateMouseOut) { element.setEventSignal("mouseout", *mouseOut); mouseOut->updateOk(); } } updateEventSignals(element, all); WWebWidget::updateDom(element, all); }
EventSignal<WMouseEvent>& WInteractWidget::mouseMoved() { return *mouseEventSignal(MOUSE_MOVE_SIGNAL, true); }
EventSignal<WMouseEvent>& WInteractWidget::mouseDragged() { return *mouseEventSignal(MOUSE_DRAG_SIGNAL, true); }
EventSignal<WMouseEvent>& WInteractWidget::mouseWentOver() { return *mouseEventSignal(MOUSE_OVER_SIGNAL, true); }
EventSignal<WMouseEvent>& WInteractWidget::mouseWentUp() { return *mouseEventSignal(MOUSE_UP_SIGNAL, true); }
EventSignal<WMouseEvent>& WInteractWidget::mouseWentDown() { return *mouseEventSignal(MOUSE_DOWN_SIGNAL, true); }
EventSignal<WMouseEvent>& WInteractWidget::doubleClicked() { return *mouseEventSignal(DBL_CLICK_SIGNAL, true); }
EventSignal<WMouseEvent>& WInteractWidget::clicked() { return *mouseEventSignal(M_CLICK_SIGNAL, true); }