package com.baselet.element;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.baselet.control.basics.geom.DimensionDouble;
import com.baselet.control.enums.ElementStyle;
import com.baselet.element.facet.Facet;
import com.baselet.element.facet.PropertiesParserState;
/**
* The PropertiesParser analyzes the Properties and the Facets of a GridElement and handles AUTORESIZE
* The Facets typically manipulates the DrawHandler state by executing the drawing methods (e.g. printing the main-text of the element, transforming -- to a horizontal line, ...)
*
* A summary of the process is the following:
* 1. Do a complete parser run (without drawing anything) to calculate the textblock height and possibly start the AUTORESIZE calculation.
* 2. The First-Run Facets get parsed and applied in order of their PriorityEnum value (this reduces the size of the remaining properties for the Second Run)
* 3. The common content of the element is drawn (e.g. the border) (therefore this must happen AFTER parsing the First-Run Facets because they can change the bg-color and so on)
* 4. The remaining properties are parsed and the Second-Run Facets are applied.
*/
public class PropertiesParser {
public static void parsePropertiesAndHandleFacets(NewGridElement element, PropertiesParserState state) {
List<String> propertiesText = element.getPanelAttributesAsList();
doPreparsing(element, state, propertiesText); // at first handle autoresize (which possibly changes elementsize) and calc the textblock size
parseFacets(element, state, propertiesText, true);
}
private static void doPreparsing(NewGridElement element, PropertiesParserState state, List<String> propertiesText) {
state.resetValues(element.getRealSize(), state.getTotalTextBlockHeight(), false); // assume certain values and disable drawing for the preparsing step
parseFacets(element, state, propertiesText, false);
if (state.getElementStyle() == ElementStyle.AUTORESIZE) { // only in case of autoresize element, calculate the elementsize
double width = state.getMinimumWidth();
double height = state.getTextPrintPosition();
element.handleAutoresize(new DimensionDouble(width, height), state.getAlignment().getHorizontal());
}
double textblockHeight = state.getTextPrintPosition() - state.getBuffer().getTop();
state.resetValues(element.getRealSize(), textblockHeight, true); // now that the element size and textblock height is known, the state is reset once again with enabled drawing
}
private static void parseFacets(NewGridElement element, PropertiesParserState state, List<String> propertiesText, boolean drawMetaDrawer) {
List<String> propertiesAfterFirstRun = parseFacets(state.getSettings().getFacetsForFirstRun(), propertiesText, state); // must be before element.drawCommonContent (because bg=... and other settings are set here)
element.resetMetaDrawerAndDrawCommonContent(state, drawMetaDrawer); // draw common content like border around classes
parseFacets(state.getSettings().getFacetsForSecondRun(), propertiesAfterFirstRun, state); // iterate over propertiestext and draw text and resolve second-run facets
}
private static List<String> parseFacets(List<? extends Facet> facets, List<String> properties, PropertiesParserState state) {
Map<Facet, List<String>> facetUsageMap = new HashMap<Facet, List<String>>();
for (Facet f : facets) { // at parsing start every facet has an empty usage list
facetUsageMap.put(f, new ArrayList<String>());
}
List<String> unusedProperties = new ArrayList<String>(properties);
for (Iterator<String> iter = unusedProperties.iterator(); iter.hasNext();) {
String line = iter.next();
for (Facet f : facets) {
if (f.checkStart(line, state)) {
f.handleLine(line, state);
facetUsageMap.get(f).add(line);
iter.remove();
break; // once a facet has consumed a line, no other facet can
}
}
}
for (Facet f : facets) {
f.parsingFinished(state, facetUsageMap.get(f));
}
return unusedProperties;
}
}