<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- $Id$ -->
<!--
<!DOCTYPE document SYSTEM "../xml-docs/dtd/document-v10.dtd">
-->

<document>
  <header>
    <title>Property Expression Parsing</title>
    <authors>
       <person id="pbw" name="Peter B. West" email="pbwest@powerup.com.au"/>
    </authors>
  </header>
  <body>
    <!-- one of (anchor s1) -->
    <s1 title="Property expression parsing">
      <note>
	The following discussion of the experiments with alternate
	property expression parsing is very much a work in progress,
	and subject to sudden changes.
      </note>
      <p>
	The parsing of property value expressions is handled by two
	closely related classes: <code>PropertyTokenizer</code> and its
	subclass, <code>PropertyParser</code>.
	<code>PropertyTokenizer</code>, as the name suggests, handles
	the tokenizing of the expression, handing <em>tokens</em>
	back to its subclass,
	<code>PropertyParser</code>. <code>PropertyParser</code>, in
	  turn, returns a <code>PropertyValueList</code>, a list of
	<code>PropertyValue</code>s. 
      </p>
      <p>
	The tokenizer and parser rely in turn on the datatype
	definition from the <code>org.apache.fop.datatypes</code>
	package and the datatype <code>static final int</code>
	constants from <code>PropertyConsts</code>.
      </p>
      <s2 title="Data types">
	<p>
	  The data types currently defined in
	  <code>org.apache.fop.datatypes</code> include:
	</p>
	<table>
	  <tr><th colspan="2">Numbers and lengths</th></tr>
	  <tr>
	    <th>Numeric</th>
	    <td colspan="3">
	      The fundamental numeric data type.  <em>Numerics</em> of
	      various types are constructed by the classes listed
	      below.
	    </td>
	  </tr>
	  <tr>
	    <td/>
	    <th colspan="3">Constructor classes for <em>Numeric</em></th>
	  </tr>
	  <tr>
	    <td/><td>Angle</td>
	    <td colspan="2">In degrees(deg), gradients(grad) or
	      radians(rad)</td>
	  </tr>
	  <tr>
	    <td/><td>Ems</td>
	    <td colspan="2">Relative length in <em>ems</em></td>
	  </tr>
	  <tr>
	    <td/><td>Frequency</td>
	    <td colspan="2">In hertz(Hz) or kilohertz(kHz)</td>
	  </tr>
	  <tr>
	    <td/><td>IntegerType</td><td/>
	  </tr>
	  <tr>
	    <td/><td>Length</td>
	    <td colspan="2">In centimetres(cm), millimetres(mm),
	      inches(in), points(pt), picas(pc) or pixels(px)</td>
	  </tr>
	  <tr>
	    <td/><td>Percentage</td><td/>
	  </tr>
	  <tr>
	    <td/><td>Time</td>
	    <td>In seconds(s) or milliseconds(ms)</td>
	  </tr>
	  <tr><th colspan="2">Strings</th></tr>
	  <tr>
	    <th>StringType</th>
	    <td colspan="3">
	      Base class for data types which result in a <em>String</em>.
	    </td>
	  </tr>
	  <tr>
	    <td/><th>Literal</th>
	    <td colspan="2">
	      A subclass of <em>StringType</em> for literals which
	      exceed the constraints of an <em>NCName</em>.
	    </td>
	  </tr>
	  <tr>
	    <td/><th>MimeType</th>
	    <td colspan="2">
	      A subclass of <em>StringType</em> for literals which
	      represent a mime type.
	    </td>
	  </tr>
	  <tr>
	    <td/><th>UriType</th>
	    <td colspan="2">
	      A subclass of <em>StringType</em> for literals which
	      represent a URI, as specified by the argument to
	      <em>url()</em>.
	    </td>
	  </tr>
	  <tr>
	    <td/><th>NCName</th>
	    <td colspan="2">
	      A subclass of <em>StringType</em> for literals which
	      meet the constraints of an <em>NCName</em>.
	    </td>
	  </tr>
	  <tr>
	    <td/><td/><th>Country</th>
	    <td>An RFC 3066/ISO 3166 country code.</td>
	  </tr>
	  <tr>
	    <td/><td/><th>Language</th>
	    <td>An RFC 3066/ISO 639 language code.</td>
	  </tr>
	  <tr>
	    <td/><td/><th>Script</th>
	    <td>An ISO 15924 script code.</td>
	  </tr>
	  <tr><th colspan="2">Enumerated types</th></tr>
	  <tr>
	    <th>EnumType</th>
	    <td colspan="3">
	      An integer representing one of the tokens in a set of
	      enumeration values.
	    </td>
	  </tr>
	  <tr>
	    <td/><th>MappedEnumType</th>
	    <td colspan="2">
	      A subclass of <em>EnumType</em>.  Maintains a
	      <em>String</em> with the value to which the associated
	      "raw" enumeration token maps.  E.g., the
	      <em>font-size</em> enumeration value "medium" maps to
	      the <em>String</em> "12pt".
	    </td>
	  </tr>
	  <tr><th colspan="2">Colors</th></tr>
	  <tr>
	    <th>ColorType</th>
	    <td colspan="3">
	      Maintains a four-element array of float, derived from
	      the name of a standard colour, the name returned by a
	      call to <em>system-color()</em>, or an RGB
	      specification.
	    </td>
	  </tr>
	  <tr><th colspan="2">Fonts</th></tr>
	  <tr>
	    <th>FontFamilySet</th>
	    <td colspan="3">
	      Maintains an array of <em>String</em>s containing a
	      prioritized list of possibly generic font family names.
	    </td>
	  </tr>
	  <tr><th colspan="2">Pseudo-types</th></tr>
	  <tr>
	    <td colspan="4">
	      A variety of pseudo-types have been defined as
	      convenience types for frequently appearing enumeration
	      token values, or for other special purposes.
	    </td>
	  </tr>
	  <tr>
	    <th>Inherit</th>
	    <td colspan="3">
	      For values of <em>inherit</em>.
	    </td>
	  </tr>
	  <tr>
	    <th>Auto</th>
	    <td colspan="3">
	      For values of <em>auto</em>.
	    </td>
	  </tr>
	  <tr>
	    <th>None</th>
	    <td colspan="3">
	      For values of <em>none</em>.
	    </td>
	  </tr>
	  <tr>
	    <th>Bool</th>
	    <td colspan="3">
	      For values of <em>true/false</em>.
	    </td>
	  </tr>
	  <tr>
	    <th>FromNearestSpecified</th>
	    <td colspan="3">
	      Created to ensure that, when associated with
	      a shorthand, the <em>from-nearest-specified-value()</em>
	      core function is the sole component of the expression.
	    </td>
	  </tr>
	  <tr>
	    <th>FromParent</th>
	    <td colspan="3">
	      Created to ensure that, when associated with
	      a shorthand, the <em>from-parent()</em>
	      core function is the sole component of the expression.
	    </td>
	  </tr>
	</table>
      </s2>
      <s2 title="Tokenizer">
	<p>
	  The tokenizer returns one of the following token
	  values:
	</p>
	<source>
    static final int
                 EOF = 0
             ,NCNAME = 1
           ,MULTIPLY = 2
               ,LPAR = 3
               ,RPAR = 4
            ,LITERAL = 5
      ,FUNCTION_LPAR = 6
               ,PLUS = 7
              ,MINUS = 8
                ,MOD = 9
                ,DIV = 10
              ,COMMA = 11
            ,PERCENT = 12
          ,COLORSPEC = 13
              ,FLOAT = 14
            ,INTEGER = 15
    ,ABSOLUTE_LENGTH = 16
    ,RELATIVE_LENGTH = 17
               ,TIME = 18
               ,FREQ = 19
              ,ANGLE = 20
            ,INHERIT = 21
               ,AUTO = 22
               ,NONE = 23
               ,BOOL = 24
                ,URI = 25
           ,MIMETYPE = 26
            // NO_UNIT is a transient token for internal use only.  It is
            // never set as the end result of parsing a token.
            ,NO_UNIT = 27
                     ;
	</source>
	<p>
	  Most of these tokens are self-explanatory, but a few need
	  further comment.
	</p>
	<dl>
	  <dt>AUTO</dt>
	  <dd>
	    Because of its frequency of occurrence, and the fact that
	    it is always the <em>initial value</em> for any property
	    which supports it, AUTO has been promoted into a
	    pseudo-type with its on datatype class.  Therefore, it is
	    also reported as a token.
	  </dd>
	  <dt>NONE</dt>
	  <dd>
	    Similarly to AUTO, NONE has been promoted to a pseudo-type
	    because of its frequency.
	  </dd>
	  <dt>BOOL</dt>
	  <dd>
	    There is a <em>de facto</em> boolean type buried in the
	    enumeration types for many of the properties.  It had been
	    specified as a type in its own right in this code.
	  </dd>
	  <dt>MIMETYPE</dt>
	  <dd>
	    The property <code>content-type</code> introduces this
	    complication.  It can have two values of the form
	    <strong>content-type:</strong><em>mime-type</em>
	    (e.g. <code>content-type="content-type:xml/svg"</code>) or
	    <strong>namespace-prefix:</strong><em>prefix</em>
	    (e.g. <code>content-type="namespace-prefix:svg"</code>).  The
	      experimental code reduces these options to the payload
	      in each case: an <code>NCName</code> in the case of a
	    namespace prefix, and a MIMETYPE in the case of a
	    content-type specification.  <code>NCName</code>s cannot
	    contain a "/". 
	  </dd>
	</dl>
      </s2>
      <s2 title="Parser">
	<p>
	  The parser retuns a <code>PropertyValueList</code>,
	  necessary because of the possibility that a list of
	  <code>PropertyValue</code> elements may be returned from the
	  expressions of soem properties.
	</p>
	<p>
	  <code>PropertyValueList</code>s may contain
	  <code>PropertyValue</code>s or other
	  <code>PropertyValueList</code>s.  This latter provision is
	  necessitated for the peculiar case of of
	  <em>text-shadow</em>, which may contain whitespace separated
	  sublists of either two or three elements, separated from one
	  another by commas.  To accommodate this peculiarity, comma
	  separated elements are added to the top-level list, while
	  whitespace separated values are always collected into
	  sublists to be added to the top-level list.
	</p>
	<p>
	  Other special cases include the processing of the core
	  functions <code>from-parent()</code> and
	  <code>from-nearest-specified-value()</code> when these
	  function calls are assigned to a shorthand property, or used
	  with a shorthand property name as an argument.  In these
	  cases, the function call must be the sole component of the
	  expression.  The pseudo-element classes
	  <code>FromParent</code> and
	  <code>FromNearestSpecified</code> are generated in these
	  circumstances so that an exception will be thrown if they
	  are involved in expression evaluation with other
	  components. (See Rec. Section 5.10.4 Property Value
	  Functions.)
	</p>
	<p>
	  The experimental code is a simple extension of the existing
	  parser code, which itself borrowed heavily from James
	  Clark's XT processor.
	</p>
      </s2>
    </s1>
  </body>
</document>
39' href='#n39'>39</a>
<a id='n40' href='#n40'>40</a>
<a id='n41' href='#n41'>41</a>
<a id='n42' href='#n42'>42</a>
<a id='n43' href='#n43'>43</a>
<a id='n44' href='#n44'>44</a>
<a id='n45' href='#n45'>45</a>
<a id='n46' href='#n46'>46</a>
<a id='n47' href='#n47'>47</a>
<a id='n48' href='#n48'>48</a>
<a id='n49' href='#n49'>49</a>
<a id='n50' href='#n50'>50</a>
<a id='n51' href='#n51'>51</a>
<a id='n52' href='#n52'>52</a>
<a id='n53' href='#n53'>53</a>
<a id='n54' href='#n54'>54</a>
<a id='n55' href='#n55'>55</a>
<a id='n56' href='#n56'>56</a>
<a id='n57' href='#n57'>57</a>
<a id='n58' href='#n58'>58</a>
<a id='n59' href='#n59'>59</a>
<a id='n60' href='#n60'>60</a>
<a id='n61' href='#n61'>61</a>
<a id='n62' href='#n62'>62</a>
<a id='n63' href='#n63'>63</a>
<a id='n64' href='#n64'>64</a>
<a id='n65' href='#n65'>65</a>
<a id='n66' href='#n66'>66</a>
<a id='n67' href='#n67'>67</a>
<a id='n68' href='#n68'>68</a>
<a id='n69' href='#n69'>69</a>
<a id='n70' href='#n70'>70</a>
<a id='n71' href='#n71'>71</a>
<a id='n72' href='#n72'>72</a>
<a id='n73' href='#n73'>73</a>
<a id='n74' href='#n74'>74</a>
<a id='n75' href='#n75'>75</a>
<a id='n76' href='#n76'>76</a>
<a id='n77' href='#n77'>77</a>
<a id='n78' href='#n78'>78</a>
<a id='n79' href='#n79'>79</a>
<a id='n80' href='#n80'>80</a>
<a id='n81' href='#n81'>81</a>
<a id='n82' href='#n82'>82</a>
<a id='n83' href='#n83'>83</a>
<a id='n84' href='#n84'>84</a>
<a id='n85' href='#n85'>85</a>
<a id='n86' href='#n86'>86</a>
<a id='n87' href='#n87'>87</a>
<a id='n88' href='#n88'>88</a>
<a id='n89' href='#n89'>89</a>
<a id='n90' href='#n90'>90</a>
<a id='n91' href='#n91'>91</a>
<a id='n92' href='#n92'>92</a>
<a id='n93' href='#n93'>93</a>
<a id='n94' href='#n94'>94</a>
<a id='n95' href='#n95'>95</a>
<a id='n96' href='#n96'>96</a>
<a id='n97' href='#n97'>97</a>
<a id='n98' href='#n98'>98</a>
<a id='n99' href='#n99'>99</a>
<a id='n100' href='#n100'>100</a>
<a id='n101' href='#n101'>101</a>
<a id='n102' href='#n102'>102</a>
<a id='n103' href='#n103'>103</a>
<a id='n104' href='#n104'>104</a>
<a id='n105' href='#n105'>105</a>
<a id='n106' href='#n106'>106</a>
<a id='n107' href='#n107'>107</a>
<a id='n108' href='#n108'>108</a>
<a id='n109' href='#n109'>109</a>
<a id='n110' href='#n110'>110</a>
<a id='n111' href='#n111'>111</a>
<a id='n112' href='#n112'>112</a>
<a id='n113' href='#n113'>113</a>
<a id='n114' href='#n114'>114</a>
<a id='n115' href='#n115'>115</a>
<a id='n116' href='#n116'>116</a>
<a id='n117' href='#n117'>117</a>
<a id='n118' href='#n118'>118</a>
<a id='n119' href='#n119'>119</a>
<a id='n120' href='#n120'>120</a>
<a id='n121' href='#n121'>121</a>
<a id='n122' href='#n122'>122</a>
<a id='n123' href='#n123'>123</a>
<a id='n124' href='#n124'>124</a>
<a id='n125' href='#n125'>125</a>
<a id='n126' href='#n126'>126</a>
<a id='n127' href='#n127'>127</a>
<a id='n128' href='#n128'>128</a>
<a id='n129' href='#n129'>129</a>
<a id='n130' href='#n130'>130</a>
<a id='n131' href='#n131'>131</a>
<a id='n132' href='#n132'>132</a>
<a id='n133' href='#n133'>133</a>
<a id='n134' href='#n134'>134</a>
<a id='n135' href='#n135'>135</a>
<a id='n136' href='#n136'>136</a>
<a id='n137' href='#n137'>137</a>
<a id='n138' href='#n138'>138</a>
<a id='n139' href='#n139'>139</a>
<a id='n140' href='#n140'>140</a>
<a id='n141' href='#n141'>141</a>
<a id='n142' href='#n142'>142</a>
<a id='n143' href='#n143'>143</a>
<a id='n144' href='#n144'>144</a>
<a id='n145' href='#n145'>145</a>
<a id='n146' href='#n146'>146</a>
<a id='n147' href='#n147'>147</a>
<a id='n148' href='#n148'>148</a>
<a id='n149' href='#n149'>149</a>
<a id='n150' href='#n150'>150</a>
<a id='n151' href='#n151'>151</a>
<a id='n152' href='#n152'>152</a>
<a id='n153' href='#n153'>153</a>
<a id='n154' href='#n154'>154</a>
<a id='n155' href='#n155'>155</a>
<a id='n156' href='#n156'>156</a>
<a id='n157' href='#n157'>157</a>
<a id='n158' href='#n158'>158</a>
<a id='n159' href='#n159'>159</a>
<a id='n160' href='#n160'>160</a>
<a id='n161' href='#n161'>161</a>
<a id='n162' href='#n162'>162</a>
<a id='n163' href='#n163'>163</a>
<a id='n164' href='#n164'>164</a>
<a id='n165' href='#n165'>165</a>
<a id='n166' href='#n166'>166</a>
<a id='n167' href='#n167'>167</a>
<a id='n168' href='#n168'>168</a>
<a id='n169' href='#n169'>169</a>
<a id='n170' href='#n170'>170</a>
<a id='n171' href='#n171'>171</a>
<a id='n172' href='#n172'>172</a>
<a id='n173' href='#n173'>173</a>
<a id='n174' href='#n174'>174</a>
<a id='n175' href='#n175'>175</a>
<a id='n176' href='#n176'>176</a>
<a id='n177' href='#n177'>177</a>
<a id='n178' href='#n178'>178</a>
<a id='n179' href='#n179'>179</a>
<a id='n180' href='#n180'>180</a>
<a id='n181' href='#n181'>181</a>
<a id='n182' href='#n182'>182</a>
<a id='n183' href='#n183'>183</a>
<a id='n184' href='#n184'>184</a>
<a id='n185' href='#n185'>185</a>
<a id='n186' href='#n186'>186</a>
<a id='n187' href='#n187'>187</a>
<a id='n188' href='#n188'>188</a>
<a id='n189' href='#n189'>189</a>
<a id='n190' href='#n190'>190</a>
<a id='n191' href='#n191'>191</a>
<a id='n192' href='#n192'>192</a>
<a id='n193' href='#n193'>193</a>
<a id='n194' href='#n194'>194</a>
<a id='n195' href='#n195'>195</a>
<a id='n196' href='#n196'>196</a>
<a id='n197' href='#n197'>197</a>
<a id='n198' href='#n198'>198</a>
<a id='n199' href='#n199'>199</a>
<a id='n200' href='#n200'>200</a>
<a id='n201' href='#n201'>201</a>
<a id='n202' href='#n202'>202</a>
<a id='n203' href='#n203'>203</a>
<a id='n204' href='#n204'>204</a>
<a id='n205' href='#n205'>205</a>
</pre></td>
<td class='lines'><pre><code><style>pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span>---
title: ProgressBar
order: 27
layout: page
---

[[components.progressbar]]
= [classname]#ProgressBar#

ifdef::web[]
[.sampler]
image:{live-demo-image}[alt=&quot;Live Demo&quot;, link=&quot;http://demo.vaadin.com/sampler/#ui/interaction/progress-bar&quot;]
endif::web[]

The [classname]#ProgressBar# component allows visualizing progress of a task.
The progress is specified as a floating-point value between 0.0 and 1.0.

[[figure.components.progressbar.basic]]
.The [classname]#ProgressBar# component
image::img/progressbar-basic.png[width=30%, scaledwidth=70%]

To display upload progress with the [classname]#Upload# component, you can
update the progress bar in a [interfacename]#ProgressListener#.

When the position of a progress bar is done in a background thread, the change
is not shown in the browser immediately. You need to use either polling or
server push to update the browser. You can enable polling with
[methodname]#setPollInterval()# in the current UI instance. See
&lt;&lt;dummy/../../../framework/advanced/advanced-push#advanced.push,&quot;Server Push&quot;&gt;&gt;
for instructions about using server push. Whichever method you use to update the
UI, it is important to lock the user session by modifying the progress bar value
inside [methodname]#access()# call, as illustrated in the following example and
described in
&lt;&lt;dummy/../../../framework/advanced/advanced-push#advanced.push.running,&quot;Accessing UI from Another Thread&quot;&gt;&gt;.

[source, java]
----
final ProgressBar bar = new ProgressBar(0.0f);
layout.addComponent(bar);

layout.addComponent(new Button(&quot;Increase&quot;,
    new ClickListener() {
    @Override
    public void buttonClick(ClickEvent event) {
        float current = bar.getValue();
        if (current &lt; 1.0f)
            bar.setValue(current + 0.10f);
    }
}));
----

[[components.progressbar.indeterminate]]
== Indeterminate Mode

In the indeterminate mode, a non-progressive indicator is displayed
continuously. The indeterminate indicator is a circular wheel in the built-in
themes. The progress value has no meaning in the indeterminate mode.


[source, java]
----
ProgressBar bar = new ProgressBar();
bar.setIndeterminate(true);
----

[[figure.components.progressbar.indeterminate]]
.Indeterminate progress bar
image::img/progressbar-indeterminate.png[width=15%, scaledwidth=40%]

ifdef::web[]
[[components.progressbar.thread]]
== Doing Heavy Computation

The progress bar is typically used to display the progress of a heavy
server-side computation task, often running in a background thread. The UI,
including the progress bar, can be updated either with polling or by using
server push. When doing so, you must ensure thread-safety, most easily by
updating the UI inside a [methodname]#UI.access()# call in a
[interfacename]#Runnable#, as described in
&lt;&lt;dummy/../../../framework/advanced/advanced-push#advanced.push.running,&quot;Accessing
UI from Another Thread&quot;&gt;&gt;.

In the following example, we create a thread in the server to do some &quot;heavy
work&quot; and use polling to update the UI. All the thread needs to do is to set the
value of the progress bar with [methodname]#setValue()# and the current progress
is displayed automatically when the browser polls the server.


[source, java]
----
HorizontalLayout barbar = new HorizontalLayout();
layout.addComponent(barbar);

// Create the bar, disabled until progress is started
final ProgressBar progress = new ProgressBar(new Float(0.0));
progress.setEnabled(false);
barbar.addComponent(progress);

final Label status = new Label(&quot;not running&quot;);
barbar.addComponent(status);

// A button to start progress
final Button button = new Button(&quot;Click to start&quot;);
layout.addComponent(button);

// A thread to do some work
class WorkThread extends Thread {
    // Volatile because read in another thread in access()
    volatile double current = 0.0;

    @Override
    public void run() {
        // Count up until 1.0 is reached
        while (current &lt; 1.0) {
            current += 0.01;

            // Do some &quot;heavy work&quot;
            try {
                sleep(50); // Sleep for 50 milliseconds
            } catch (InterruptedException e) {}

            // Update the UI thread-safely
            UI.getCurrent().access(new Runnable() {
                @Override
                public void run() {
                    progress.setValue(new Float(current));
                    if (current &lt; 1.0)
                        status.setValue(&quot;&quot; +
                            ((int)(current*100)) + &quot;% done&quot;);
                    else
                        status.setValue(&quot;all done&quot;);
                }
            });
        }

        // Show the &quot;all done&quot; for a while
        try {
            sleep(2000); // Sleep for 2 seconds
        } catch (InterruptedException e) {}

        // Update the UI thread-safely
        UI.getCurrent().access(new Runnable() {
            @Override
            public void run() {
                // Restore the state to initial
                progress.setValue(new Float(0.0));
                progress.setEnabled(false);

                // Stop polling
                UI.getCurrent().setPollInterval(-1);

                button.setEnabled(true);
                status.setValue(&quot;not running&quot;);
            }
        });
    }
}

// Clicking the button creates and runs a work thread
button.addClickListener(new Button.ClickListener() {
    public void buttonClick(ClickEvent event) {
        final WorkThread thread = new WorkThread();
        thread.start();

        // Enable polling and set frequency to 0.5 seconds
        UI.getCurrent().setPollInterval(500);

        // Disable the button until the work is done
        progress.setEnabled(true);
        button.setEnabled(false);

        status.setValue(&quot;running...&quot;);
    }
});
----

The example is illustrated in &lt;&lt;figure.components.progressbar.thread&gt;&gt;.

[[figure.components.progressbar.thread]]
.Doing heavy work
image::img/progressbar-thread.png[width=40%, scaledwidth=70%]

endif::web[]

[[components.progressbar.css]]
== CSS Style Rules


[source, css]
----
.v-progressbar, v-progressbar-indeterminate {}
  .v-progressbar-wrapper {}
    .v-progressbar-indicator {}
----

The progress bar has a [literal]#++v-progressbar++# base style.
The progress is an element with [literal]#++v-progressbar-indicator++# style inside the wrapper, and therefore displayed on top of it.
When the progress element grows, it covers more and more of the animated background.

The progress bar can be animated (some themes use that).
Animation is done in the element with the [literal]#v-progressbar-wrapper# style, by having an animated GIF as the background image.

In the indeterminate mode, the top element also has the
[literal]#++v-progressbar-indeterminate++# style.
The built-in themes simply display the animated GIF in the top element and have the inner elements disabled.
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.39.1</a>) at 2025-08-03 22:35:36 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
