Example #1
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;
}
Example #2
0
void WWebWidget::updateDom(DomElement& element, bool all)
{
  /*
   * determine display
   */
  if (hiddenChanged_ || geometryChanged_ || all) {
    if (!hidden_) {
      if (element.isDefaultInline() != inline_) {
	if (inline_) {
	  if (element.type() == DomElement::TABLE)
	    element.setProperty(PropertyStyleDisplay, "inline-table");
	  else if (element.type() != DomElement::TD)
	    element.setProperty(PropertyStyleDisplay, "inline-block");
	} else {
	  element.setProperty(PropertyStyleDisplay, "block");
	}
      } else if (hiddenChanged_) {
	element.setProperty(PropertyStyleDisplay,
			    inline_ ? "inline" : "block");
      }
    } else
      element.setProperty(PropertyStyleDisplay, "none");

    hiddenChanged_ = false;
  }

  if (geometryChanged_ || all) {
    /*
     * set position
     */
    switch (positionScheme_) {
    case Static:
      break;
    case Relative:
      element.setProperty(PropertyStylePosition, "relative"); break;
    case Absolute:
      element.setProperty(PropertyStylePosition, "absolute"); break;
    case Fixed:
      element.setProperty(PropertyStylePosition, "fixed"); break;
    }

    /*
     * set z-index
     */
    if (popup_)
      element.setProperty(PropertyStyleZIndex,
			  boost::lexical_cast<std::string>(zIndex()));

    /*
     * set float
     */
    switch (floatSide_) {
    case None:
      break;
    case Left:
      element.setProperty(PropertyStyleFloat, "left"); break;
      break;
    case Right:
      element.setProperty(PropertyStyleFloat, "right"); break;
      break;
    default:
      /* illegal values */
      ;
    }

    /*
     * set clear: FIXME: multiple values
     */
    switch (clearSides_) {
    case None:
      break;
    case Left:
      element.setProperty(PropertyStyleClear, "left"); break;
      break;
    case Right:
      element.setProperty(PropertyStyleClear, "right"); break;
      break;
    case Verticals:
      element.setProperty(PropertyStyleClear, "both"); break;
      break;
    default:
      /* illegal values */
      ;
    }

    /*
     * set width & height
     */
    if (!width_.isAuto())
      element.setProperty(PropertyStyleWidth, width_.cssText());
    if (!height_.isAuto())
      element.setProperty(PropertyStyleHeight, height_.cssText());
    if (!minimumWidth_.isAuto() && (minimumWidth_.value() != 0))
      element.setProperty(PropertyStyleMinWidth, minimumWidth_.cssText());
    if (!minimumHeight_.isAuto() && (minimumHeight_.value() != 0))
      element.setProperty(PropertyStyleMinHeight, minimumHeight_.cssText());
    if (!maximumWidth_.isAuto()) // == none
      element.setProperty(PropertyStyleMaxWidth, maximumWidth_.cssText());
    if (!maximumHeight_.isAuto()) // == none
      element.setProperty(PropertyStyleMaxHeight, maximumHeight_.cssText());

    /*
     * set offsets
     */
    if (positionScheme_ != Static) {
      static const Property properties[] = { PropertyStyleTop,
					     PropertyStyleRight,
					     PropertyStyleBottom,
					     PropertyStyleLeft };

      for (unsigned i = 0; i < 4; ++i) {
	if (!offsets_[i].isAuto())
	  element.setProperty(properties[i], offsets_[i].cssText());
      }
    }

    /*
     * set vertical alignment
     */
    switch (verticalAlignment_) {
    case AlignBaseline:
      break;
    case AlignSub:
      element.setProperty(PropertyStyleVerticalAlign, "sub"); break;
    case AlignSuper:
      element.setProperty(PropertyStyleVerticalAlign, "super"); break;
    case AlignTop:
      element.setProperty(PropertyStyleVerticalAlign, "top"); break;
    case AlignTextTop:
      element.setProperty(PropertyStyleVerticalAlign, "text-top"); break;
    case AlignMiddle:
      element.setProperty(PropertyStyleVerticalAlign, "middle"); break;
    case AlignBottom:
      element.setProperty(PropertyStyleVerticalAlign, "bottom"); break;
    case AlignTextBottom:
      element.setProperty(PropertyStyleVerticalAlign, "text-bottom"); break;
    case AlignLength:
      element.setProperty(PropertyStyleVerticalAlign,
			  verticalAlignmentLength_.cssText()); break;
    }

    geometryChanged_ = false;
  }

  if (marginsChanged_ || all) {
    if (marginsChanged_ || (margin_[0].value() != 0))
      element.setProperty(PropertyStyleMarginTop, margin_[0].cssText());
    if (marginsChanged_ || (margin_[1].value() != 0))
      element.setProperty(PropertyStyleMarginRight, margin_[1].cssText());
    if (marginsChanged_ || (margin_[2].value() != 0))
      element.setProperty(PropertyStyleMarginBottom, margin_[2].cssText());
    if (marginsChanged_ || (margin_[3].value() != 0))
      element.setProperty(PropertyStyleMarginLeft, margin_[3].cssText());

    marginsChanged_ = false;
  }

  if (toolTipChanged_ || all) {
    if ((toolTip_.length() > 0) || toolTipChanged_)
      element.setAttribute("title", toolTip_);

    toolTipChanged_ = false;
  }

  if (styleClass_.length() == 0) {
    decorationStyle_.updateDomElement(element, all);
  } else {
    if (styleClassChanged_ || all) {
      element.setAttribute("class", styleClass_);
      styleClassChanged_ = false;
    }
  }

  renderOk();

  for (unsigned i = 0; i < childRemoveChanges_.size(); ++i)
    delete childRemoveChanges_[i];

  childRemoveChanges_.clear();
}