void WAbstractSpinBox::render(WFlags<RenderFlag> flags)
{
  /*
   * In theory we are a bit late here to decide what we want to become:
   * somebody could already have asked the domElementType()
   */
  if (!setup_ && flags.test(RenderFlag::Full)) {
    setup();
  }

  if (jsValueChanged().needsUpdate(true)) {
    WStringStream function;
    function << "jQuery.data(" + jsRef() + ",'obj').jsValueChanged=";
    if (jsValueChanged().isConnected()) {
      function << "function(oldv, v){"
               << "var o=null;var e=null;" << jsValueChanged().createCall({"oldv", "v"}) << "};";
    } else {
      function << "function() {};";
    }
    doJavaScript(function.str());
  }

  WLineEdit::render(flags);
}
Exemple #2
0
void WCalendar::create()
{
  selectionMode_ = SingleSelection;
  singleClickSelect_ = false;
  horizontalHeaderFormat_ = ShortDayNames;
  firstDayOfWeek_ = 1;
  cellClickMapper_ = 0;
  cellDblClickMapper_ = 0;

  WDate currentDay = WDate::currentDate();

  currentYear_ = currentDay.year();
  currentMonth_ = currentDay.month();

  WStringStream text;

  text <<
    "<table class=\"days ${table-class}\" cellspacing=\"0\" cellpadding=\"0\">"
    """<tr>"
    ""  "<th class=\"caption\">${nav-prev}</th>"
    ""  "<th class=\"caption\"colspan=\"5\">${month} ${year}</th>"
    ""  "<th class=\"caption\">${nav-next}</th>"
    """</tr>"
    """<tr>";

  for (int j = 0; j < 7; ++j)
    text <<
      "<th title=\"${t" << j << "}\" scope=\"col\">${d" << j << "}</th>";

  text << "</tr>";

  for (int i = 0; i < 6; ++i) {
    text << "<tr>";
    for (int j = 0; j < 7; ++j)
      text << "<td>${c" << (i * 7 + j) << "}</td>";
    text << "</tr>";
  }

  text << "</table>";

  setImplementation(impl_ = new WTemplate());
  impl_->setTemplateText(WString::fromUTF8(text.str()), XHTMLUnsafeText);
  impl_->setStyleClass("Wt-cal");

  setSelectable(false);

  WText *prevMonth = new WText(tr("Wt.WCalendar.PrevMonth"));
  prevMonth->setStyleClass("Wt-cal-navbutton");
  prevMonth->clicked().connect(this, &WCalendar::browseToPreviousMonth);

  WText *nextMonth = new WText(tr("Wt.WCalendar.NextMonth"));
  nextMonth->setStyleClass("Wt-cal-navbutton");
  nextMonth->clicked().connect(this, &WCalendar::browseToNextMonth);

  monthEdit_ = new WComboBox();
  monthEdit_->setInline(true);
  for (unsigned i = 0; i < 12; ++i)
    monthEdit_->addItem(WDate::longMonthName(i+1));
  monthEdit_->activated().connect(this, &WCalendar::monthChanged);
  monthEdit_->setDisabled(!WApplication::instance()->environment().ajax());

  yearEdit_ = new WInPlaceEdit("");
  yearEdit_->setButtonsEnabled(false);
  yearEdit_->lineEdit()->setTextSize(4);
  yearEdit_->setStyleClass("Wt-cal-year");
  yearEdit_->valueChanged().connect(this, &WCalendar::yearChanged);

  impl_->bindWidget("nav-prev", prevMonth);
  impl_->bindWidget("nav-next", nextMonth);
  impl_->bindWidget("month", monthEdit_);
  impl_->bindWidget("year", yearEdit_);

  setHorizontalHeaderFormat(horizontalHeaderFormat_);
  setFirstDayOfWeek(firstDayOfWeek_);
}
Exemple #3
0
std::size_t WTemplate::parseArgs(const std::string& text,
				 std::size_t pos,
				 std::vector<WString>& result)
{
  std::size_t Error = std::string::npos;

  if (pos == std::string::npos)
    return Error;

  enum { Next, Name, Value, SValue, DValue } state = Next;

  WStringStream v;

  for (; pos < text.length(); ++pos) {
    char c = text[pos];
    switch (state) {
    case Next:
      if (!std::isspace(c)) {
	if (c == '}')
	  return pos;
	else if (std::isalpha(c) || c == '_') {
	  state = Name;
	  v.clear();
	  v << c;
	} else if (c == '\'') {
	  state = SValue;
	  v.clear();
	} else if (c == '"') {
	  state = DValue;
	  v.clear();
	} else
	  return Error;
      }
      break;

    case Name:
      if (c == '=') {
	state = Value;
	v << '=';
      } else if (std::isspace(c)) {
	result.push_back(WString::fromUTF8(v.str()));
	state = Next;
      } else if (c == '}') {
	result.push_back(WString::fromUTF8(v.str()));
	return pos;
      } else if (std::isalnum(c) || c == '_' || c == '-')
	v << c;
      else
	return Error;
      break;

    case Value:
      if (c == '\'')
	state = SValue;
      else if (c == '"')
	state = DValue;
      else
	return Error;
      break;

    case SValue:
    case DValue:
      char quote = state == SValue ? '\'' : '"';

      std::size_t end = text.find(quote, pos);
      if (end == std::string::npos)
	return Error;
      if (text[end - 1] == '\\')
	v << text.substr(pos, end - pos - 1) << quote;
      else {
	v << text.substr(pos, end - pos);
	result.push_back(WString::fromUTF8(v.str()));
	state = Next;
      }

      pos = end;
    }
  }

  return pos == text.length() ? std::string::npos : pos;
}
Exemple #4
0
void WPainter::drawText(const WRectF& rectangle,
                        WFlags<AlignmentFlag> alignmentFlags,
                        TextFlag textFlag,
                        const WString& text)
{
    if (textFlag == TextSingleLine)
        drawText(rectangle, alignmentFlags, text);
    else {
        if (!(alignmentFlags & AlignVerticalMask))
            alignmentFlags |= AlignTop;
        if (!(alignmentFlags & AlignHorizontalMask))
            alignmentFlags |= AlignLeft;

        if (device_->features() & WPaintDevice::CanWordWrap)
            device_->drawText(rectangle.normalized(), alignmentFlags, textFlag, text);
        else if (device_->features() & WPaintDevice::HasFontMetrics) {
#ifndef WT_TARGET_JAVA
            MultiLineTextRenderer renderer(*this, rectangle);

            AlignmentFlag horizontalAlign = alignmentFlags & AlignHorizontalMask;
            AlignmentFlag verticalAlign = alignmentFlags & AlignVerticalMask;

            /*
             * Oh irony: after all these years of hating CSS, we now
             * implemented an XHTML renderer for which we need to use the
             * same silly workarounds to render the text with all possible
             * alignment options
             */
            WStringStream s;
            s << "<table style=\"width:" << (int)rectangle.width() << "px;\""
              "cellspacing=\"0\"><tr>"
              "<td style=\"padding:0px;height:" << (int)rectangle.height() <<
              "px;color:" << pen().color().cssText()
              << ";text-align:";

            switch (horizontalAlign) {
            case AlignLeft:
                s << "left";
                break;
            case AlignRight:
                s << "right";
                break;
            case AlignCenter:
                s << "center";
                break;
            default:
                break;
            }

            s << ";vertical-align:";

            switch (verticalAlign) {
            case AlignTop:
                s << "top";
                break;
            case AlignBottom:
                s << "bottom";
                break;
            case AlignMiddle:
                s << "middle";
                break;
            default:
                break;
            }

            s << ";" << font().cssText(false);

            s << "\">"
              << WWebWidget::escapeText(text, true).toUTF8()
              << "</td></tr></table>";

            save();

            /*
             * FIXME: what if there was already a clip path? We need to combine
             * them ...
             */
            WPainterPath p;
            p.addRect(rectangle.x() + 1, rectangle.y() + 1, rectangle.width() - 2, rectangle.height() - 2);
            setClipPath(p);
            setClipping(true);
            renderer.render(WString::fromUTF8(s.str()));
            restore();
#endif // WT_TARGET_JAVA
        } else
            throw WException("WPainter::drawText(): device does not support "
                             "TextWordWrap or FontMetrics");
    }
}
Exemple #5
0
/*
 * 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;
}
Exemple #6
0
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);
      }
    }
  }
}
Exemple #7
0
DomElement *FlexLayoutImpl::createElement(Orientation orientation,
					  unsigned index,
					  int totalStretch,
					  WApplication *app)
{
  Impl::Grid::Item& it = item(orientation, index);
  Impl::Grid::Section& s = section(orientation, index);

  DomElement *el
    = getImpl(it.item_.get())->createDomElement(nullptr, true, true, app);
  if (dynamic_cast<StdGridLayoutImpl2*>(getImpl(it.item_.get()))) {
    DomElement *wrapEl = DomElement::createNew(DomElementType::DIV);
    wrapEl->addChild(el);
    el = wrapEl;
  }

  int m[] = { 0, 0, 0, 0 };
  if (FlexLayoutImpl *flexImpl = dynamic_cast<FlexLayoutImpl*>(getImpl(it.item_.get()))) {
    Orientation elOrientation = flexImpl->getOrientation();
    if (elOrientation == Orientation::Horizontal) {
      m[3] -= (flexImpl->grid_.horizontalSpacing_) / 2;
      m[1] -= (flexImpl->grid_.horizontalSpacing_ + 1) / 2;
    } else {
      m[0] -= (flexImpl->grid_.verticalSpacing_) / 2;
      m[2] -= (flexImpl->grid_.horizontalSpacing_ + 1) / 2;
    }
  }

  AlignmentFlag hAlign = it.alignment_ & AlignHorizontalMask;
  AlignmentFlag vAlign = it.alignment_ & AlignVerticalMask;

  /*
   * If not justifying along main axis, then we need to wrap inside
   * an additional (flex) element
   */
  if (orientation == Orientation::Horizontal) {
    if (hAlign != static_cast<AlignmentFlag>(0)) {
      el->setProperty(Property::StyleFlex, "0 0 auto");

      DomElement *wrap = DomElement::createNew(DomElementType::DIV);
      wrap->setId("w" + el->id());
      wrap->setProperty(Property::StyleDisplay, styleDisplay());
      wrap->setProperty(Property::StyleFlexFlow, styleFlex());
      wrap->addChild(el);
      el = wrap;

      switch (hAlign) {
      case AlignmentFlag::Left:
	el->setProperty(Property::StyleJustifyContent, "flex-start");
	break;
      case AlignmentFlag::Center:
	el->setProperty(Property::StyleJustifyContent, "center");
	break;
      case AlignmentFlag::Right:
	el->setProperty(Property::StyleJustifyContent, "flex-end");
      default:
	break;
      }
    }

    if (vAlign != static_cast<AlignmentFlag>(0))
      switch (vAlign) {
      case AlignmentFlag::Top:
	el->setProperty(Property::StyleAlignSelf, "flex-start");
	break;
      case AlignmentFlag::Middle:
	el->setProperty(Property::StyleAlignSelf, "center");
	break;
      case AlignmentFlag::Bottom:
	el->setProperty(Property::StyleAlignSelf, "flex-end");
	break;
      case AlignmentFlag::Baseline:
	el->setProperty(Property::StyleAlignSelf, "baseline");
      default:
	break;
      }
  } else {
    if (vAlign != static_cast<AlignmentFlag>(0)) {
      el->setProperty(Property::StyleFlex, "0 0 auto");

      DomElement *wrap = DomElement::createNew(DomElementType::DIV);
      wrap->setId("w" + el->id());
      wrap->setProperty(Property::StyleDisplay, styleDisplay());
      wrap->setProperty(Property::StyleFlexFlow, styleFlex());
      wrap->addChild(el);
      el = wrap;

      switch (vAlign) {
      case AlignmentFlag::Top:
	el->setProperty(Property::StyleJustifyContent, "flex-start");
	break;
      case AlignmentFlag::Middle:
	el->setProperty(Property::StyleJustifyContent, "center");
	break;
      case AlignmentFlag::Bottom:
	el->setProperty(Property::StyleJustifyContent, "flex-end");
      default:
	break;
      }
    }

    if (hAlign != static_cast<AlignmentFlag>(0)) 
      switch (hAlign) {
      case AlignmentFlag::Left:
	el->setProperty(Property::StyleAlignSelf, "flex-start");
	break;
      case AlignmentFlag::Center:
	el->setProperty(Property::StyleAlignSelf, "center");
	break;
      case AlignmentFlag::Right:
	el->setProperty(Property::StyleAlignSelf, "flex-end");
	break;
      default:
	break;
      }
  }
      
  {
    WStringStream flexProperty;
    int flexGrow = totalStretch == 0 ? 1 : s.stretch_;
    int flexShrink = totalStretch == 0 ? 1 : (s.stretch_ == 0 ? 0 : 1);
    flexProperty << flexGrow << ' ' << flexShrink << ' ' << s.initialSize_.cssText();
    if (s.stretch_ == 0)
      el->setAttribute("flg", "0");
    el->setProperty(Property::StyleFlex, flexProperty.str());
  }

  switch (getDirection()) {
  case LayoutDirection::LeftToRight:
    m[3] += (grid_.horizontalSpacing_ + 1) / 2;
    m[1] += (grid_.horizontalSpacing_) / 2;
    break;

  case LayoutDirection::RightToLeft:
    m[1] += (grid_.horizontalSpacing_ + 1) / 2;
    m[3] += (grid_.horizontalSpacing_) / 2;
    break;

  case LayoutDirection::TopToBottom:
    m[0] += (grid_.horizontalSpacing_ + 1) / 2;
    m[2] += (grid_.horizontalSpacing_) / 2;
    break;

  case LayoutDirection::BottomToTop:
    m[2] += (grid_.horizontalSpacing_ + 1) / 2;
    m[0] += (grid_.horizontalSpacing_) / 2;
    break;
  }

  if (m[0] != 0 || m[1] != 0 || m[2] != 0 || m[3] != 0) {
    WStringStream marginProperty;
    marginProperty << m[0] << "px " << m[1] << "px "
		   << m[2] << "px " << m[3] << "px";
    el->setProperty(Property::StyleMargin, marginProperty.str());
  }

  return el;
}
Exemple #8
0
DomElement *FlexLayoutImpl::createDomElement(DomElement *parent,
					     bool fitWidth, bool fitHeight,
					     WApplication *app)
{
  addedItems_.clear();
  removedItems_.clear();

  int margin[] = { 0, 0, 0, 0 };

  DomElement *result;

  if (layout()->parentLayout() == nullptr) {
    /*
     * If it is a top-level layout (as opposed to a nested layout),
     * configure overflow of the container.
     */
    if (container() == app->root()) {
      /*
       * Reset body,html default paddings and so on if we are doing layout
       * in the entire document.
       */
      app->setBodyClass(app->bodyClass() + " Wt-layout");
      app->setHtmlClass(app->htmlClass() + " Wt-layout");

      parent->setProperty(Property::StyleBoxSizing, "border-box");
    }

#ifndef WT_TARGET_JAVA
    layout()->getContentsMargins(margin + 3, margin, margin + 1, margin + 2);
#else // WT_TARGET_JAVA
    margin[3] = layout()->getContentsMargin(Side::Left);
    margin[0] = layout()->getContentsMargin(Side::Top);
    margin[1] = layout()->getContentsMargin(Side::Right);
    margin[2] = layout()->getContentsMargin(Side::Bottom);
#endif // WT_TARGET_JAVA

    Orientation orientation = getOrientation();

    if (orientation == Orientation::Horizontal) {
      margin[3] = std::max(0, margin[3] - (grid_.horizontalSpacing_) / 2);
      margin[1] = std::max(0, margin[1] - (grid_.horizontalSpacing_ + 1) / 2);
    } else {
      margin[0] = std::max(0, margin[0] - (grid_.verticalSpacing_) / 2);
      margin[2] = std::max(0, margin[2] - (grid_.horizontalSpacing_ + 1) / 2);
    }

    ResizeSensor::applyIfNeeded(container());
    container()->setFlexBox(true);

    result = parent;
    elId_ = container()->id();
  } else {
    result = DomElement::createNew(DomElementType::DIV);
    elId_ = id();
    result->setId(elId_);
  }

  if (margin[0] != 0 || margin[1] != 0 || margin[2] != 0 || margin[3] != 0) {
    WStringStream paddingProperty;
    paddingProperty << margin[0] << "px " << margin[1] << "px "
		    << margin[2] << "px " << margin[3] << "px";
    result->setProperty(Property::StylePadding, paddingProperty.str());
  }

  // FIXME minsize/maxsize

  result->setProperty(Property::StyleDisplay, styleDisplay());
  result->setProperty(Property::StyleFlexFlow, styleFlex());

  Orientation orientation = getOrientation();

  int c = count(orientation);

  int totalStretch = getTotalStretch(orientation);

  for (int i = 0; i < c; ++i) {
    DomElement *el = createElement(orientation, i, totalStretch, app);
    result->addChild(el);
  }

  WStringStream js;
  js << "layout=new " WT_CLASS ".FlexLayout("
     << app->javaScriptClass() << ",'" << elId_ << "');";
  result->callMethod(js.str());

  return result;
}
Exemple #9
0
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);
}
Exemple #10
0
void WMediaPlayer::render(WFlags<RenderFlag> flags)
{
  // XXX subtitles, chapters, stream ?
  static const char *mediaNames[] = {
    "poster",
    "mp3", "m4a", "oga", "wav", "webma", "fla",
    "m4v", "ogv", "webmv", "flv"
  };

  WApplication *app = WApplication::instance();

  if (mediaUpdated_) {
    WStringStream ss;

    ss << '{';

    bool first = true;
    for (unsigned i = 0; i < media_.size(); ++i) {
      if (media_[i].link.isNull())
	continue;

      if (!first)
	ss << ',';

      std::string url = app->resolveRelativeUrl(media_[i].link.url());

      ss << const_cast<char *>(mediaNames[media_[i].encoding]) << ": "
	 << WWebWidget::jsStringLiteral(url);

      first = false;
    }

    ss << '}';

    if (!(flags & RenderFull))
      playerDo("setMedia", ss.str());
    else {
      initialJs_ = ".jPlayer('setMedia', " + ss.str() + ')' + initialJs_;
    }

    mediaUpdated_ = false;
  }

  if (flags & RenderFull) {
    if (gui_ == this)
      createDefaultGui();

    WStringStream ss;

    ss << jsPlayerRef() << ".jPlayer({"
       << "ready: function () {";

    if (!initialJs_.empty())
      ss << "$(this)" << initialJs_ << ';';

    initialJs_.clear();

    ss << "},"
       << "swfPath: \"" << WApplication::resourcesUrl() << "jPlayer\","
       << "supplied: \"";

    bool first = true;
    for (unsigned i = 0; i < media_.size(); ++i) {
      if (media_[i].encoding != PosterImage) {
	if (!first)
	  ss << ',';
	ss << const_cast<char *>(mediaNames[media_[i].encoding]);
	first = false;
      }
    }

    ss << "\",";

    if (mediaType_ == Video) {
      ss << "size: {"
	 <<   "width: \"" << videoWidth_ << "px\","
	 <<   "height: \"" << videoHeight_ << "px\","
	 <<   "cssClass: \"jp-video-" << videoHeight_ << "p\""
	 << "},";
    }

    ss << "cssSelectorAncestor: " << (gui_ ? "'#" + id() + '\'' : "''")
       << ", cssSelector: {";

    const char *controlSelectors[] = 
      { "videoPlay", "play", "pause", "stop", "volumeMute", "volumeUnmute",
	"volumeMax",
	"fullScreen", "restoreScreen", "repeat", "repeatOff" };

    first = true;
    for (unsigned i = VideoPlay; i < RepeatOff; ++i) {
      if (control_[i]) {
	if (!first)
	  ss << ", ";

	ss << const_cast<char *>(controlSelectors[i]) << ":\"#" 
	   << control_[i]->id() << "\"";

	first = false;
      }
    }

    const char *displaySelectors[] = 
      { "currentTime", "duration" };

    for (unsigned i = CurrentTime; i < Duration; ++i) {
      if (control_[i]) {
	if (!first)
	  ss << ", ";

	ss << const_cast<char *>(displaySelectors[i]) << ":\"#"
	   << display_[i]->id() << "\"";

	first = false;
      }
    }

    if (progressBar_[Time]) {
      if (!first)
	ss << ", ";

      ss << "seekBar:\"#" << progressBar_[Time]->id() << "\", "
	 << "playBar:\"#bar" << progressBar_[Time]->id() << "\"";

      first = false;
    }

    if (progressBar_[Volume]) {
      if (!first)
	ss << ", ";

      ss << "volumeBar:\"#" << progressBar_[Volume]->id() << "\", "
	 << "volumeBarValue:\"#bar" << progressBar_[Volume]->id() << "\"";

      first = false;
    }

    ss << '}'
       << "});";

    ss << "new " WT_CLASS ".WMediaPlayer("
       << app->javaScriptClass() << ',' << jsRef() << ");";

    doJavaScript(ss.str());

    boundSignals_ = 0;
  }

  if (boundSignals_ < signals_.size()) {
    WStringStream ss;
    ss << jsPlayerRef();
    for (unsigned i = boundSignals_; i < signals_.size(); ++i)
      ss << ".bind('" << signals_[i]->name() << "', function(o, e) { "
	 << signals_[i]->createCall() << "})";
    ss << ';';

    doJavaScript(ss.str());
    boundSignals_ = signals_.size();
  }

  WCompositeWidget::render(flags);
}
Exemple #11
0
void PaintedSlider::updateState()
{
  bool rtl = WApplication::instance()->layoutDirection() ==
    LayoutDirection::RightToLeft;

  Orientation o = slider_->orientation();

  if (o == Orientation::Horizontal) {
    handle_->resize(slider_->handleWidth(), h());
    handle_->setOffsets(0, Side::Top);
  } else {
    handle_->resize(w(), slider_->handleWidth());
    handle_->setOffsets(0, Side::Left);
  }

  double l = o == Orientation::Horizontal ? w() : h();
  double pixelsPerUnit = (l - slider_->handleWidth()) / range();

  std::string dir;
  std::string size;
  if (o == Orientation::Horizontal) {
    dir = rtl ? "right" : "left";
    size = "width";
  } else {
    dir = "top";
    size = "height";
  }

  char u = (o == Orientation::Horizontal ? 'x' : 'y');

  double max = l - slider_->handleWidth();
  bool horizontal = o == Orientation::Horizontal;

  char buf[30]; // Buffer for round_js_str

  /*
   * Note: cancelling the mouseDown event prevents the selection behaviour
   */
  WStringStream mouseDownJS;
  mouseDownJS << "obj.setAttribute('down', " WT_CLASS
	      <<                     ".widgetCoordinates(obj, event)." << u
	      <<                  ");"
	      << WT_CLASS ".cancelEvent(event);";

  WStringStream computeD; // = 'u' position relative to background, corrected for slider
  computeD << "var objh = " << handle_->jsRef() << ","
	   <<     "objf = " << fill_->jsRef() << ","
	   <<     "objb = " << slider_->jsRef() << ","
	   <<     "page_u = WT.pageCoordinates(event)." << u << ","
	   <<     "widget_page_u = WT.widgetPageCoordinates(objb)." << u << ","
	   <<     "pos = page_u - widget_page_u,"
	   <<     "rtl = " << rtl << ","
	   <<     "horizontal = " << horizontal << ";"
	   <<     "if (rtl && horizontal)";
  computeD <<       "pos = " << Utils::round_js_str(l, 3, buf) << " - pos;";
  computeD <<     "var d = pos - down;";
  
  WStringStream mouseMovedJS;
  mouseMovedJS << "var down = obj.getAttribute('down');"
	       << "var WT = " WT_CLASS ";"
	       << "if (down != null && down != '') {"
	       <<    computeD.str();
  mouseMovedJS <<   "d = Math.max(0, Math.min(d, " << Utils::round_js_str(max, 3, buf) << "));";
  mouseMovedJS <<   "var v = Math.round(d/" << Utils::round_js_str(pixelsPerUnit, 3, buf) << ");";
  mouseMovedJS <<   "var intd = v*" << Utils::round_js_str(pixelsPerUnit, 3, buf) << ";";
  mouseMovedJS <<   "if (Math.abs(WT.pxself(objh, '" << dir
	       <<                 "') - intd) > 1) {"
	       <<     "objf.style." << size << " = ";
  if (o == Orientation::Vertical) {
    mouseMovedJS << '(' << Utils::round_js_str(max, 3, buf);
    mouseMovedJS << " - intd + " << (slider_->handleWidth() / 2)
		 << ")";
  } else
    mouseMovedJS << "intd + " << (slider_->handleWidth() / 2);
  mouseMovedJS <<       " + 'px';" 
	       <<     "objh.style." << dir << " = intd + 'px';"
	       <<     "var vs = ";
  if (o == Orientation::Horizontal)
    mouseMovedJS << "v + " << slider_->minimum();
  else
    mouseMovedJS << slider_->maximum() << " - v";
  mouseMovedJS <<     ";"
	       <<     "var f = objb.onValueChange;"
	       <<     "if (f) f(vs);";

  if (slider_->sliderMoved().needsUpdate(true)) {
#ifndef WT_TARGET_JAVA
    mouseMovedJS << slider_->sliderMoved().createCall({"vs"});
#else
    mouseMovedJS << slider_->sliderMoved().createCall("vs");
#endif
  }

  mouseMovedJS <<   "}"
	       << "}";

  WStringStream mouseUpJS;
  mouseUpJS << "var down = obj.getAttribute('down');"
	    << "var WT = " WT_CLASS ";"
	    << "if (down != null && down != '') {"
	    <<    computeD.str()
	    <<   "d += " << (slider_->handleWidth() / 2) << ";"
#ifndef WT_TARGET_JAVA
	    <<    sliderReleased_.createCall({"Math.round(d)"})
#else
	    <<    sliderReleased_.createCall("Math.round(d)")
#endif
	    <<   "obj.removeAttribute('down');"
	    << "}";

  bool enabled = !slider_->isDisabled();
  
  mouseDownJS_.setJavaScript(std::string("function(obj, event) {") 
			     + (enabled ? mouseDownJS.str() : "") 
			     + "}");
  mouseMovedJS_.setJavaScript(std::string("function(obj, event) {") 
			      + (enabled ? mouseMovedJS.str() : "") 
			      + "}");
  mouseUpJS_.setJavaScript(std::string("function(obj, event) {") 
			   + (enabled ? mouseUpJS.str() : "") 
			   + "}");
  handleClickedJS_.setJavaScript(std::string("function(obj, event) {")
			     + WT_CLASS + ".cancelEvent(event,"
			     + WT_CLASS + ".CancelPropagate); }");

  update();
  updateSliderPosition();
}
Exemple #12
0
WT_BOSTREAM& Response::out()
{
  if (!headersCommitted_) {
    if (response_ &&
	!continuation_ &&
	(resource_->dispositionType() != ContentDisposition::None
	 || !resource_->suggestedFileName().empty())) {
      WStringStream cdp;

      switch (resource_->dispositionType()) {
      default:
      case ContentDisposition::Inline:
        cdp << "inline";
        break;
      case ContentDisposition::Attachment:
        cdp << "attachment";
        break;
      }

      const WString& fileName = resource_->suggestedFileName();

      if (!fileName.empty()) {
	if (resource_->dispositionType() == ContentDisposition::None) {
	  // backward compatibility-ish with older Wt versions
	  cdp.clear();
	  cdp << "attachment";
	}

	// Browser incompatibility hell: internatianalized filename suggestions
	// First filename is for browsers that don't support RFC 5987
	// Second filename is for browsers that do support RFC 5987
	cdp << ';';

	// We cannot query wApp here, because wApp doesn't exist for
	// static resources.
	const char *ua = response_->userAgent();
	bool isIE = ua && strstr(ua, "MSIE") != nullptr;
	bool isChrome = ua && strstr(ua, "Chrome") != nullptr;

	if (isIE || isChrome) {
	  // filename="foo-%c3%a4-%e2%82%ac.html"
	  // Note: IE never converts %20 back to space, so avoid escaping
	  // IE wil also not url decode the filename if the file has no ASCII
	  // extension (e.g. .txt)
	  cdp << "filename=\""
	      << Utils::urlEncode(fileName.toUTF8(), " ")
	      << "\";";
	} else {
	  // Binary UTF-8 sequence: for FF3, Safari, Chrome, Chrome9
	  cdp << "filename=\"" << fileName.toUTF8() << "\";";
	}
	// Next will be picked by RFC 5987 in favour of the
	// one without specified encoding (Chrome9, 
	cdp << Utils::EncodeHttpHeaderField("filename", fileName);
	addHeader("Content-Disposition", cdp.str());
      } else {
	addHeader("Content-Disposition", cdp.str());
      }
    }

    headersCommitted_ = true;
  }

  if (out_)
    return *out_;
  else
    return response_->out();
}
Exemple #13
0
	WString toWString(const Color& val)
	{
		WStringStream stream;
		stream << val.r << L" " << val.g << L" " << val.b << L" " << val.a;
		return stream.str();
	}
Exemple #14
0
	WString toWString(const Quaternion& val)
	{
		WStringStream stream;
		stream  << val.w << L" " << val.x << L" " << val.y << L" " << val.z;
		return stream.str();
	}
Exemple #15
0
	WString toWString(const Vector4& val)
	{
		WStringStream stream;
		stream << val.x << L" " << val.y << L" " << val.z << L" " << val.w;
		return stream.str();
	}
Exemple #16
0
	WString toWString(const Vector2I& val)
	{
		WStringStream stream;
		stream << val.x << L" " << val.y;
		return stream.str();
	}