blob: 808a4e52a9d5ff0becbe482b1e0b8830f1a6f2c6 [file] [log] [blame]
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="CACHE-CONTROL" content="NO-CACHE"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Apache Royale Blog</title><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"><link rel="stylesheet" href="/css/styles.css"><link rel="shortcut icon" href="/img/favicon.ico"></head><body class="page post" id="main"><header class="docs-header"><div class="container"><div class="topbar"><div class="topbar-left"><a href="/"><span class="site-title">Apache Royale</span></a></div><div class="topbar-center"></div><div class="topbar-right"><button class="topMenu-dropbtn"><i class="fa fa-bars"></i>&nbsp;Menu</button><ul class="topMenu"><li><a href="/features">Features</a></li><li><a href="https://apache.github.io/royale-docs/get-started">Get Started</a></li><li><a href="/download">Download</a></li><li><a href="/docs">Docs</a></li><li><a href="/blog">Blog</a></li><li><a href="https://github.com/apache/royale-asjs/wiki/Apache-Royale-Source-Code-Repositories"><i class="fa fa-github"></i> GitHub</a></li></ul></div></div><div class="post-header"><h1>Apache Royale Blog</h1><div class="post-meta"></div></div></div></header><div class="page-content"><div class="container"><article><h2 class="post-title"><a href="/blog/using-jewel-tilehorizontallayout/">Using Jewel TileHorizontalLayout</a></h2><div class="post-meta">by Carlos Rovira on August 11, 2020</div><div><p>This example shows how to use the Jewel <strong>TileHorizontalLayout</strong> in Jewel components and data-based containers to arrange child elements as tiles. The layout lets you customize the tiles' size, the gaps between tiles, and whether you want them organized by rows or columns.</p><p>This layout is modeled very closely on the <a href="https://flex.apache.org/asdoc/spark/layouts/TileLayout.html">Apache Flex Spark TileLayout</a>.</p><h2>Example structure</h2><p>We're using the <strong>Jewel UI set</strong> to build a simple interface as a placeholder for the example. We use a Jewel <strong>Card</strong> in the middle of the screen. Inside the <strong>CardPrimaryContent</strong> we add a <strong>TabBarContent</strong> to switch between a <strong>Container</strong> and a <strong>DataContainer</strong> both using the <strong>TileHorizontalLayout</strong> to display child elements as tiles. We switch between the views using a TabBar inside a <strong>CardExpandedContent</strong>.</p><blockquote><p>Use <strong>CardExpandedContent</strong> when we need the content adjusted to fit the Card borders without any gap. In our example, we want the TabBar to fill all the available space.</p></blockquote><h2>Adding the TabBar</h2><p>We declare the <strong>TabBar</strong> using an inline <strong>ArrayList</strong> as <strong>dataProvider</strong> with the data to build each <strong>TabBarButton</strong>.</p><pre><code class="language-mxml">&lt;j:CardExpandedContent&gt;
&lt;j:TabBar localId=&quot;tabbar&quot; width=&quot;100%&quot; selectedIndex=&quot;0&quot; sameWidths=&quot;true&quot;
itemRenderer=&quot;itemRenderers.TabBarVerticalIconItemRenderer&quot;&gt;
&lt;js:ArrayList&gt;
&lt;fx:Array&gt;
&lt;vos:TabBarButtonVO label=&quot;Tile Container&quot; hash=&quot;sec1&quot; icon=&quot;{FontAwesome5IconType.TH_LARGE}&quot;/&gt;
&lt;vos:TabBarButtonVO label=&quot;Tile DataContainer&quot; hash=&quot;sec2&quot; icon=&quot;{FontAwesome5IconType.TH_LIST}&quot;/&gt;
&lt;/fx:Array&gt;
&lt;/js:ArrayList&gt;
&lt;/j:TabBar&gt;
&lt;/j:CardExpandedContent&gt;
</code></pre><p>The Tabbar add two buttons to control the content that fills all available space (width is 100%). It makes both buttons the same width and puts the focus on the first one (selectedIndex = 0). The <strong>TabBarVerticalIconItemRenderer</strong> item renderer controls each button's layout. Check the full code to see details on configuring the renderer.</p><p>With this code in place we can add the content.</p><h2>Add the dual TabBarContent</h2><p>The main content is structured as follows:</p><pre><code class="language-mxml">&lt;j:CardPrimaryContent&gt;
&lt;j:TabBarContent selectedContent=&quot;{(tabbar.selectedItem as TabBarButtonVO).hash}&quot;&gt;
&lt;j:SectionContent name=&quot;sec1&quot;&gt;
&lt;j:Container width=&quot;100%&quot;&gt;
&lt;!-- Content to show as tiles--&gt;
&lt;/j:Container&gt;
&lt;/j:SectionContent&gt;
&lt;j:SectionContent name=&quot;sec2&quot;&gt;
&lt;j:DataContainer width=&quot;100%&quot; height=&quot;250&quot;&gt;
&lt;!-- Content to show as tiles--&gt;
&lt;/j:DataContainer&gt;
&lt;/j:SectionContent&gt;
&lt;/j:TabBarContent&gt;
&lt;/j:CardPrimaryContent&gt;
</code></pre><p>The TabBarContent's <strong>selectedContent</strong> is bound to the TabBar's <strong>selectedItem</strong> so when a TabBar button is selected the content changes accordingly.</p><h2>Using the tile layout in a Container</h2><p>Inside the <strong>SectionContent</strong> we add a <strong>Container</strong> configured with <strong>TileHorizontalLayout</strong>. We can add any content we want to the container, but the size of each piece will be controlled by the layout.</p><p>Since no height is provided, no scrolling will be added as the number of content items increases or decreases, and the surrounding card will grow or shrink to adapt to them.</p><p>The layout is configured with some horizontal and vertical gaps, and we want three columns by default. This means that the width of the tiles will be calculated to fill all available space, taking into account the <strong>requestedColumnCount</strong> and the gaps:</p><pre><code class="language-mxml">&lt;j:Container width=&quot;100%&quot;&gt;
&lt;j:beads&gt;
&lt;j:TileHorizontalLayout localId=&quot;thl&quot; verticalGap=&quot;6&quot;
horizontalGap=&quot;6&quot; requestedColumnCount=&quot;3&quot;/&gt;
&lt;/j:beads&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;1&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;2&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;3&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;4&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;5&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;6&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;7&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;8&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;9&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;10&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;11&quot;/&gt;
&lt;html:Div className=&quot;box&quot; text=&quot;12&quot;/&gt;
&lt;/j:Container&gt;
</code></pre><h2>Using the tile layout in a DataContainer</h2><p>Inside the <strong>SectionContent</strong> we add a <strong>DataContainer</strong> configured with the <strong>TileHorizontalLayout</strong>. As its name indicates, the content is generated dynamically based on the data in the ArrayList, and the item renderer controls the display of each tile.</p><blockquote><p>You can use other data-based containers like a <strong>List</strong> if you need more functionality like selection of items, roll-over support or keyboard accessibility.</p></blockquote><p>For this example, we limit the height of the container so the content can be hidden, and add scrolling with the <strong>ScrollingViewport</strong> bead.</p><p>Also we configure <strong>columnWidth</strong> and <strong>rowHeight</strong> so the columns will be calculated based on tile size and gaps.</p><pre><code class="language-mxml">&lt;j:DataContainer width=&quot;100%&quot; height=&quot;250&quot;
itemRenderer=&quot;itemRenderers.VerticalIconListItemRenderer&quot;&gt;
&lt;j:beads&gt;
&lt;j:ScrollingViewport/&gt;
&lt;j:TileHorizontalLayout localId=&quot;thll&quot; verticalGap=&quot;6&quot;
horizontalGap=&quot;6&quot; columnWidth=&quot;130&quot; rowHeight=&quot;70&quot;/&gt;
&lt;/j:beads&gt;
&lt;js:ArrayList&gt;
&lt;fx:Array&gt;
&lt;vos:IconListVO label=&quot;Ank&quot; icon=&quot;{FontAwesome5IconType.ANKH}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Atom&quot; icon=&quot;{FontAwesome5IconType.ATOM}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Burn&quot; icon=&quot;{FontAwesome5IconType.BURN}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Candy Cane&quot; icon=&quot;{FontAwesome5IconType.CANDY_CANE}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Fire&quot; icon=&quot;{FontAwesome5IconType.FIRE_ALT}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Duck&quot; icon=&quot;{FontAwesome5IconType.DUCK}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Cloud And Moon&quot; icon=&quot;{FontAwesome5IconType.CLOUD_MOON}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Europe&quot; icon=&quot;{FontAwesome5IconType.GLOBE_EUROPE}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Electric Guitar&quot; icon=&quot;{FontAwesome5IconType.GUITAR_ELECTRIC}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Mask&quot; icon=&quot;{FontAwesome5IconType.MASK}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Skull&quot; icon=&quot;{FontAwesome5IconType.SKULL}&quot;/&gt;
&lt;vos:IconListVO label=&quot;Spider&quot; icon=&quot;{FontAwesome5IconType.SPIDER}&quot;/&gt;
&lt;/fx:Array&gt;
&lt;/js:ArrayList&gt;
&lt;/j:DataContainer&gt;
</code></pre><h2>CardActions to control sizing at runtime</h2><p>In the example we also add some sliders to control different settings of each layout. For example, to change columnWidth we configure the following slider:</p><pre><code class="language-mxml">&lt;j:VGroup&gt;
&lt;j:Label text=&quot;columnWidth&quot;/&gt;
&lt;j:HSlider width=&quot;200&quot; value=&quot;85&quot; minimum=&quot;50&quot; maximum=&quot;150&quot;
valueChange=&quot;tabbar.selectedIndex == 0 ? thl.columnWidth = event.target.value : thll.columnWidth = event.target.value;&quot;/&gt;
&lt;/j:VGroup&gt;
</code></pre><p>We use the tabbar selectedIndex to affect the current selected content layout and avoid changing the content layout in the other tab. Check the final code example to see the rest of sliders since all are similar.</p><p>And that's all! I hope you like this layout example in Royale. As always, enjoy coding with Apache Royale!</p><h2>Where to go from here</h2><ul><li><a href="https://apache.github.io/royale-docs/features/data-binding">Apache Royale Data Binding documentation page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel">Apache Royale Jewel UI Set documentation page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel/tabbar">Jewel TabBar Royale Docs page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel/tabbarcontent">Jewel TabBarContent Royale Docs page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel/container">Jewel Container Royale Docs page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel/datacontainer">Jewel DataContainer Royale Docs page</a></li></ul><p>The result of this code snippet is the following:</p><iframe width="100%" height="600" src="/blog-examples/BE0015_Using_Jewel_TileHorizontalLayout/index.html"></iframe><p>(We're using an iframe to host the actual results of this example compilation. To see the example in a separate window click <a href="/blog-examples/BE0015_Using_Jewel_TileHorizontalLayout/index.html" target="_blank">this link</a>.)</p><p>Full project with source code can be found <a href="https://github.com/apache/royale-asjs/tree/develop/examples/blog/BE0015_Using_Jewel_TileHorizontalLayout">here</a>:</p><p><a class="btn btn-download" href="https://github.com/apache/royale-asjs/tree/develop/examples/blog/BE0015_Using_Jewel_TileHorizontalLayout"><i class="fa fa-download"></i> Project Source Code</a></p></div><h2 class="post-title"><a href="/blog/apache-royale-v0-9-7-released/">Apache Royale v0.9.7 released!</a></h2><div class="post-meta">by Carlos Rovira on May 15, 2020</div><div><p>The Apache Royale community is pleased to announce the release of <strong>Apache Royale 0.9.7</strong>.</p><p><img src="/img/blog/release-0.9.7.png" alt=""></p><p>The Apache Royale project is the next generation of the Apache Flex SDK. It lets developers use <strong>MXML</strong> and <strong>ActionScript 3</strong> to generate <strong>HTML/JS/CSS</strong> applications which can run natively in browsers. The cross-compiled code can also run on platforms like <strong>Electron</strong> or <strong>Apache Cordova</strong> (Adobe PhoneGap) to build mobile applications.</p><p>This release should be considered 'beta' quality, although <em>we're very close to a 1.0 release</em> and <em>we have many applications in production</em> at this point. The purpose of this release is to continue to gather feedback about Royale's features and the project's implementation strategies, and to recruit new contributors. We hope to grow the code base into an SDK and tool chain that delivers the highest productivity when developing applications that can run on many platforms. Beta releases, however, may not handle all production needs.</p><h2>Changes in 0.9.7:</h2><h3>Apache Royale Framework 0.9.7</h3><ul><li>Reflection support improved (supports access to custom namespaces) including improved utility methods</li><li>Added a <code>getTimer</code> emulation to Core library, similar to <code>flash.utils.getTimer</code></li><li>added <code>[RoyaleArrayLike]</code> implementation support to Royale Collections, and BinaryData</li><li>improvements to XML/E4X conformance, and memory footprint</li><li>General improvements in Bindings, including function bindings</li><li>Added new Router classes</li><li>Added AMFLocalStorage, a javascript version of the Flash runtime LSO (Local Shared Object)</li><li>Added new ItemRendererInitializer bead infrastructure to decouple better item renderers functionality</li><li>Added ToolTipRemovalWhenItemRemoved for renderers that use tooltips.</li><li>Fix bin/mxmlc and bin/compc scripts that did not understand certain default compiler options in royale-config.xml</li><li>Crux:<ul><li>Improved:<ul><li>Crux can now be used in MXRoyale and SparkRoyale applications</li></ul></li><li>New:<ul><li>Added support for using Command pattern to Crux</li><li>Added Documentation in royale-docs site</li></ul></li></ul></li><li>Graphics:<ul><li>New:<ul><li>Added new high-parity swf graphics emulation (UIGraphicBase)</li></ul></li></ul></li><li>Jewel:<ul><li>Improved:<ul><li>Massive refactors and improvments</li><li>Hierachy improved in many Jewel framework branches to make StyleUIBase the base of all components and unify APIs.</li><li>StyleUIBase now improve width and height so we can use NaN values to unset values. For JS this means return to default values.</li><li>Card: Added new subcomponents (CardHeader, CardTitle, CardPrimaryContent and CardActions)</li><li>Button: Added new unboxed and outlined styles (also to IconButton and ToggleButton)</li><li>CheckBox and RadioButton now can size the icon part</li><li>ComboBox can now confifure custom renders and supports rowCount, and fixed percent width. also popup adapts to data provider length.</li><li>List supports now variableRowHeight, scrollToIndex and can be navigated with arrow cursors (up/down)</li><li>Item Renderer: Use the new Initializer infrastructure</li><li>Remove mappers to rely on basic ones, also remove CRUD beads (Add, Remove and Update item beads)</li><li>Layouts, Group and Container supports variableRowHeight</li><li>Layouts many fixes and improvements in alignment, and now dispatch childs dispatch a &quot;sizeChanged&quot;</li><li>Viewport and ScrollingViewport refactor. Viewport has now clipContent so Container can activate/deactivate</li><li>added tabindex in many components and to Disabled bead (=-1)</li><li>Prompt beads now support changes at runtime</li><li>TabBar: fix AssignTabContent bead when change dataprovider</li><li>Jewel Themes was updated to show many visual improvements in colors and styles. Flat and Light themes are almost finished. Still Dark themes are work in progress.</li><li><a href="https://royale.apache.org/tourdejewel/">Tour De Jewel</a> was updated to show all the latest updates</li></ul></li><li>New:<ul><li>Runtime Theme Switch. Can be seen working in Tour De Jewel</li><li>StyledUIBase now adds min and max width and height properties.</li><li>Added VSlider. The original Slider is now HSlider.</li><li>Added Paddings bead</li><li>Added VContainer and HContainer for clipped content</li><li>Added DataGrid</li><li>Added ButtonBar</li><li>Added ComboBoxTrucatedText</li><li>Added DrawerFooter</li><li>Added VirtualList and VirtualComboBox to load huge amounts of data in a performant way</li><li>New colors for text and icons (lightest, light, normal, dark and darkest)</li><li>Added Jewel TodoMVC and TodoMVC with Crux examples following the TodoMVC website guidelines. Also added more blog examples.</li></ul></li></ul></li><li>Icons<ul><li>Refactored classes IIcon classes to support more icons sets</li><li>Added FontAwesome v5 support (also v4)</li><li>Icons now support Material and FontAwesome (more sets can be added)</li></ul></li><li>SVG:<ul><li>Fixed SVGImage when using Maven</li></ul></li><li>Network:<ul><li>Improved:<ul><li>URLLoader now respects contentType passed in via URLRequest.</li></ul></li><li>New:<ul><li>Added URLVariables emulation</li></ul></li></ul></li><li>MXRoyale:<ul><li>Improved:<ul><li>mx.utils.ObjectUtil – improved parity</li><li>mx.net.SharedObject – improved parity</li><li>add support for legacy HttpService decoding format</li><li>Fixes in mx.messaging for polling support, mx.external.ExternalInterface</li></ul></li><li>New:<ul><li>mx.net.SharedObjectJSON – new alternative</li></ul></li></ul></li><li>Maven:<ul><li>Massive improvements</li><li>Now Maven can generate a valid distribution (SDK) to use in any IDE (tested on VSCode and Moonshine) distribution can be JS only</li><li>SASS generation is now separated from main build to a profile to save lots of time when no need to build themes</li></ul></li><li>RoyaleUnit:<ul><li><code>[Test(async)]</code> may be used to define asynchronous tests</li><li><code>[BeforeClass]</code> and <code>[AfterClass]</code> metadata must be added to static methods</li><li><code>[Test]</code> metadata supports an 'expected' attribute to expect a thrown exception</li><li>Fixed incorrect order of expected and actual values in assert messages</li></ul></li><li>RoyaleUnitUI: An optional UI to display the results of RoyaleUnit tests</li><li>Dozens of bugs reported, investigated, and squashed. For details of closed bug reports see <a href="https://github.com/apache/royale-asjs/issues?q=is%3Aissue+is%3Aclosed">GitHub Issues list</a>.</li></ul><p>Updates to the <em>RELEASE_NOTES</em> made after this file was packaged into the release artifacts can be found here:</p><p><a href="https://github.com/apache/royale-asjs/wiki/Release-Notes-0.9.7">https://github.com/apache/royale-asjs/wiki/Release-Notes-0.9.7</a></p><h3>Apache Royale Compiler 0.9.7</h3><ul><li>Definitions containing <code>[JSModule]</code> with a custom module name are no longer required to use strict camelCase naming scheme.</li><li>Added Flex emulation RPC WebService partial support</li><li>Fix add event handler code in renderers and inline Components</li><li>(SWF/JS) Added support for <code>[RoyaleArrayLike]</code> metadata-driven support for proxying compile-time numeric-typed array index access to get/set method calls and also specific for-in/for-each-in loop support.</li><li>(JS) Compiler updates to support more e4X variations/scenarios, including 'use namespace' and 'default xml namespace' directives</li><li>(JS) Compiler updates to address custom namespace-related output, and reflection support</li><li>(JS) Compiler updates to output more compact Reflection data</li><li>Fixed a compiler memory leak that was occurring over multiple compilations</li><li>Fixes in bindable code generation for accessors, and in bindable function generation for swf</li><li>Fixed <code>-show-binding-warnings=false</code> option to switch off binding warnings</li><li>Maven: Many fixes, improvements and Updates</li><li>Support for Maven distribution (Create SDK with Maven)</li><li>(JS) Prevent renaming of public variables in release builds so that they may be set from MXML.</li><li>(JS) Fix conflict between methods of the same name in superclass and subclass, where the superclass method is private and the subclass method is public.</li><li>(JS) Added <code>-jsx-factory</code> compiler option to customize the factory method used in code generated from [JSX].</li><li>(JS) Added <code>-inline-constants</code> compiler option that optionally replaces references to contants with their value when the value is a primitive (like numeric, boolean, or string).</li><li>(SWF/JS) Added <code>-warn-this-within-closure</code> compiler option that controls whether the compiler emits warnings when referencing <code>this</code> in closures or anonymous functions.</li><li>(SWF/JS) Added <code>-strict-identifier-names</code> compiler option to make the compiler emit errors when using certain keywords as identifiers, to match the old behavior of the Flex SDK compiler.</li><li>(SWF/JS) Fix metadata attributes being ignored if they did not have a value. Example: async was ignored in <code>[Test(async)]</code>.</li><li>(SWF/JS) Fix path resolving error when specifying a source file with ./ or .\ on the command line.</li><li>(SWF/JS) Fix <code>[ArrayElementType]</code> being ignored when setting the <code>[DefaultProperty]</code> in MXML.</li><li>(SWF) Fix mxmlc and compc scripts in the bin folder that didn't work from the command line.</li><li>(SWF/JS) Fix incorrect resolving of a property with a different namespace than the parent element in MXML. Properties must have the same namespace as the component, just like in Flex.</li><li>(SWF/JS) Fix missing error for values that cannot be parsed as text in MXML.</li><li>(JS) Fix stripped end quotes from strings in data binding expressions in MXML.</li><li>(Maven) Added missing MXML manifest for core language types like Object, Array, Number, String, Boolean, etc.</li><li>(JS) Fixed null reference error on source map generation with certain folder hierarchies.</li><li>(JS) Fixed lost UTF-8 encoding when using remove-circulars.</li><li>(SWF/JS) Fix missing error when setting private/inaccessible property in MXML.</li><li>(JS) Fix &quot;missing var keyword&quot; warning from Closure compiler for type definitions.</li><li>(SWF/JS) Fix missing error for calling a getter as a function (similar to attempting to call a variable as a function) when it is the wrong type.</li><li>(JS) Fix missing . in generated JS when using static getter/setter in a custom namespace.</li></ul><p>For additional information on recent issues that have been closed, see <a href="https://github.com/apache/royale-compiler/issues?q=is%3Aissue+is%3Aclosed">Github Issues List</a></p><p>You can download a <a href="https://royale.apache.org/download/">binary distribution</a>, the <a href="https://royale.apache.org/source-code/">source code</a> or browse our <a href="https://github.com/apache/royale-asjs/wiki/Apache-Royale-Source-Code-Repositories">GitHub repositories</a>. If you're a NPM user you can check <a href="https://www.npmjs.com/org/apache-royale">Apache Royale at NPM</a>.</p><p>As well, you can help us <a href="https://github.com/apache/royale-asjs/issues">filing bug reports for issues you encounter in the framework</a> or <a href="https://github.com/apache/royale-compiler/issues">compiler</a>.</p><p>For questions about how to use Royale, send email to <a href="users@royale.apache.org">mailto:users@royale.apache.org</a>. For questions and feedback on the development of the source code in the release, send email to <a href="mailto:dev@royale.apache.org">dev@royale.apache.org</a>.</p><p>Enjoy! 🙂</p></div><h2 class="post-title"><a href="/blog/working-with-vector-graphics/">Working with vector graphics</a></h2><div class="post-meta">by Carlos Rovira on March 29, 2020</div><div><p>This example shows some ways you can work with vector graphics in Apache Royale. Since Royale draws in part from the sources of Flash and Flex technologies, you'll find that <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html">the powerful Flash drawing API</a> is supported for JavaScript and SWF applications. On the other hand, Apache Royale also supports use of <a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics">SVG graphics</a>.</p><p>In this example we create an Erlenmeyer flask, a measuring and mixing container for laboratories, that we can fill with some kind of strange green fluid. We can change the level of the fill with a Jewel <strong>HSlider</strong>, and use a <strong>ToggleButton</strong> to show or hide an indicator of the maximum level the liquid can reach. The bottle is be a static SVG shape and the fluid is drawn at runtime as the code responds when the slider value changes.</p><h2>Example structure</h2><p>We're using the <strong>Jewel UI set</strong> to build a simple interface as a placeholder for the example. We use a Jewel <strong>Card</strong>; the Jewel <strong>HorizontalCenteredLayout</strong> centers the card in the card on both axes.</p><p>As usual, the <strong>Card</strong> has three sections: a <strong>CardHeader</strong> (with the title), a <strong>CardPrimaryContent</strong> (that holds the bottle) and a <strong>CardActions</strong> (with some controls).</p><p>This is the main structure:</p><pre><code class="language-mxml">&lt;j:Card width=&quot;460&quot; height=&quot;680&quot;&gt;
&lt;j:CardHeader&gt;
&lt;html:H3 text=&quot;Working with vector graphics&quot; className=&quot;primary-normal&quot;/&gt;
&lt;/j:CardHeader&gt;
&lt;j:CardPrimaryContent itemsHorizontalAlign=&quot;itemsCentered&quot;&gt;
&lt;!-- Here will have the bottle --&gt;
&lt;/j:CardPrimaryContent&gt;
&lt;j:CardActions itemsHorizontalAlign=&quot;itemsRight&quot; itemsVerticalAlign=&quot;itemsCentered&quot;&gt;
&lt;j:BarSection width=&quot;50%&quot;&gt;
&lt;!-- Here will go the ToggleButton --&gt;
&lt;/j:BarSection&gt;
&lt;j:BarSection width=&quot;50%&quot; itemsHorizontalAlign=&quot;itemsRight&quot;&gt;
&lt;!-- Here will go the Slider --&gt;
&lt;/j:BarSection&gt;
&lt;/j:CardActions&gt;
&lt;/j:Card&gt;
</code></pre><p>With this code in place we can…</p><h2>Create the bottle</h2><p>We use SVG graphics to assemble the flask, and <strong>ActionScript 3</strong> code using the powerful <strong>Flash drawing API</strong> to create and manage the liquid. We're using both to show you both options so you have more weapons in your arsenal.</p><p>For the flask, I created three SVG files using a design tool. You can use whatever tool you prefer to draw vector art and export it in SVG format. I used <a href="https://affinity.serif.com/">Affinity Designer</a> software to create it since I think it's one of the best professional and modern tools available today. But many other free, open source and commercial options are available, so choose whatever you want.</p><p>The flask's three files are: A <strong>mask</strong>, a <strong>shade</strong> (with some reflections and gradients) and the <strong>main flask shape</strong>. I loaded the files with the <strong>svg:Image</strong> Royale component. Then I added a red indicator line coded In SVG directly in Royale to show that option with <strong>svg:Rect</strong>. Finally the fluid uses the <strong>UIGraphicsBase</strong> class that lets you work with the Flash drawing API.</p><p>I added all the parts to a Jewel <strong>Container</strong> so I can position them in relation to each other as layers. The Container clips the content so things that fall outside the container boundaries are hidden.</p><p>You can see all the pieces in perspective in the following image:</p><p><img src="/img/blog/bottle-layers-perspective.png" alt=""></p><p>Here is the final code of the <strong>Container</strong> that composes all the graphic parts:</p><pre><code class="language-mxml">&lt;j:Container localId=&quot;fgShape&quot; width=&quot;400&quot; height=&quot;500&quot;&gt;
&lt;!-- liquid --&gt;
&lt;js:UIGraphicsBase localId=&quot;bgShape&quot; width=&quot;400&quot; height=&quot;500&quot;/&gt;
&lt;!-- rule --&gt;
&lt;j:Group&gt;
&lt;svg:Rect localId=&quot;rule&quot; x=&quot;180&quot; y=&quot;{bgShape.height - rule.height}&quot; width=&quot;6&quot; height=&quot;350&quot;&gt;
&lt;svg:fill&gt;
&lt;js:SolidColor color=&quot;#ff0000&quot; alpha=&quot;.5&quot;/&gt;
&lt;/svg:fill&gt;
&lt;/svg:Rect&gt;
&lt;/j:Group&gt;
&lt;!-- fill mask --&gt;
&lt;svg:Image src=&quot;assets/bottle-mask.svg&quot; width=&quot;400&quot; height=&quot;500&quot;/&gt;
&lt;!-- inner shade --&gt;
&lt;svg:Image src=&quot;assets/bottle-shade.svg&quot; width=&quot;400&quot; height=&quot;500&quot;/&gt;
&lt;!-- main shape --&gt;
&lt;svg:Image src=&quot;assets/bottle-main.svg&quot; width=&quot;400&quot; height=&quot;500&quot;/&gt;
&lt;/j:Container&gt;
</code></pre><p>Notice that the fluid is declared first so the other shapes can hide the fluid that is outside the flask shape.</p><h2>Fluid controls</h2><p>To provide some interactivity we add a <strong>ToogleButton</strong> and an <strong>HSlider</strong>. The button lets you show and hide the indicator line; move the slider to change the fluid level from empty to full.</p><p>The <strong>ToogleButton</strong> has the following code:</p><pre><code class="language-mxml">&lt;j:ToggleButton localId=&quot;ruleVisibility&quot;
outlined=&quot;true&quot; emphasis=&quot;emphasized&quot;
text=&quot;Hide Rule&quot; selectedText=&quot;Show Rule&quot; selected=&quot;true&quot;&gt;
&lt;j:icon&gt;
&lt;js:ToggleFontIcon text=&quot;{MaterialIconType.VISIBILITY_OFF}&quot; selectedText=&quot;{MaterialIconType.VISIBILITY}&quot; material=&quot;true&quot;/&gt;
&lt;/j:icon&gt;
&lt;/j:ToggleButton&gt;
</code></pre><p>It uses an outlined style with emphasized coloring, and <a href="https://www.material.io/resources/icons/?style=baseline">material icons</a> and texts for both selected and unselected states.</p><h2>Show and Hide the indicator with binding</h2><p>We control the visibility of the red indicator line with the <strong>data binding</strong> Royale feature:</p><p>First add <strong>ApplicationDataBinding</strong> to the application beads to make Royale support binding at that level (Remember that Royale is <a href="https://apache.github.io/royale-docs/features/payg">PAYG</a>, so we only add code when it is really necessary instead of adding lots of code that you probably will never use to every component).</p><p>Then add the binding to the <strong>Group</strong> that holds the rule.</p><pre><code class="language-mxml">&lt;!-- rule --&gt;
&lt;j:Group visible=&quot;{ruleVisibility.selected}&quot;&gt;
</code></pre><p>When you run the application, click the button to show and hide the red indicator.</p><h2>Add the slider</h2><p>We finish the action controls part by adding a label and a slider in the last <strong>BarSection</strong> of the <strong>CardActions</strong>. The slider lets you change the fluid level.</p><pre><code class="language-mxml">&lt;j:Label text=&quot;Slide to fill&quot;/&gt;
&lt;j:HSlider localId=&quot;slider&quot; value=&quot;0&quot; minimum=&quot;0&quot; maximum=&quot;500&quot;/&gt;
</code></pre><h2>Drawing the fluid</h2><p>Using the drawing API in Royale is easy, and well-supported by both <strong>JavaScript</strong> and <strong>SWF</strong>. We get the <strong>Graphics</strong> instance of the <strong>UIGraphicsBase</strong> object in the following way:</p><pre><code class="language-as3">var g:Graphics = Graphics.getInstanceFor(bgShape);
</code></pre><p>Now we can use the graphics object to invoke drawing functions like <strong>moveTo</strong>, <strong>lineTo</strong>, and more.</p><p>To draw the fluid we use the following function using fills, lines and quadratic bezier curves:</p><pre><code class="language-as3">/**
* Draw the liquid to fill the bottle
*/
private function drawLiquid(g:Graphics, color:Number, alpha:Number, x:int, y:int, width:int, height:int, wave:int):void {
if(y &gt; height)
y = height;
g.beginFill(color, alpha);
g.moveTo(x, height);
g.lineTo(x, y);
g.curveTo(width / 4, y - wave, width / 2, y);
g.lineTo(width / 2, y)
g.curveTo(width * 3 / 4, y + wave, width, y);
g.lineTo(width, height);
g.lineTo(x, height);
g.endFill();
}
</code></pre><p>Then to join all the pieces we add a <strong>valueChange</strong> event handler to the <strong>HSlider</strong>:</p><pre><code class="language-mxml">&lt;j:HSlider localId=&quot;slider&quot; value=&quot;0&quot; minimum=&quot;0&quot; maximum=&quot;500&quot; valueChange=&quot;changeFill(event)&quot;/&gt;
</code></pre><p>The <strong>changeFill</strong> function is the following:</p><pre><code class="language-as3">/**
* Fill the bottle
*/
private function changeFill(event:ValueChangeEvent):void {
var g:Graphics = Graphics.getInstanceFor(bgShape);
var newHeight:Number = transformValueFromRange(slider.value, slider.minimum, slider.maximum, 0, rule.height);
var newY:Number = fgShape.height - newHeight;
g.clear();
drawLiquid(g, liquidColor, .5, 0, newY, 400, 500, -15);
drawLiquid(g, liquidColor, 1, 0, newY, 400, 500, 30);
}
</code></pre><p>When we change the <strong>HSlider</strong> position, the code calls the function, gets the graphic object, calculates the new height value based on the current container height (transforming ranges), clears all drawings and redraws two different liquids with some displacement on X and change on the wave length with the new values.</p><p>And that's all! I hope you like this drawing feature in Royale. You'll be able to do many creative things in your Royale applications with it!</p><p>As always, enjoy!</p><h2>Where to go from here</h2><ul><li><a href="https://apache.github.io/royale-docs/features/data-binding">Apache Royale Data Binding documentation page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel">Apache Royale Jewel UI Set documentation page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel/hslider">Jewel HSlider Royale Docs page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel/card">Jewel Card Royale Docs page</a></li></ul><p>The result of this code snippet is the following:</p><iframe width="100%" height="800" src="/blog-examples/BE0014_Working_with_vector_graphics/index.html"></iframe><p>(We're using an iframe to host the actual results of this example compilation. To see the example in a separate window click <a href="/blog-examples/BE0014_Working_with_vector_graphics/index.html" target="_blank">this link</a>.)</p><p>Full project with source code can be found <a href="https://github.com/apache/royale-asjs/tree/develop/examples/blog/BE0014_Working_with_vector_graphics">here</a>:</p><p><a class="btn btn-download" href="https://github.com/apache/royale-asjs/tree/develop/examples/blog/BE0014_Working_with_vector_graphics"><i class="fa fa-download"></i> Project Source Code</a></p></div><a class="btn btn-quiet" href="/blog/"><i class="fa fa-arrow-left"></i> Newer Posts</a> <a class="btn btn-quiet" href="/blog/page/3/">Older Posts <i class="fa fa-arrow-right"></i></a></article></div></div><footer class="footer"><div class="footer-row"><div class="footer-column"><ul class="footer-list"><li class="apacheroyale"><a href="/">Apache Royale</a></li><li><a href="/">Home</a></li><li><a href="/features">Features</a></li><li><a href="/download">Download</a></li><li><a href="/ides">IDEs and Editors</a></li><li><a href="/showcase">Showcase</a></li><li><a href="/blog">Blog</a></li><li><a href="/team">Team</a></li><li><a href="/thanks-to">Thanks To</a></li><li><a href="https://apache.org/logos/#royale"><i class="fa fa-external-link-square"></i> Logos</a></li><li><a href="https://www.apache.org/licenses/"><i class="fa fa-external-link-square"></i> Apache License v2.0</a></li></ul></div><div class="footer-column"><ul class="footer-list"><li class="documentation"><a href="/docs">Documentation</a></li><li><a href="https://apache.github.io/royale-docs/get-started">Get Started</a></li><li><a href="/docs">Docs</a></li><li><a href="/asdoc">API Reference</a></li><li><a href="https://github.com/apache/royale-asjs/wiki"><i class="fa fa-github"></i>Wiki</a></li><li><a href="https://stackoverflow.com/questions/tagged/apache-royale"><i class="fa fa-stack-overflow"></i> StackOverFlow Tag</a></li></ul><ul class="footer-list"><li class="community"><a href="/get-involved">Community</a></li><li><a href="/get-involved">Get Involved</a></li><li><a href="/mailing-lists">Mailing Lists</a></li><li><a href="/faq">FAQ</a></li></ul><ul class="footer-list"><li class="development"><a href="/source-code">Development</a></li><li><a href="https://github.com/apache/royale-asjs/wiki/Apache-Royale-Source-Code-Repositories"><i class="fa fa-github"></i> Github</a></li><li><a href="https://github.com/apache/royale-asjs/issues"><i class="fa fa-github"></i> Issues</a></li><li><a href="/source-code"><i class="fa fa-code"></i> Source Code</a></li></ul></div><div class="footer-column"><ul class="footer-list"><li class="social_t">Social</li><li><a href="https://twitter.com/apacheroyale"><i class="fa fa-twitter"></i> Twitter</a></li><li><a href="https://facebook.com/ApacheRoyaleSDK/"><i class="fa fa-facebook"></i> Facebook</a></li><li><a href="https://www.linkedin.com/groups/12118437"><i class="fa fa-linkedin"></i> LinkedIn</a></li><li><a href="/feed/index.xml"><i class="fa fa-rss"></i> RSS</a></li></ul><ul class="footer-list"><li class="apache"><a href="https://www.apache.org/">Apache</a></li><li><a href="https://www.apache.org/"><i class="fa fa-external-link-square"></i> Apache</a></li><li><a href="https://www.apache.org/foundation/contributing.html"><i class="fa fa-external-link-square"></i> Donations</a></li><li><a href="https://www.apache.org/events/current-event"><i class="fa fa-external-link-square"></i> Events</a></li><li><a href="https://www.apache.org/foundation/sponsorship.html"><i class="fa fa-external-link-square"></i> Sponsorship</a></li><li><a href="https://www.apache.org/foundation/thanks.html"><i class="fa fa-external-link-square"></i> Thanks</a></li><li><a href="https://www.apache.org/security/"><i class="fa fa-external-link-square"></i>Security</a></li></ul></div><div class="aboutusdiv"><p class="aboutus">About Us</p><p class="aboutus_p"><img class="aboutus-logo" src="/img/apache-royale-logo-footer-circle-grey.svg"><a href="/" class="aboutus_a">Apache Royale™</a> is a highly productive open source application technology for building expressive frontend applications that outputs to different formats and deploy consistently on all major browsers, desktops and devices.</p><p><img class="aboutus-apache-logo" src="/img/Apache_PoweredBy.svg"> <a href="/" class="aboutus_a">Apache Royale™</a>, <a href="https://www.apache.org" class="aboutus_a">Apache™</a> and the <a href="https://www.apache.org/foundation/press/kit/" class="aboutus_a">Apache feather logo™</a> are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners. Read more about our privacy policy on our <a href="/privacy-policy">Privacy Policy page</a>.</p></div></div><div class="asf">Copyright &copy; 2017-2022 <a href="https://www.apache.org">The Apache Software Foundation</a>, Licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a></div></footer></body></html>