package org.droiddraw.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Stack;
import java.util.Vector;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.droiddraw.AndroidEditor;
import org.droiddraw.widget.AbsoluteLayout;
import org.droiddraw.widget.AnalogClock;
import org.droiddraw.widget.AutoCompleteTextView;
import org.droiddraw.widget.Button;
import org.droiddraw.widget.CheckBox;
import org.droiddraw.widget.DatePicker;
import org.droiddraw.widget.DigitalClock;
import org.droiddraw.widget.EditView;
import org.droiddraw.widget.FrameLayout;
import org.droiddraw.widget.Gallery;
import org.droiddraw.widget.GridView;
import org.droiddraw.widget.ImageButton;
import org.droiddraw.widget.ImageView;
import org.droiddraw.widget.Layout;
import org.droiddraw.widget.LinearLayout;
import org.droiddraw.widget.ListView;
import org.droiddraw.widget.ProgressBar;
import org.droiddraw.widget.RadioButton;
import org.droiddraw.widget.RadioGroup;
import org.droiddraw.widget.RelativeLayout;
import org.droiddraw.widget.ScrollView;
import org.droiddraw.widget.Spinner;
import org.droiddraw.widget.TableLayout;
import org.droiddraw.widget.TableRow;
import org.droiddraw.widget.TextView;
import org.droiddraw.widget.Ticker;
import org.droiddraw.widget.TimePicker;
import org.droiddraw.widget.View;
import org.droiddraw.widget.Widget;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class DroidDrawHandler extends DefaultHandler {
Vector<String> all_props;
Stack<Vector<String>> layout_props;
Stack<Layout> layoutStack;
public DroidDrawHandler() {
all_props = new Vector<String>();
all_props.add("android:layout_width");
all_props.add("android:layout_height");
all_props.add("android:background");
all_props.add("android:padding");
all_props.add("android:id");
all_props.add("android:visibility");
all_props.add("android:layout_marginTop");
all_props.add("android:layout_marginBottom");
all_props.add("android:layout_marginLeft");
all_props.add("android:layout_marginRight");
layout_props = new Stack<Vector<String> >();
layoutStack = new Stack<Layout>();
}
protected boolean isLayout(String name) {
return name.endsWith("Layout") || name.equals("RadioGroup") || name.equals("Ticker") || name.equals("TableRow") || name.equals("ScrollView");
}
@Override
public void startElement(String uri, String lName, String qName, Attributes atts)
throws SAXException
{
if (isLayout(qName)) {
Layout l = null;
Vector<String> l_props = new Vector<String>();
if (qName.equals("AbsoluteLayout"))
l = new AbsoluteLayout();
else if (qName.equals("LinearLayout") || (qName.equals("RadioGroup"))) {
if (qName.equals("LinearLayout")) {
l = new LinearLayout();
}
else if (qName.equals("RadioGroup")) {
l = new RadioGroup();
l.setPropertyByAttName("android:checkedButton", atts.getValue("android:checkedButton"));
}
l.setPropertyByAttName("android:gravity", atts.getValue("android:gravity"));
if (atts.getValue("android:orientation") == null) {
l.setPropertyByAttName("android:orientation", "horizontal");
}
else {
l.setPropertyByAttName("android:orientation", atts.getValue("android:orientation"));
}
l_props.add("android:layout_gravity");
l_props.add("android:layout_weight");
}
else if (qName.equals("RelativeLayout")) {
l = new RelativeLayout();
for (int i=0;i<RelativeLayout.propNames.length;i++) {
l_props.add(RelativeLayout.propNames[i]);
}
}
else if (qName.equals("FrameLayout")) {
l = new FrameLayout();
}
else if (qName.equals("TableLayout")) {
l = new TableLayout();
l.setPropertyByAttName("android:stretchColumns", atts.getValue("android:stretchColumns"));
}
else if (qName.equals("TableRow")) {
l = new TableRow();
l_props.add("android:layout_column");
l_props.add("android:layout_span");
}
else if (qName.equals("Ticker")) {
l = new Ticker();
}
else if (qName.equals("ScrollView")) {
l = new ScrollView();
}
if (layoutStack.size() == 0) {
l.setPosition(AndroidEditor.OFFSET_X, AndroidEditor.OFFSET_Y);
for (String prop : all_props) {
if (atts.getValue(prop) != null) {
l.setPropertyByAttName(prop, atts.getValue(prop));
}
}
l.apply();
AndroidEditor.instance().setLayout(l, false);
}
else {
addWidget(l, atts);
}
layoutStack.push(l);
layout_props.push(l_props);
}
else if (layoutStack.size() == 0) {
throw new SAXException("Error, no Layout!");
}
else {
Widget w = null;
if (qName.equals("Button")) {
String txt = atts.getValue("android:text");
Button b = new Button(txt);
w = b;
}
else if (qName.equals("TextView")) {
String txt = atts.getValue("android:text");
w = new TextView(txt);
if (atts.getValue("android:textAlign") != null) {
w.setPropertyByAttName("android:textAlign", atts.getValue("android:textAlign"));
}
}
else if (qName.equals("EditText")) {
String txt = atts.getValue("android:text");
EditView et = new EditView(txt);
for (int i=0;i<EditView.propertyNames.length;i++) {
et.setPropertyByAttName(EditView.propertyNames[i], atts.getValue(EditView.propertyNames[i]));
}
w = et;
}
else if (qName.equals("CheckBox") || qName.equals("RadioButton")) {
String txt = atts.getValue("android:text");
if (qName.equals("CheckBox"))
w = new CheckBox(txt);
else if (qName.equals("RadioButton"))
w = new RadioButton(txt);
w.setPropertyByAttName("android:checked", atts.getValue("android:checked"));
}
else if (qName.equals("DigitalClock")) {
w = new DigitalClock();
}
else if (qName.equals("AnalogClock")) {
w = new AnalogClock();
}
else if (qName.equals("TimePicker")) {
w = new TimePicker();
}
else if (qName.equals("ListView")) {
w = new ListView();
}
else if (qName.equals("Spinner")) {
w = new Spinner();
}
else if (qName.equals("AutoCompleteTextView")) {
w = new AutoCompleteTextView("AutoComplete");
}
else if (qName.equals("ImageButton")) {
w = new ImageButton();
}
else if (qName.equals("ImageView")) {
w = new ImageView();
}
else if (qName.equals("ProgressBar")) {
w = new ProgressBar();
for (int i=0;i<ProgressBar.propertyNames.length;i++) {
w.setPropertyByAttName(ProgressBar.propertyNames[i],
atts.getValue(ProgressBar.propertyNames[i]));
}
}
else if (qName.equals("View")) {
w = new View();
}
else if (qName.equals("GridView")) {
w = new GridView();
for (int i=0;i<GridView.propertyNames.length;i++) {
w.setPropertyByAttName(GridView.propertyNames[i],
atts.getValue(GridView.propertyNames[i]));
}
}
else if (qName.equals("Gallery")) {
w = new Gallery();
for (int i=0;i<Gallery.propertyNames.length;i++) {
w.setPropertyByAttName(Gallery.propertyNames[i],
atts.getValue(Gallery.propertyNames[i]));
}
}
else if (qName.equals("DatePicker")) {
w = new DatePicker();
}
if (w != null) {
addWidget(w, atts);
}
}
}
@Override
public void endElement(String ns, String lName, String qName)
{
if (isLayout(qName)) {
layout_props.pop();
layoutStack.pop();
}
}
protected void addWidget(Widget w, Attributes atts) {
if (w instanceof TextView) {
for (int i=0;i<TextView.propertyNames.length;i++) {
w.setPropertyByAttName(TextView.propertyNames[i], atts.getValue(TextView.propertyNames[i]));
}
}
for (String prop : all_props) {
if (atts.getValue(prop) != null) {
w.setPropertyByAttName(prop, atts.getValue(prop));
}
}
for (String prop : layout_props.peek()) {
if (atts.getValue(prop) != null) {
w.setPropertyByAttName(prop, atts.getValue(prop));
}
}
Layout layout = layoutStack.peek();
w.apply();
if (layout instanceof LinearLayout) {
w.setPosition(layout.getWidth(),layout.getHeight());
}
layout.addWidget(w);
if (layout instanceof AbsoluteLayout) {
int x = DisplayMetrics.readSize(atts.getValue("android:layout_x"));
int y = DisplayMetrics.readSize(atts.getValue("android:layout_y"));
w.setPropertyByAttName("android:layout_x", atts.getValue("android:layout_x"));
w.setPropertyByAttName("android:layout_y", atts.getValue("android:layout_y"));
w.setPosition(x, y);
}
}
public static void loadFromString(String content)
throws SAXException, ParserConfigurationException, IOException
{
load(new InputSource(new StringReader(content)));
}
public static void load(File f)
throws SAXException, ParserConfigurationException, IOException, FileNotFoundException
{
load(new FileReader(f));
}
public static void load(Reader r)
throws SAXException, ParserConfigurationException, IOException
{
load(new InputSource(r));
}
public static void load(InputSource in)
throws SAXException, ParserConfigurationException, IOException
{
DroidDrawHandler ddh = new DroidDrawHandler();
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(in, ddh);
AndroidEditor.instance().getLayout().repositionAllWidgets();
}
}