blob: 880851941ce00784dd3f75afa1ceac219f86329e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2005 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.core.internal.formatter;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.wst.css.core.internal.provisional.adapters.ICSSModelAdapter;
import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleDeclarationAdapter;
import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetAdapter;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
public class CSSFormatUtil {
public List collectCSSNodes(IStructuredModel model, int start, int length) {
List nodes = new ArrayList();
IndexedRegion startNode = model.getIndexedRegion(start);
IndexedRegion endNode = model.getIndexedRegion(start + length - 1);
if (startNode == null || endNode == null) {
return nodes;
}
if (model instanceof ICSSModel && startNode instanceof ICSSNode && endNode instanceof ICSSNode) {
// CSS model
ICSSNode ca = getCommonAncestor((ICSSNode) startNode, (ICSSNode) endNode);
if (ca != null) {
for (ICSSNode node = ca.getFirstChild(); node != null && start + length < ((IndexedRegion) node).getStartOffset(); node = node.getNextSibling()) {
if (start < ((IndexedRegion) node).getEndOffset()) {
nodes.add(node);
}
}
}
}
else if (model instanceof IDOMModel && startNode instanceof IDOMNode && endNode instanceof IDOMNode) {
if (startNode instanceof Text) {
startNode = (IndexedRegion) ((Text) startNode).getParentNode();
}
if (endNode instanceof Text) {
endNode = (IndexedRegion) ((Text) endNode).getParentNode();
}
// HTML model, maybe
IDOMNode ca = (IDOMNode) getCommonAncestor((Node) startNode, (Node) endNode);
findCSS(nodes, ca);
}
return nodes;
}
/**
* getCommonAncestor method
*
* @return org.w3c.dom.Node
* @param node
* org.w3c.dom.Node
*/
private Node getCommonAncestor(Node node1, Node node2) {
if (node1 == null || node2 == null)
return null;
for (Node na = node2; na != null; na = na.getParentNode()) {
for (Node ta = node1; ta != null; ta = ta.getParentNode()) {
if (ta == na)
return ta;
}
}
return null; // not found
}
private void findCSS(List cssNodes, IDOMNode node) {
ICSSModelAdapter adapter;
adapter = (ICSSModelAdapter) node.getAdapterFor(IStyleSheetAdapter.class);
if (adapter != null) {
ICSSModel model = adapter.getModel();
if (model != null && model.getStyleSheetType() == ICSSModel.EMBEDDED) {
cssNodes.add(model.getDocument());
}
}
else {
adapter = (ICSSModelAdapter) node.getAdapterFor(IStyleDeclarationAdapter.class);
if (adapter != null) {
ICSSModel model = adapter.getModel();
if (model != null && model.getStyleSheetType() == ICSSModel.INLINE) {
cssNodes.add(model.getDocument());
}
}
}
for (IDOMNode child = (IDOMNode) node.getFirstChild(); child != null; child = (IDOMNode) child.getNextSibling()) {
findCSS(cssNodes, child);
}
}
private ICSSNode getCommonAncestor(ICSSNode nodeA, ICSSNode nodeB) {
if (nodeA == null || nodeB == null) {
return null;
}
for (ICSSNode na = nodeA; na != null; na = na.getParentNode()) {
for (ICSSNode ta = nodeB; ta != null; ta = ta.getParentNode()) {
if (ta == na) {
return ta;
}
}
}
return null; // not found
}
/**
*/
public void replaceSource(IStructuredModel model, int offset, int length, String source) {
if (model == null)
return;
IStructuredDocument structuredDocument = model.getStructuredDocument();
if (structuredDocument == null)
return;
if (offset >= 0 && length >= 0 && offset + length <= structuredDocument.getLength()) {
if (structuredDocument.containsReadOnly(offset, length))
return;
if (source == null)
source = new String();
// We use 'structuredDocument' as the requester object just so
// this and the other
// format-related 'repalceText' (in replaceSource) can use the
// same requester.
// Otherwise, if requester is not identical,
// the undo group gets "broken" into multiple pieces based
// on the requesters being different. Technically, any unique,
// common
// requester object would work.
structuredDocument.replaceText(structuredDocument, offset, length, source);
}
}
public synchronized static CSSFormatUtil getInstance() {
if (fInstance == null) {
fInstance = new CSSFormatUtil();
}
return fInstance;
}
private CSSFormatUtil() {
super();
}
private static CSSFormatUtil fInstance;
}