<?xml version="1.0" encoding="UTF-8" ?>

<grammar xmlns="http://relaxng.org/ns/structure/1.0">
  <start>
    <element name="interface">
      <attribute name="base_widget"/>
      <attribute name="sequence"/>
      <oneOrMore>
	<ref name="widget"/>
      </oneOrMore>
      <oneOrMore>
	<ref name="message_box"/>
      </oneOrMore>
      <zeroOrMore>
	<ref name='top_window'/>
      </zeroOrMore>
      <zeroOrMore>
	<ref name="text"/>
      </zeroOrMore>
      <oneOrMore>
	<ref name="sequence"/>
      </oneOrMore>
    </element>
  </start>

  <define name="widget">
    <element name="widget">
      <attribute name="type"/>
      <optional>
	<attribute name="name"/>
      </optional>
      <optional>
	<attribute name='construct'/>
      </optional>
      <optional>
	<ref name="widget_attribute"/>
      </optional>
      <optional>
	<!-- geometry management is to manage its sons -->
	<ref name="geometry_management"/>
      </optional>
      <optional>
	<!-- geometry location is the location inside its parent -->
	<ref name="geometry_location"/>
      </optional>
      <zeroOrMore>
	<ref name="variable"/>
      </zeroOrMore>
      <optional>
	<ref name="action"/>
      </optional>
      <zeroOrMore>
	<ref name="binding"/>
      </zeroOrMore>
      <zeroOrMore>
	<ref name="widget"/>
      </zeroOrMore>
    </element>
  </define>

  <!-- I split widget attributes from attributes added by I. So I
can easily convert add widget attributes into a dict without processing
on special cases -->

  <define name="widget_attribute">
    <element name="widget_attribute">
      <interleave>
	<optional>
	  <attribute name="background"/>
	</optional>
	<optional>
	  <attribute name="height"/>
	</optional>
	<optional>
	  <attribute name="width"/>
	</optional>
	<optional>
	  <attribute name="text"/>
	</optional>
	<optional>
	  <attribute name="command"/>
	</optional>
	<optional>
	  <attribute name="image"/>
	</optional>
	<optional>
	  <attribute name="state"/>
	</optional>
	<optional>
	  <attribute name="textvariable"/>
	</optional>
	<optional>
	  <attribute name="listvariable"/>
	</optional>
	<optional>
	  <attribute name="orient">
	    <choice>
	      <value>vertical</value>
	      <value>horizontal</value>
	    </choice>
	  </attribute>
	</optional>
	<optional>
	  <attribute name='variable'/>
	</optional>
	<optional>
	  <attribute name='value'/>
	</optional>
	<optional>
	  <attribute name='selectmode'/>
	</optional>
	<optional>
	  <attribute name='onvalue'/>
	</optional>
	<optional>
	  <attribute name='offvalue'/>
	</optional>
      </interleave>
    </element>
  </define>

  <define name="geometry_management">
    <!-- why choice? because there may be other geometry management-->
    <choice>
      <element name="grid_management">
	<attribute name="rows"/>
	<attribute name="columns"/>
	<oneOrMore>
	  <element name="configure">
	    <choice>
	      <attribute name="row"/>
	      <attribute name="column"/>
	    </choice>
	    <attribute name="weight"/>
	  </element>
	</oneOrMore>
      </element>
    </choice>
  </define>

  <define name="geometry_location">
    <!-- why choice? because there may be other geometry location -->
    <choice>
      <element name="grid_location">
	<attribute name="row"/>
	<attribute name="column"/>
	<interleave>
	  <optional>
	    <attribute name="columnspan"/>
	  </optional>
	  <optional>
	    <attribute name="rowspan"/>
	  </optional>
	  <optional>
	    <attribute name="sticky"/>
	  </optional>
	  <optional>
	    <attribute name="padx"/>
	  </optional>
	  <optional>
	    <attribute name="pady"/>
	  </optional>
	</interleave>
      </element>
    </choice>
  </define>

  <define name="variable">
    <element name="variable">
      <attribute name="name"/>
      <attribute name="type"/>
      <optional>
	<attribute name="value"/>
      </optional>
    </element>
  </define>

  <define name="action">
    <element name="action">
      <optional>
	<attribute name="init"/>
      </optional>
      <optional>
	<attribute name="quit"/>
      </optional>
      <zeroOrMore>
	<element name='scroll'>
	  <attribute name='scrolling'/>
	  <attribute name='scrolled'/>
	</element>
      </zeroOrMore>
    </element>
  </define>

  <define name='binding'>
    <element name='binding'>
      <attribute name='sequence'/>
      <attribute name='function'/>
    </element>
  </define>
      
  <define name="message_box">
    <element name="message_box">
      <attribute name="name"/>
      <attribute name="type">
	<choice>
	  <value>askokcancel</value>
	  <value>askquestion</value>
	  <value>askretrycancel</value>
	  <value>askyesno</value>
	  <value>showerror</value>
	  <value>showinfo</value>
	  <value>showwarning</value>
	</choice>
      </attribute>
      <attribute name="title"/>
      <attribute name="message"/>
    </element>
  </define>

  <define name='top_window'>
    <element name='top_window'>
      <attribute name='name'/>
      <optional>
	<ref name="widget_attribute"/>
      </optional>
      <optional>
	<attribute name='construct'/>
      </optional>
      <optional>
	<!-- geometry management is to manage its sons -->
	<ref name="geometry_management"/>
      </optional>
      <zeroOrMore>
	<ref name="widget"/>
      </zeroOrMore>
    </element>
  </define>

  <define name="text">
    <element name="text">
      <optional>
	<attribute name="key"/>
      </optional>
      <interleave>
	<element name="English">
	  <text/>
	</element>
	<element name="Chinese">
	  <text/>
	</element>
      </interleave>
    </element>
  </define>

  <define name="sequence">
    <element name="sequence">
      <attribute name="name"/>
      <oneOrMore>
	<element name="widget">
	  <attribute name="name"/>
	</element>
      </oneOrMore>
    </element>
  </define>
</grammar>
  
