blob: 55fe3c27701206cdf118bc004bbe6233970d60a8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.css.ui.internal.properties;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.wst.css.core.internal.metamodel.CSSMMCategory;
import org.eclipse.wst.css.core.internal.metamodel.CSSMMNode;
import org.eclipse.wst.css.core.internal.metamodel.CSSMetaModel;
import org.eclipse.wst.css.core.internal.metamodel.util.CSSMetaModelFinder;
import org.eclipse.wst.css.core.internal.metamodel.util.CSSMetaModelUtil;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSNodeList;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSStyleDeclItem;
import org.eclipse.wst.css.ui.internal.CSSUIMessages;
import org.w3c.dom.css.CSSStyleDeclaration;
/**
* A IPropertySource implementation for a JFace viewer used to display
* properties of CSS nodes.
*/
public class CSSPropertySource implements IPropertySource {
protected ICSSNode fNode = null;
// for performance...
final static Class ADAPTER_KEY = IPropertySource.class;
final boolean PERF_GETDESCRIPTORS = false;
private long time0;
public CSSPropertySource(ICSSNode target) {
super();
fNode = target;
}
protected IPropertyDescriptor createDefaultPropertyDescriptor(String attributeName) {
// the displayName MUST be set
IPropertyDescriptor descriptor = new CSSTextPropertyDescriptor(attributeName, attributeName, fNode);
// IPropertyDescriptor descriptor = new
// TextPropertyDescriptor(attributeName, attributeName);
return descriptor;
}
protected IPropertyDescriptor createPropertyDescriptor(CSSMMNode node, String category) {
return createPropertyDescriptor(node.getName(), category);
}
protected IPropertyDescriptor createPropertyDescriptor(String name, String category) {
IPropertyDescriptor descriptor = null;
if (name != null && 0 < name.length()) {
name = name.toLowerCase();
if (category == null) {
category = CSSUIMessages.INFO_Not_Categorized_1; //$NON-NLS-1$
}
descriptor = new CSSTextPropertyDescriptor(name, name, fNode, category);
// if (category == null) {
// descriptor = new CSSTextPropertyDescriptor(name, name, fNode);
// } else {
// descriptor = new CSSTextPropertyDescriptor(name, name, fNode,
// category);
// }
}
return descriptor;
}
/**
* Returns a value for this object that can be editted in a property
* sheet.
*
* @return a value that can be editted
*/
public Object getEditableValue() {
return null;
}
/**
* Returns the current collection of property descriptors.
*
* @return a vector containing all descriptors.
*/
public IPropertyDescriptor[] getPropertyDescriptors() {
time0 = System.currentTimeMillis();
CSSMetaModel metamodel = CSSMetaModelFinder.getInstance().findMetaModelFor(fNode);
Iterator iProperties = Collections.EMPTY_LIST.iterator();
switch (fNode.getNodeType()) {
case ICSSNode.STYLERULE_NODE :
case ICSSNode.FONTFACERULE_NODE :
case ICSSNode.PAGERULE_NODE :
case ICSSNode.STYLEDECLARATION_NODE :
CSSMMNode mmParent = new CSSMetaModelUtil(metamodel).getMetaModelNodeFor(fNode);
if (mmParent != null) {
iProperties = mmParent.getChildNodes();
}
break;
case ICSSNode.STYLEDECLITEM_NODE :
CSSMMNode mmNode = new CSSMetaModelUtil(metamodel).getMetaModelNodeFor(fNode);
if (mmNode != null) {
iProperties = Collections.singletonList(mmNode).iterator();
}
break;
default :
break;
}
// setup categories
Map categories = new HashMap();
Iterator iCategories = metamodel.getCategories();
while (iCategories.hasNext()) {
CSSMMCategory category = (CSSMMCategory) iCategories.next();
categories.put(category.getName(), category.getCaption());
}
// collect property names
Set declaredProperties = new HashSet();
if (iProperties.hasNext()) {
CSSStyleDeclaration declaration = getDeclarationNode();
if (declaration != null) {
ICSSNodeList nodeList = ((ICSSNode) declaration).getChildNodes();
int nProps = (nodeList != null) ? nodeList.getLength() : 0;
for (int i = 0; i < nProps; i++) {
ICSSNode node = nodeList.item(i);
if (node instanceof ICSSStyleDeclItem) {
String name = ((ICSSStyleDeclItem) node).getPropertyName();
if (name != null && 0 < name.length()) {
declaredProperties.add(name.toLowerCase());
}
}
}
}
}
List descriptors = new ArrayList();
// first: properties from content model
while (iProperties.hasNext()) {
CSSMMNode node = (CSSMMNode) iProperties.next();
if (node.getType() == CSSMMNode.TYPE_PROPERTY || node.getType() == CSSMMNode.TYPE_DESCRIPTOR) {
String category = (String) categories.get(node.getAttribute("category")); //$NON-NLS-1$
String name = node.getName().toLowerCase();
if (declaredProperties.contains(name)) {
declaredProperties.remove(name);
}
IPropertyDescriptor descriptor = createPropertyDescriptor(name, category);
if (descriptor != null) {
descriptors.add(descriptor);
}
}
}
// second: existing properties but not in content model
Iterator iRemains = declaredProperties.iterator();
while (iRemains.hasNext()) {
IPropertyDescriptor descriptor = createPropertyDescriptor((String) iRemains.next(), null);
if (descriptor != null) {
descriptors.add(descriptor);
}
}
IPropertyDescriptor[] resultArray = new IPropertyDescriptor[descriptors.size()];
if (PERF_GETDESCRIPTORS) {
System.out.println(getClass().getName() + ".getPropertyDescriptors: " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
}
return (IPropertyDescriptor[]) descriptors.toArray(resultArray);
}
/**
* Returns the current value for the named property.
*
* @param name
* the name of the property as named by its property descriptor
* @return the current value of the property
*/
public Object getPropertyValue(Object name) {
if (name == null) {
return ""; //$NON-NLS-1$
}
String valueString = null;
String nameString = name.toString();
CSSStyleDeclaration declaration = null;
switch (fNode.getNodeType()) {
case ICSSNode.STYLEDECLITEM_NODE :
valueString = ((ICSSStyleDeclItem) fNode).getCSSValueText();
break;
case ICSSNode.STYLERULE_NODE :
case ICSSNode.FONTFACERULE_NODE :
case ICSSNode.PAGERULE_NODE :
declaration = (CSSStyleDeclaration) fNode.getFirstChild();
if (declaration != null) {
valueString = declaration.getPropertyValue(nameString);
}
break;
case ICSSNode.STYLEDECLARATION_NODE :
valueString = ((CSSStyleDeclaration) fNode).getPropertyValue(nameString);
break;
case ICSSNode.PRIMITIVEVALUE_NODE :
ICSSNode parent = fNode;
while (parent != null && !(parent instanceof ICSSStyleDeclItem)) {
parent = parent.getParentNode();
}
if (parent != null) {
valueString = ((ICSSStyleDeclItem) parent).getCSSValueText();
}
break;
default :
break;
}
if (valueString == null) {
valueString = ""; //$NON-NLS-1$
}
return valueString;
}
/**
* Returns whether the property value has changed from the default.
*
* @return <code>true</code> if the value of the specified property has
* changed from its original default value; <code>false</code>
* otherwise.
*/
public boolean isPropertySet(Object property) {
if (property == null) {
return false;
}
CSSStyleDeclaration declaration = getDeclarationNode();
if (declaration != null) {
String value = declaration.getPropertyValue(property.toString());
if (value != null && 0 < value.length()) {
return true;
}
}
return false;
}
/**
* Resets the specified property's value to its default value.
*
* @param property
* the property to reset
*/
public void resetPropertyValue(Object str) {
if (str == null) {
return;
}
CSSStyleDeclaration declaration = getDeclarationNode();
if (declaration != null) {
declaration.removeProperty(str.toString());
}
}
/**
* Sets the named property to the given value.
*
* @param name
* the name of the property being set
* @param value
* the new value for the property
*/
public void setPropertyValue(Object name, Object value) {
if (name == null) {
return;
}
String valueString = (value != null) ? value.toString() : null;
String nameString = name.toString();
CSSStyleDeclaration declaration = getDeclarationNode();
if (declaration != null) {
try {
if (valueString == null || valueString.length() <= 0) {
declaration.removeProperty(nameString);
}
else {
declaration.setProperty(nameString, valueString, ""); //$NON-NLS-1$
}
}
catch (Exception e) {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
String title = CSSUIMessages.Title_InvalidValue; //$NON-NLS-1$
String message = CSSUIMessages.Message_InvalidValue; //$NON-NLS-1$
MessageDialog.openWarning(window.getShell(), title, message);
}
}
}
private CSSStyleDeclaration getDeclarationNode() {
CSSStyleDeclaration declaration = null;
switch (fNode.getNodeType()) {
case ICSSNode.STYLEDECLITEM_NODE :
declaration = (CSSStyleDeclaration) fNode.getParentNode();
break;
case ICSSNode.STYLERULE_NODE :
case ICSSNode.FONTFACERULE_NODE :
case ICSSNode.PAGERULE_NODE :
declaration = (CSSStyleDeclaration) fNode.getFirstChild();
break;
case ICSSNode.STYLEDECLARATION_NODE :
declaration = (CSSStyleDeclaration) fNode;
break;
case ICSSNode.PRIMITIVEVALUE_NODE :
ICSSNode parent = fNode;
while (parent != null && !(parent instanceof CSSStyleDeclaration)) {
parent = parent.getParentNode();
}
if (parent != null) {
declaration = (CSSStyleDeclaration) parent;
}
break;
default :
break;
}
return declaration;
}
}