/**
* Copyright (c) 2012 Cloudsmith Inc. and other contributors, as listed below.
* 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:
* Cloudsmith
*
*/
package org.cloudsmith.xtext.dommodel.formatter;
import org.cloudsmith.xtext.dommodel.IDomNode;
import org.cloudsmith.xtext.dommodel.formatter.ILayoutManager.ILayoutContext;
import org.cloudsmith.xtext.dommodel.formatter.context.IFormattingContext;
import org.cloudsmith.xtext.dommodel.formatter.css.DomCSS;
import org.cloudsmith.xtext.textflow.ITextFlow;
import org.cloudsmith.xtext.textflow.TextFlow;
import org.eclipse.xtext.formatting.IIndentationInformation;
import org.eclipse.xtext.formatting.ILineSeparatorInformation;
import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic;
import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic.Acceptor;
import org.eclipse.xtext.util.ITextRegion;
import org.eclipse.xtext.util.ReplaceRegion;
import org.eclipse.xtext.util.TextRegion;
import com.google.inject.Inject;
import com.google.inject.Provider;
/**
* <p>
* A Dom Model Formatter driven by rules in a {@link DomCSS}.
* <p>
* <p>
* This formatter is given a style sheet in the form of a {@link DomCSS}, and a {@link DomNodeLayoutFeeder} that
* sequences the content of a node to format to instances of {@link ILayoutManager} obtained by computing the
* {@link LayoutStyle} using the given style sheet.
* </p>
* <p>
* The intent is that this implementation works for all formatting needs. A derived class could possibly override the
* {@link #getTextFlow(IFormattingContext)} method if text flow should be collected in specific way.
* </p>
*/
public class CSSDomFormatter implements IDomModelFormatter {
private DomNodeLayoutFeeder layoutFeeder;
private Provider<DomCSS> cssProvider;
@Inject
public CSSDomFormatter(Provider<DomCSS> domProvider, DomNodeLayoutFeeder layoutFeeder) {
cssProvider = domProvider;
this.layoutFeeder = layoutFeeder;
}
@Override
public ReplaceRegion format(IDomNode dom, ITextRegion regionToFormat, IFormattingContext formattingContext) {
return format(dom, regionToFormat, formattingContext, ISerializationDiagnostic.EXCEPTION_THROWING_ACCEPTOR);
}
@Override
public ReplaceRegion format(IDomNode dom, final ITextRegion regionToFormat,
final IFormattingContext formattingContext, final Acceptor errors) {
final DomCSS css = cssProvider.get();
ILayoutContext layoutContext = new AbstractLayoutContext() {
@Override
public DomCSS getCSS() {
return css;
}
@Override
public Acceptor getErrorAcceptor() {
return errors;
}
@Override
public IIndentationInformation getIndentationInformation() {
return formattingContext.getIndentationInformation();
}
@Override
public ILineSeparatorInformation getLineSeparatorInformation() {
return formattingContext.getLineSeparatorInformation();
}
@Override
public int getPreferredMaxWidth() {
return formattingContext.getPreferredMaxWidth();
}
@Override
public ITextRegion getRegionToFormat() {
return regionToFormat;
}
@Override
public int getWrapIndentSize() {
return formattingContext.getWrapIndentSize();
}
@Override
public boolean isWhitespacePreservation() {
return formattingContext.isWhitespacePreservation();
}
};
final ITextFlow.WithText output = getTextFlow(formattingContext);
layoutFeeder.sequence(dom, output, layoutContext);
// internalFormat(dom, output, layoutContext);
final CharSequence text = output.getText();
String textString = null;
if(text instanceof String)
textString = (String) text;
else if(text instanceof StringBuilder)
textString = ((StringBuilder) text).toString();
else
textString = new StringBuilder(text).toString();
return new ReplaceRegion(regionToFormat == null
? new TextRegion(0, text.length())
: regionToFormat, textString);
}
protected ITextFlow.WithText getTextFlow(IFormattingContext context) {
return new TextFlow(context);
}
}