bool StylePropertySet::propertyMatches(const PropertyReference& property) const { int foundPropertyIndex = findPropertyIndex(property.id()); if (foundPropertyIndex == -1) return false; return propertyAt(foundPropertyIndex).value()->cssText() == property.value()->cssText(); }
void MutableStylePropertySet::mergeAndOverrideOnConflict(const StylePropertySet* other) { unsigned size = other->propertyCount(); for (unsigned n = 0; n < size; ++n) { PropertyReference toMerge = other->propertyAt(n); CSSProperty* old = findCSSPropertyWithID(toMerge.id()); if (old) setProperty(toMerge.toCSSProperty(), old); else appendPrefixingVariantProperty(toMerge.toCSSProperty()); } }
void StylePropertySet::mergeAndOverrideOnConflict(const StylePropertySet* other) { ASSERT(isMutable()); unsigned size = other->propertyCount(); for (unsigned n = 0; n < size; ++n) { PropertyReference toMerge = other->propertyAt(n); CSSProperty* old = findMutableCSSPropertyWithID(toMerge.id()); if (old) setProperty(toMerge.toCSSProperty(), old); else mutablePropertyVector().append(toMerge.toCSSProperty()); } }
void MutableStylePropertySet::removeEquivalentProperties(const CSSStyleDeclaration* style) { Vector<CSSPropertyID> propertiesToRemove; unsigned size = m_propertyVector.size(); for (unsigned i = 0; i < size; ++i) { PropertyReference property = propertyAt(i); if (style->cssPropertyMatches(property.id(), property.value())) propertiesToRemove.append(property.id()); } // FIXME: This should use mass removal. for (unsigned i = 0; i < propertiesToRemove.size(); ++i) removeProperty(propertiesToRemove[i]); }
void MutableStylePropertySet::mergeAndOverrideOnConflict(const StylePropertySet* other) { unsigned size = other->propertyCount(); for (unsigned n = 0; n < size; ++n) { PropertyReference toMerge = other->propertyAt(n); // TODO(leviw): This probably doesn't work correctly with Custom Properties CSSProperty* old = findCSSPropertyWithID(toMerge.id()); if (old) setProperty(toMerge.toCSSProperty(), old); else m_propertyVector.append(toMerge.toCSSProperty()); } }
void StylePropertySet::removeEquivalentProperties(const StylePropertySet* style) { ASSERT(isMutable()); Vector<CSSPropertyID> propertiesToRemove; unsigned size = mutablePropertyVector().size(); for (unsigned i = 0; i < size; ++i) { PropertyReference property = propertyAt(i); if (style->propertyMatches(property.id(), property.value())) propertiesToRemove.append(property.id()); } // FIXME: This should use mass removal. for (unsigned i = 0; i < propertiesToRemove.size(); ++i) removeProperty(propertiesToRemove[i]); }
String StylePropertySet::fontValue() const { int fontSizePropertyIndex = findPropertyIndex(CSSPropertyFontSize); int fontFamilyPropertyIndex = findPropertyIndex(CSSPropertyFontFamily); if (fontSizePropertyIndex == -1 || fontFamilyPropertyIndex == -1) return emptyString(); PropertyReference fontSizeProperty = propertyAt(fontSizePropertyIndex); PropertyReference fontFamilyProperty = propertyAt(fontFamilyPropertyIndex); if (fontSizeProperty.isImplicit() || fontFamilyProperty.isImplicit()) return emptyString(); String commonValue = fontSizeProperty.value()->cssText(); StringBuilder result; appendFontLonghandValueIfExplicit(CSSPropertyFontStyle, result, commonValue); appendFontLonghandValueIfExplicit(CSSPropertyFontVariant, result, commonValue); appendFontLonghandValueIfExplicit(CSSPropertyFontWeight, result, commonValue); if (!result.isEmpty()) result.append(' '); result.append(fontSizeProperty.value()->cssText()); appendFontLonghandValueIfExplicit(CSSPropertyLineHeight, result, commonValue); if (!result.isEmpty()) result.append(' '); result.append(fontFamilyProperty.value()->cssText()); if (isInitialOrInherit(commonValue)) return commonValue; return result.toString(); }
void Edge::changedHandler(capputils::ObservableClass* object, int eventId) { // check for the right property ID if ((object != this && eventId == (int)outputId) || (object == this && eventId == positionId)) { PropertyReference* inputRef = getInputReference().get(); PropertyReference* outputRef = getOutputReference().get(); if (!inputRef || !outputRef) return; capputils::reflection::IClassProperty* inProp = inputRef->getProperty(); capputils::reflection::IClassProperty* outProp = outputRef->getProperty(); if (inProp && outProp) { IMergeAttribute* merge = inProp->getAttribute<IMergeAttribute>(); if (merge) { merge->setValue(*inputRef->getObject(), inProp, getInputPosition(), *outputRef->getObject(), outProp); } else { inProp->setValue(*inputRef->getObject(), *outputRef->getObject(), outProp); } } } }
String StylePropertySet::asText() const { StringBuilder result; int positionXPropertyIndex = -1; int positionYPropertyIndex = -1; int repeatXPropertyIndex = -1; int repeatYPropertyIndex = -1; BitArray<numCSSProperties> shorthandPropertyUsed; BitArray<numCSSProperties> shorthandPropertyAppeared; unsigned size = propertyCount(); unsigned numDecls = 0; for (unsigned n = 0; n < size; ++n) { PropertyReference property = propertyAt(n); CSSPropertyID propertyID = property.id(); CSSPropertyID shorthandPropertyID = CSSPropertyInvalid; CSSPropertyID borderFallbackShorthandProperty = CSSPropertyInvalid; String value; switch (propertyID) { #if ENABLE(CSS_VARIABLES) case CSSPropertyVariable: if (numDecls++) result.append(' '); result.append(property.cssText()); continue; #endif case CSSPropertyBackgroundPositionX: positionXPropertyIndex = n; continue; case CSSPropertyBackgroundPositionY: positionYPropertyIndex = n; continue; case CSSPropertyBackgroundRepeatX: repeatXPropertyIndex = n; continue; case CSSPropertyBackgroundRepeatY: repeatYPropertyIndex = n; continue; case CSSPropertyBorderTopWidth: case CSSPropertyBorderRightWidth: case CSSPropertyBorderBottomWidth: case CSSPropertyBorderLeftWidth: if (!borderFallbackShorthandProperty) borderFallbackShorthandProperty = CSSPropertyBorderWidth; case CSSPropertyBorderTopStyle: case CSSPropertyBorderRightStyle: case CSSPropertyBorderBottomStyle: case CSSPropertyBorderLeftStyle: if (!borderFallbackShorthandProperty) borderFallbackShorthandProperty = CSSPropertyBorderStyle; case CSSPropertyBorderTopColor: case CSSPropertyBorderRightColor: case CSSPropertyBorderBottomColor: case CSSPropertyBorderLeftColor: if (!borderFallbackShorthandProperty) borderFallbackShorthandProperty = CSSPropertyBorderColor; // FIXME: Deal with cases where only some of border-(top|right|bottom|left) are specified. if (!shorthandPropertyAppeared.get(CSSPropertyBorder - firstCSSProperty)) { value = borderPropertyValue(ReturnNullOnUncommonValues); if (value.isNull()) shorthandPropertyAppeared.set(CSSPropertyBorder - firstCSSProperty); else shorthandPropertyID = CSSPropertyBorder; } else if (shorthandPropertyUsed.get(CSSPropertyBorder - firstCSSProperty)) shorthandPropertyID = CSSPropertyBorder; if (!shorthandPropertyID) shorthandPropertyID = borderFallbackShorthandProperty; break; case CSSPropertyWebkitBorderHorizontalSpacing: case CSSPropertyWebkitBorderVerticalSpacing: shorthandPropertyID = CSSPropertyBorderSpacing; break; case CSSPropertyFontFamily: case CSSPropertyLineHeight: case CSSPropertyFontSize: case CSSPropertyFontStyle: case CSSPropertyFontVariant: case CSSPropertyFontWeight: // Don't use CSSPropertyFont because old UAs can't recognize them but are important for editing. break; case CSSPropertyListStyleType: case CSSPropertyListStylePosition: case CSSPropertyListStyleImage: shorthandPropertyID = CSSPropertyListStyle; break; case CSSPropertyMarginTop: case CSSPropertyMarginRight: case CSSPropertyMarginBottom: case CSSPropertyMarginLeft: shorthandPropertyID = CSSPropertyMargin; break; case CSSPropertyOutlineWidth: case CSSPropertyOutlineStyle: case CSSPropertyOutlineColor: shorthandPropertyID = CSSPropertyOutline; break; case CSSPropertyOverflowX: case CSSPropertyOverflowY: shorthandPropertyID = CSSPropertyOverflow; break; case CSSPropertyPaddingTop: case CSSPropertyPaddingRight: case CSSPropertyPaddingBottom: case CSSPropertyPaddingLeft: shorthandPropertyID = CSSPropertyPadding; break; case CSSPropertyWebkitAnimationName: case CSSPropertyWebkitAnimationDuration: case CSSPropertyWebkitAnimationTimingFunction: case CSSPropertyWebkitAnimationDelay: case CSSPropertyWebkitAnimationIterationCount: case CSSPropertyWebkitAnimationDirection: case CSSPropertyWebkitAnimationFillMode: shorthandPropertyID = CSSPropertyWebkitAnimation; break; case CSSPropertyWebkitFlexDirection: case CSSPropertyWebkitFlexWrap: shorthandPropertyID = CSSPropertyWebkitFlexFlow; break; case CSSPropertyWebkitFlexBasis: case CSSPropertyWebkitFlexGrow: case CSSPropertyWebkitFlexShrink: shorthandPropertyID = CSSPropertyWebkitFlex; break; case CSSPropertyWebkitMaskPositionX: case CSSPropertyWebkitMaskPositionY: case CSSPropertyWebkitMaskRepeatX: case CSSPropertyWebkitMaskRepeatY: case CSSPropertyWebkitMaskImage: case CSSPropertyWebkitMaskRepeat: case CSSPropertyWebkitMaskPosition: case CSSPropertyWebkitMaskClip: case CSSPropertyWebkitMaskOrigin: shorthandPropertyID = CSSPropertyWebkitMask; break; case CSSPropertyWebkitTransformOriginX: case CSSPropertyWebkitTransformOriginY: case CSSPropertyWebkitTransformOriginZ: shorthandPropertyID = CSSPropertyWebkitTransformOrigin; break; case CSSPropertyWebkitTransitionProperty: case CSSPropertyWebkitTransitionDuration: case CSSPropertyWebkitTransitionTimingFunction: case CSSPropertyWebkitTransitionDelay: shorthandPropertyID = CSSPropertyWebkitTransition; break; #if ENABLE(CSS_EXCLUSIONS) case CSSPropertyWebkitWrapFlow: case CSSPropertyWebkitShapeMargin: case CSSPropertyWebkitShapePadding: shorthandPropertyID = CSSPropertyWebkitWrap; break; #endif default: break; } unsigned shortPropertyIndex = shorthandPropertyID - firstCSSProperty; if (shorthandPropertyID) { if (shorthandPropertyUsed.get(shortPropertyIndex)) continue; if (!shorthandPropertyAppeared.get(shortPropertyIndex) && value.isNull()) value = getPropertyValue(shorthandPropertyID); shorthandPropertyAppeared.set(shortPropertyIndex); } if (!value.isNull()) { propertyID = shorthandPropertyID; shorthandPropertyUsed.set(shortPropertyIndex); } else value = property.value()->cssText(); if (value == "initial" && !CSSProperty::isInheritedProperty(propertyID)) continue; if (numDecls++) result.append(' '); result.append(getPropertyName(propertyID)); result.appendLiteral(": "); result.append(value); if (property.isImportant()) result.appendLiteral(" !important"); result.append(';'); } // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output. // It is required because background-position-x/y are non-standard properties and WebKit generated output // would not work in Firefox (<rdar://problem/5143183>) // It would be a better solution if background-position was CSS_PAIR. if (positionXPropertyIndex != -1 && positionYPropertyIndex != -1 && propertyAt(positionXPropertyIndex).isImportant() == propertyAt(positionYPropertyIndex).isImportant()) { PropertyReference positionXProperty = propertyAt(positionXPropertyIndex); PropertyReference positionYProperty = propertyAt(positionYPropertyIndex); if (numDecls++) result.append(' '); result.appendLiteral("background-position: "); if (positionXProperty.value()->isValueList() || positionYProperty.value()->isValueList()) result.append(getLayeredShorthandValue(backgroundPositionShorthand())); else { result.append(positionXProperty.value()->cssText()); result.append(' '); result.append(positionYProperty.value()->cssText()); } if (positionXProperty.isImportant()) result.appendLiteral(" !important"); result.append(';'); } else { if (positionXPropertyIndex != -1) { if (numDecls++) result.append(' '); result.append(propertyAt(positionXPropertyIndex).cssText()); } if (positionYPropertyIndex != -1) { if (numDecls++) result.append(' '); result.append(propertyAt(positionYPropertyIndex).cssText()); } } // FIXME: We need to do the same for background-repeat. if (repeatXPropertyIndex != -1 && repeatYPropertyIndex != -1 && propertyAt(repeatXPropertyIndex).isImportant() == propertyAt(repeatYPropertyIndex).isImportant()) { PropertyReference repeatXProperty = propertyAt(repeatXPropertyIndex); PropertyReference repeatYProperty = propertyAt(repeatYPropertyIndex); if (numDecls++) result.append(' '); result.appendLiteral("background-repeat: "); if (repeatXProperty.value()->isValueList() || repeatYProperty.value()->isValueList()) result.append(getLayeredShorthandValue(backgroundRepeatShorthand())); else { result.append(repeatXProperty.value()->cssText()); result.append(' '); result.append(repeatYProperty.value()->cssText()); } if (repeatXProperty.isImportant()) result.appendLiteral(" !important"); result.append(';'); } else { if (repeatXPropertyIndex != -1) { if (numDecls++) result.append(' '); result.append(propertyAt(repeatXPropertyIndex).cssText()); } if (repeatYPropertyIndex != -1) { if (numDecls++) result.append(' '); result.append(propertyAt(repeatYPropertyIndex).cssText()); } } ASSERT(!numDecls ^ !result.isEmpty()); return result.toString(); }
String StylePropertySet::get4Values(const StylePropertyShorthand& shorthand) const { // Assume the properties are in the usual order top, right, bottom, left. int topValueIndex = findPropertyIndex(shorthand.properties()[0]); int rightValueIndex = findPropertyIndex(shorthand.properties()[1]); int bottomValueIndex = findPropertyIndex(shorthand.properties()[2]); int leftValueIndex = findPropertyIndex(shorthand.properties()[3]); if (topValueIndex == -1 || rightValueIndex == -1 || bottomValueIndex == -1 || leftValueIndex == -1) return String(); PropertyReference top = propertyAt(topValueIndex); PropertyReference right = propertyAt(rightValueIndex); PropertyReference bottom = propertyAt(bottomValueIndex); PropertyReference left = propertyAt(leftValueIndex); // All 4 properties must be specified. if (!top.value() || !right.value() || !bottom.value() || !left.value()) return String(); if (top.isInherited() && right.isInherited() && bottom.isInherited() && left.isInherited()) return getValueName(CSSValueInherit); if (top.value()->isInitialValue() || right.value()->isInitialValue() || bottom.value()->isInitialValue() || left.value()->isInitialValue()) { if (top.value()->isInitialValue() && right.value()->isInitialValue() && bottom.value()->isInitialValue() && left.value()->isInitialValue() && !top.isImplicit()) { // All components are "initial" and "top" is not implicit. return getValueName(CSSValueInitial); } return String(); } if (top.isImportant() != right.isImportant() || right.isImportant() != bottom.isImportant() || bottom.isImportant() != left.isImportant()) return String(); bool showLeft = !right.value()->equals(*left.value()); bool showBottom = !top.value()->equals(*bottom.value()) || showLeft; bool showRight = !top.value()->equals(*right.value()) || showBottom; StringBuilder result; result.append(top.value()->cssText()); if (showRight) { result.append(' '); result.append(right.value()->cssText()); } if (showBottom) { result.append(' '); result.append(bottom.value()->cssText()); } if (showLeft) { result.append(' '); result.append(left.value()->cssText()); } return result.toString(); }
void ModelHarmonizer::itemChanged(QStandardItem* item) { if (!item) return; if (modelLocked) return; if (item->data(Qt::UserRole).canConvert<int>()) { int from = item->data(Qt::UserRole).value<int>(); int to = item->index().row(); // Delete new row if new row (new row if value does not have a property reference) if (!model->item(to, 1) || !model->item(to, 1)->data(Qt::UserRole).canConvert<PropertyReference>()) { model->removeRow(to, item->index().parent()); if (from != to) { // move rows to first valid position (count number of workflow module properties) // Update grid positions of all keys // Update workflow interface node order boost::shared_ptr<gapputils::workflow::Node> node = this->node.lock(); int firstInterfaceProperty = 0; for (int iRow = 0; iRow < model->rowCount(); ++iRow) { if (model->item(iRow, 1) && model->item(iRow, 1)->data(Qt::UserRole).canConvert<PropertyReference>()) { PropertyReference ref = model->item(iRow, 1)->data(Qt::UserRole).value<PropertyReference>(); if (ref.getObject() != node->getModule().get()) { firstInterfaceProperty = iRow; break; } } } to = std::max(to, firstInterfaceProperty); if (from < to) --to; model->insertRow(to, model->takeRow(from)); modelLocked = true; for (int gridPos = 0; gridPos < model->rowCount(); ++gridPos) model->item(gridPos, 0)->setData(QVariant::fromValue(gridPos), Qt::UserRole); modelLocked = false; gapputils::Workflow* workflow = dynamic_cast<gapputils::Workflow*>(node.get()); if (workflow) { workflow->moveInterfaceNode(from - firstInterfaceProperty, to - firstInterfaceProperty); } } return; } } // Update model if necessary if (item->data(Qt::UserRole).canConvert<PropertyReference>()) { const PropertyReference& reference = item->data(Qt::UserRole).value<PropertyReference>(); ReflectableClass* object = reference.getObject(); IClassProperty* prop = reference.getProperty(); QString qstr = item->text(); std::string str(qstr.toUtf8().data()); if (prop->getAttribute<FlagAttribute>()) { if ((prop->getStringValue(*object) != "0") != (item->checkState() == Qt::Checked)) { prop->setStringValue(*object, (item->checkState() == Qt::Checked ? "1" : "0")); } } else if (prop->getStringValue(*object).compare(str)) { IReflectableAttribute* reflectable = prop->getAttribute<IReflectableAttribute>(); if (reflectable) { ReflectableClass* subObject = reflectable->getValuePtr(*object, prop); if (dynamic_cast<AbstractEnumerator*>(subObject)) { stringstream stream(str); subObject->fromStream(stream); reflectable->setValuePtr(*object, prop, subObject); } } else { prop->setStringValue(*object, str); } } } }
void updateModel(QStandardItem* parentItem, const std::string& propertyPrefix = "") { // Go throw keys of parentItem for (int iRow = 0; iRow < parentItem->rowCount(); ++iRow) { QStandardItem* valueItem = parentItem->child(iRow, 1); if (valueItem && valueItem->data(Qt::UserRole).canConvert<PropertyReference>()) { PropertyReference ref = valueItem->data(Qt::UserRole).value<PropertyReference>(); IReflectableAttribute* reflectable = ref.getProperty()->getAttribute<IReflectableAttribute>(); if (reflectable) { ReflectableClass* subObject = reflectable->getValuePtr(*ref.getObject(), ref.getProperty()); // If the type of the reflectable object has changed, the subtree needs to be rebuild. // You need to know the previous type in order to detect a change. ScalarAttributes are // no longer supported in order to guarantee, that the string value is always set to the // previous type name. if (subObject) { std::string oldClassName(valueItem->text().toStdString()); if (oldClassName.compare(subObject->getClassName())) { valueItem->setText(subObject->getClassName().c_str()); buildModel(parentItem->child(iRow, 0), subObject, ref.getNode().get(), propertyPrefix + ref.getProperty()->getName() + "."); } else { updateModel(parentItem->child(iRow, 0), propertyPrefix + ref.getProperty()->getName() + "."); } } else { valueItem->setText(ref.getProperty()->getStringValue(*ref.getObject()).c_str()); } } else if (ref.getProperty()->getAttribute<FlagAttribute>()) { ClassProperty<bool>* boolProperty = dynamic_cast<ClassProperty<bool>* >(ref.getProperty()); // properties tagged as Flag() must be of type bool assert(boolProperty); if (boolProperty->getValue(*ref.getObject())) valueItem->setCheckState(Qt::Checked); else valueItem->setCheckState(Qt::Unchecked); } else{ valueItem->setText(ref.getProperty()->getStringValue(*ref.getObject()).c_str()); } } else { if (parentItem->child(iRow, 0)->hasChildren()) { updateModel(parentItem->child(iRow, 0), propertyPrefix); } } } }