<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>User Interface &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/user-interface/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Wed, 07 May 2025 14:28:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Year of Code 2025: April Project, User Interface</title>
		<link>https://blog.xojo.com/2025/04/08/year-of-code-2025-april-project-user-interface/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Tue, 08 Apr 2025 15:30:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Year of Code]]></category>
		<category><![CDATA[#YearofCode]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[Listbox]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[UI-Design]]></category>
		<category><![CDATA[User Interface]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14788</guid>

					<description><![CDATA[April&#8217;s Year of Code theme is all about a great User Interface, I decided to focus on refining the user experience of an existing application.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>April&#8217;s Year of Code theme is all about a great User Interface, I decided to focus on refining the user experience of an existing application. My project involves a user interface revamp of the familiar built-in ToDo desktop app example provided with Xojo.</p>



<p>The goal wasn&#8217;t to add new features but to explore how applying thoughtful UI design principles can significantly enhance the look and feel of an application, making it more visually appealing and cohesive.</p>



<p>Here are some of the key aspects of the UI revamp:</p>



<ul class="wp-block-list">
<li><strong>Design System Foundation:</strong>&nbsp;I started by establishing a basic design system. This involved defining core visual elements to ensure consistency across the entire application interface.</li>



<li><strong>Typography Definition:</strong>&nbsp;Specific styles were defined for how titles and standard text should appear. This helps create a clear visual hierarchy and improves readability.</li>



<li><strong>Consistent Color Palette:</strong>&nbsp;A specific set of colors (Light &amp; Dark mode) was chosen and implemented throughout the project, contributing to a unified and more polished look.</li>



<li><strong>Refined ListBox Appearance:</strong>&nbsp;The standard&nbsp;DesktopListBox&nbsp;control received some visual tweaks to better align with the overall updated aesthetic.</li>
</ul>



<p>The aim was to demonstrate how focusing on UI details can elevate even a simple example application.</p>



<p>Here’s a glimpse of the revamped ToDo app:</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="602" height="452" data-id="14792" src="https://blog.xojo.com/wp-content/uploads/2025/04/ToDoOrig-1.jpg" alt="" class="wp-image-14792" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/ToDoOrig-1.jpg 602w, https://blog.xojo.com/wp-content/uploads/2025/04/ToDoOrig-1-300x225.jpg 300w" sizes="(max-width: 602px) 100vw, 602px" /></figure>



<figure class="wp-block-image size-large"><img decoding="async" width="602" height="584" data-id="14793" src="https://blog.xojo.com/wp-content/uploads/2025/04/ToDoFresh-1.jpg" alt="" class="wp-image-14793" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/ToDoFresh-1.jpg 602w, https://blog.xojo.com/wp-content/uploads/2025/04/ToDoFresh-1-300x291.jpg 300w" sizes="(max-width: 602px) 100vw, 602px" /></figure>
</figure>



<p>You can find the complete source code for this UI-enhanced <a href="https://github.com/xolabsro/ToDoFresh" data-type="link" data-id="https://github.com/xolabsro/ToDoFresh" target="_blank" rel="noreferrer noopener">ToDo app project on GitHub</a>. </p>



<p>Stay tuned for more exciting projects as we continue our Year of Code 2025 journey!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>Year of Code Project</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/">Year of Code: Kickoff</a></li>



<li><a href="https://blog.xojo.com/2025/01/15/year-of-code-2025-january-project/" target="_blank" rel="noreferrer noopener">January Project: Desktop Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/year-of-code-2025-january-project-sharing/83927" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/02/11/year-of-code-2025-february-project/">February Project: Database Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/2025-year-of-code-february" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/03/05/year-of-code-2025-march-project-web-apps/">March Project: Web Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-march/84474?u=alyssa_foley">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/04/08/year-of-code-2025-april-project-user-interface/">April Project: User Interface</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-april-user-interface/84926">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/05/07/year-of-code-2025-may-project-mobile-apps/">May Project: Mobile Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-may-is-mobile/85272">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/06/10/year-of-code-2025-june-project-cross-platform-code-class/">June Project: Code Sharing</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-june-is-code-sharing/85612">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/07/10/year-of-code-2025-july-project-charting/">July Project: Charting</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-july-is-charting/85896">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/08/07/year-of-code-2025-august-project-console-apps/">August Project: Console Apps</a> | <a href="https://forum.xojo.com/t/august-2025-year-of-code-console-apps/86203">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/09/08/year-of-code-2025-september-project-games/">September Project: Games</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-septgamer">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/10/13/year-of-code-2025-october-project-multi-platform-communication/">October Project: Multi-Platform</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-october-multi-platform-communication/86717">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/11/10/year-of-code-2025-november-project-pdf-postcard-generator/">November Project: PDF</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-november-pdf/86969">Forum Discussion</a></li>
</ul>



<p><strong>How to Play:</strong></p>



<p>Each month we&#8217;ll announce a new theme and share an example project of our own. Share your projects to the Xojo Forum thread for that month via GitHub (all the links you need are posted above ↑ ). Learn how to use <a href="https://blog.xojo.com/2024/04/02/using-xojo-and-github/">Xojo and GitHub</a>.</p>



<p><strong>The Prizes:</strong></p>



<p>Monthly winners get $100 at the Xojo store. Every month you submit a project is another chance to win the grand prize. The grand prize is $250 cash plus a Xojo Pro license and a year of GraffitiSuite and will be announce in December. Learn more about the <a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/#prizes">prizes</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Use AndroidMobileUserControl to Create Custom Controls</title>
		<link>https://blog.xojo.com/2025/03/25/use-androidmobileusercontrol-to-create-custom-controls/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 15:30:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[2025r1]]></category>
		<category><![CDATA[Control]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14637</guid>

					<description><![CDATA[Xojo for Android has robust Declare and Library support that allows you to call into many native Android libraries and frameworks. With the newly added&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo for Android has robust <a href="https://blog.xojo.com/2024/10/01/android-declare-and-library-enhancements/">Declare and Library support</a> that allows you to call into many native Android libraries and frameworks. With the newly added AndroidMobileUserControl you can also create your own native UI controls as well.</p>



<p>This control is available in the Xojo Library panel and works similarly to iOSMobileUserControl: drag it onto a layout and implement the CreateView event.</p>



<pre class="wp-block-code"><code>Declare Function Button Lib "Kotlin" Alias "android.widget.Button(context as android.content.Context)" (context As Ptr) As Ptr

Var bp As Ptr = Button(App.AndroidContextHandle)

Return bp</code></pre>



<p>The above code uses a Declare to create a native Button and returns it so that it can be displayed in a layout.</p>



<p>By using AndroidMobileUserControl and Declares to access the Android UI library, you can create your own UI controls. I look forward to seeing what the community creates!</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Spotlight On: GraffitiSuite</title>
		<link>https://blog.xojo.com/2024/06/13/spotlight-on-graffitisuite/</link>
		
		<dc:creator><![CDATA[Xojo]]></dc:creator>
		<pubDate>Thu, 13 Jun 2024 16:00:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[GraffitiSuite]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Spotlight On]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13114</guid>

					<description><![CDATA[GraffitiSuite is a series of user interface components for Xojo developers. With a powerful data grid component for web, an extensive WYSIWYG HTML content editor, and beautiful animated in-window modal popups for Desktop, GraffitiSuite classes have helped people make stunning UIs for their Xojo-made apps since 2003. ]]></description>
										<content:encoded><![CDATA[
<p><em>Spotlight On posts focus on Xojo community members. We&#8217;ll use this space to tell the stories of people using Xojo, share amazing Xojo-made apps and spread awareness of community resources. If you have an app, a project or a person you want to see featured in Spotlight On, <a href="mailto:hello@xojo.com">tell us about it</a>!</em></p>



<p>GraffitiSuite is a series of user interface components for Xojo developers. With a powerful data grid component for web, an extensive WYSIWYG HTML content editor, and beautiful animated in-window modal popups for Desktop, GraffitiSuite classes have helped people make stunning UIs for their Xojo-made apps since 2003. Anthony Cyphers, GraffitiSuite&#8217;s founder, is a well-known name in the Xojo community and a Xojo MVP; and he volunteered to be our first <em>Spotlight On</em> guest.&nbsp;GraffitiSuite is offering 10% off this month only! <a href="https://xojo.com/store/addons/graffitisuite.php">Use coupon code SPOTGS10</a> in June go get 10% off GraffitiSuite.</p>



<h2 class="wp-block-heading">10 Questions with Anthony Cyphers of GraffitiSuite</h2>



<h3 class="wp-block-heading">Mac, Windows or Linux?</h3>



<p>Mac, primarily, but I&#8217;m comfortable pretty much anywhere since I tend to have a set OS for specific things. macOS for work, Windows for play, Linux for servers. I keep multiple machines for each hanging around here.</p>



<h3 class="wp-block-heading">What do you wish more people would ask you about when it comes to GraffitiSuite?</h3>



<p>I wish people would show me their project and ask how GraffitiSuite can help them more.</p>



<h3 class="wp-block-heading">How would you explain your most recent project to a 5 year old?</h3>



<p>I make pretty things that help people use computers.</p>



<h3 class="wp-block-heading">What&#8217;s next on your <em>Learn Next</em> list?</h3>



<p>I&#8217;ve been deep in TypeScript for the last six months &#8212; and enjoying it &#8212; expanding from my JavaScript skills. The plan is to continue that journey and use it to augment Xojo Web as much as I can. This means rewriting some Xojo Web components with more modern, useable, performant and attractive controls.</p>



<h3 class="wp-block-heading">When do you think of solutions for big bugs? </h3>



<p>Usually when I&#8217;m trying (and failing) to sleep or when watching something on TV that I&#8217;m really not paying any attention to.</p>



<h3 class="wp-block-heading">What programming moments made you think &#8220;Wow, I love my job so much.&#8221;</h3>



<p>That feeling of triumph when you spend an inordinate amount of time working on an idea without doing any actual testing, then you hit &#8220;Run&#8221; and it just works. As though the stars aligned in that moment to say &#8220;Yeah, you can have this one, but the next one will be harder&#8221; &#8212; and it usually is.</p>



<h3 class="wp-block-heading">What&#8217;s something that has surprised you about coding in the last 10 years?</h3>



<p>Meh. Not much.</p>



<h3 class="wp-block-heading">What&#8217;s a cool piece of software more people should know about?</h3>



<p>The obvious answer would be Xojo, but I&#8217;m also very impressed with a lot of software that I use. And, in keeping with the Xojo theme:</p>



<ul class="wp-block-list">
<li><a href="https://strawberrysw.com/versiontracker/">Version Tracker from Tim Parnell</a> immediately springs to mind as an indispensable part of my toolkit.</li>



<li><a href="https://www.stretchedout.com/yaxew/">Apple Profile Triage from Greg O&#8217;Lone</a> has saved me from some headaches.</li>



<li><a href="https://ricardocruz.gumroad.com/">Beauty Shot by Ricardo Cruz</a> is wonderful for tweaking screenshots.</li>
</ul>



<h3 class="wp-block-heading">What&#8217;s the coolest thing you worked on recently?</h3>



<p>I&#8217;d have to say it&#8217;s my web application firewall (WAF) for Xojo Web called GraffitiFirewall. I spent some time reading white papers, tutorials, specs, and just playing with other implementations. I&#8217;m really happy with how it&#8217;s turned out and excited to add more features over time that may help protect Xojo users&#8217; web apps. I work on a lot in a given week, both new and old stuff, but this one feels right.</p>



<h3 class="wp-block-heading">Music or no music while coding?</h3>



<p>Doesn&#8217;t matter. It&#8217;s all background noise. I often stream an old TV show like The X-Files, Law &amp; Order, The Big Bang Theory, or Adventures of the Gummi Bears.</p>



<p>Thank you to Anthony Cyphers for answering our questions and for being a rock in the Xojo community. If you want to learn more about what GraffitiSuite can do for you, visit <a href="https://graffitisuite.com/">graffitisuite.com</a>. And take 10% off in June with coupon code <a href="https://xojo.com/store/addons/graffitisuite.php">SPOTGS10</a>.</p>



<p><em>Anthony G. Cyphers is the Lead Developer and Sole Proprietor of </em><a href="https://graffitisuite.com/" target="_blank" rel="noreferrer noopener"><em>GraffitiSuite Solutions</em></a><em>, and has been providing custom Xojo components and contract development since 2003 and is a Xojo MVP.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Popovers for Xojo Desktop, Web and iOS</title>
		<link>https://blog.xojo.com/2024/03/26/popovers-for-xojo-desktop-web-and-ios/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 26 Mar 2024 15:27:47 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[2024r1]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Popovers]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12707</guid>

					<description><![CDATA[Starting with Xojo 2024r1 there's a new Window type in Xojo's UI/UX bag: Popovers. Popovers are kind of a Modal window with a more transient behavior and associated with a Parent control. A Popover will display the chosen content or layout, the same as when you design the user interface of a window or a Container control that will be included as part of another more complex design or displayed at runtime.]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2024r1 there&#8217;s a new Window type in Xojo&#8217;s UI/UX bag: Popovers. Popovers are kind of a Modal window with a more transient behavior and associated with a Parent control. A Popover will display the chosen content or layout, the same as when you design the user interface of a window or a Container control that will be included as part of another more complex design or displayed at runtime.</p>



<span id="more-12707"></span>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img decoding="async" width="1024" height="558" src="https://blog.xojo.com/wp-content/uploads/2024/03/Popover-1024x558.png" alt="" class="wp-image-12708" srcset="https://blog.xojo.com/wp-content/uploads/2024/03/Popover-1024x558.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/03/Popover-300x164.png 300w, https://blog.xojo.com/wp-content/uploads/2024/03/Popover-768x419.png 768w, https://blog.xojo.com/wp-content/uploads/2024/03/Popover-1536x837.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/03/Popover-2048x1116.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>And what do we mean by the transitory character of Popover windows? Well, and here comes one of the first differences from Modal windows. When a Popover is visible and the user clicks or taps on any other element of the graphical interface not contained in the Popover itself it will close, hence transitory. So, you don&#8217;t have to include the typical &#8220;Close window&#8221; button in a Popover (though you can), since it will close when the user clicks outside of it, i.e. when the Popover loses focus.</p>



<h3 class="wp-block-heading">Where are the Popover Window Contents?</h3>



<p>Where do you define the content displayed in a Popover window? While in your Web app, you can do it on any Container control added to the project. In the case of Desktop and iOS apps, you can do it on either the designs of a Container Control or any Window or Screen added to the project.</p>



<p>For example, here you can see that the content shown as a Popover in the previous screenshot is actually that of a Window (Window2) added to the project:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="558" src="https://blog.xojo.com/wp-content/uploads/2024/03/PopoverUI-1024x558.png" alt="" class="wp-image-12709" srcset="https://blog.xojo.com/wp-content/uploads/2024/03/PopoverUI-1024x558.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/03/PopoverUI-300x163.png 300w, https://blog.xojo.com/wp-content/uploads/2024/03/PopoverUI-768x418.png 768w, https://blog.xojo.com/wp-content/uploads/2024/03/PopoverUI-1536x837.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/03/PopoverUI-2048x1116.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>This introduces additional flexibility allowing your app&#8217;s logic to decide when to display a Window or Container instance as you have been doing until now, or display it as a Popover.</p>



<h3 class="wp-block-heading">Showing a Popover</h3>



<p>Displaying a Popover is very straightforward, whether it is created from a Container or a Window, the method is the same:</p>



<pre class="wp-block-preformatted">DesktopContainer.ShowPopover(parentControl As DesktopUIControl, facing As DesktopWindow.DisplaySides = DesktopWindow.DisplaySides.Bottom, detachable As Boolean = True)</pre>



<p>The explanation of the expected parameters is as follows:</p>



<ul class="wp-block-list">
<li><strong>ParentControl:</strong> The control that will act as the parent, or on which the Popover will be pointing to.</li>



<li><strong>Facing:</strong> The direction in which the Popover will point on the parent control; by default it will appear under the parent control, but you can use any of the values available in the DesktopWindow.DisplaySides enumerator (or the iOS equivalent).</li>



<li><strong>Detachable:</strong> This value only applies to macOS Popovers, since said operating system has the ability for the user to &#8220;detach&#8221; the Popover from the parent control as long as this value is defined as True. To detach, drag the Popover with the mouse cursor.</li>
</ul>



<p>Let&#8217;s say we have a window called Window2 and a button called MyButton. In the Pressed event of MyButton we can use the following lines of code to display Window2 as a Popover:</p>



<pre class="wp-block-preformatted">Var w As New Window2
w.ShowPopover(me)</pre>



<p>And that&#8217;s all!</p>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="1280" height="720" src="https://blog.xojo.com/wp-content/uploads/2024/03/PopoverDettach.gif" alt="" class="wp-image-12710"/></figure>



<h3 class="wp-block-heading">Platform Differences</h3>



<p>In the previous section we already pointed out the first: macOS is the only operating system that acts on the value indicated in the Detachable parameter. But there are some other considerations to keep in mind so you don&#8217;t get caught off guard:</p>



<ul class="wp-block-list">
<li><strong>Beyond the limits.</strong> Although in Windows and macOS Popovers can exceed the limits of the window on which the parent control is located, the position of the popover in Linux is restricted to the limits of the window that contains the parent control. This is the same for iOS and for Web pages.</li>



<li><strong>iPhone and iPad.</strong> When a Popover is displayed on an iPhone, it will look like a modal window; while if the same application is run on an iPad, the appearance will be the typical one expected from Popovers: the window pointing to the parent control in the indicated direction.</li>



<li><strong>On the Web.</strong> The contents of a Popover are those defined in a Container control, while on the rest of the platforms you can use both Container controls and Windows / Screens.</li>
</ul>



<h3 class="wp-block-heading">Why the Popover doesn&#8217;t &#8220;point&#8221; in the configured direction?</h3>



<p>By default it will try to do so according to the value that has been set in the &#8220;facing&#8221; parameter, but if it does not find enough space on the margins of the screen, then it will be displayed on the next side of the parent control in which there is available space for display the Popover in its full width and height; This is true on macOS, Linux, Web and iOS.</p>



<h3 class="wp-block-heading">Can I reuse a Popover?</h3>



<p>No, You can not. Whether you use a Container control or a window as the source of the UI design to be displayed by the Popover, do not lose sight of the fact that the Popover is just another type of window; and therefore behaves as such. That is, once it is closed either because it has lost focus or because you have closed it explicitly through code invoking the Close method, all the displayed controls and the rest of the internal structures will be closed / invalidated, so that although the instance If a Popover is not Nil (because, for example, you keep a reference to the window or container instance used as the UI source), you will not be able to invoke the ShowPopover method again on said instance but you will have to create a new instance of the Container/ Window used as the source of the UI to be displayed by the Popover.</p>



<h3 class="wp-block-heading">How can I communicate with the UI elements contained in the Popover?</h3>



<p>You would do so just as you would do with any other type of window that you have been using so far in your Xojo projects.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1280" height="720" src="https://blog.xojo.com/wp-content/uploads/2024/03/PopoverComm.gif" alt="" class="wp-image-12712"/></figure>
</div>


<h3 class="wp-block-heading">Conclusion</h3>



<p>Without a doubt, Popovers are a new way to improve the design of your apps&#8217; user interfaces, providing a more direct relationship between the user interface elements displayed in the Popover and the &#8220;parent&#8221; control in charge of displaying it. Furthermore, since you can use any window or container you want as the source of the UI to be displayed by the Popover, you will have greater flexibility about when you want to display them in a Popover or display them using any other of the available window types or, in the case of Containers, embedding them as part of other UI elements at runtime.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WebUIControl Badges Using Extension Methods</title>
		<link>https://blog.xojo.com/2022/11/03/webuicontrol-badges-using-extension-methods/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Thu, 03 Nov 2022 17:59:19 +0000</pubDate>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Extension Methods]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10934</guid>

					<description><![CDATA[I was having some fun with badges, trying to recreate a design. I’ve ended up writing a few extension methods to use them on almost any WebUIControl. ]]></description>
										<content:encoded><![CDATA[
<p>I was having some fun with badges, trying to recreate a design. I’ve ended up writing a few extension methods to use them on almost any WebUIControl. </p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="429" src="https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.12-AM-1024x429.png" alt="" class="wp-image-10936" srcset="https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.12-AM-1024x429.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.12-AM-300x126.png 300w, https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.12-AM-768x321.png 768w, https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.12-AM-1536x643.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.12-AM-2048x857.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">But first, what’s an Extension Method anyway? </h3>



<p>There are situations where you want to add functionality to a Xojo Framework class. Let’s say we want to add a method to every visual web control. We know that every visual control inherits from WebUIControl. This class can’t be modified, as it’s part of the framework. One option would be subclassing each control and adding new methods… but that’s so boring… </p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="577" src="https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.21-AM-1024x577.png" alt="" class="wp-image-10937" srcset="https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.21-AM-1024x577.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.21-AM-300x169.png 300w, https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.21-AM-768x433.png 768w, https://blog.xojo.com/wp-content/uploads/2022/11/Screen-Shot-2022-11-03-at-9.24.21-AM.png 1342w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p><a href="https://documentation.xojo.com/getting_started/using_the_xojo_language/modules.html#extension-methods">Extension Methods</a> are part of the Modules feature, allowing us to extend classes with methods, even if we don’t have access to their source code.</p>



<h3 class="wp-block-heading">Adding SetBadge and RemoveBadge methods to every visual control</h3>



<p>The first thing you need is a Module. Press on the Add button from the toolbar and select Module. The name of the module is up to you, I’ll be using WebExtensions in this example.</p>



<p>Now add a new method into that module, called &#8220;SetBadge&#8221;. Then, in the inspector, ensure its visibility is set to Global, instead of Public or Protected.</p>



<p>The magic happens in the first parameter of this method. “Extends” is the reserved keyword for this feature, for example:</p>



<pre class="wp-block-preformatted">Extends myInstance As ExampleClass</pre>



<p>Above method would be extending an imaginary class called “ExampleClass”, and its instance would be available inside that method, accessible from the variable “myInstance”.</p>



<p>In our case, for SetBadge, we want to use this method signature instead:</p>



<pre class="wp-block-preformatted">Extends control As WebUIControl, caption As String, indicator As String = "danger", top As Integer = -10, right As Integer = -10</pre>



<p>Inside, paste the method contents:</p>



<pre class="wp-block-preformatted">Var classes() As String = Array("xojo-badge", "d-flex", "p-2", _ 
"border", "border-light", "bg-" + indicator) 
classes.Add(If(caption.Length &lt; 2, "rounded-circle", "rounded-pill"))

Var styles() As String = Array("height: 21px", "font-size: 10px", _ 
"align-items: center", "color: white", "position: absolute", _ 
"top: " + top.ToString + "px", "right: " + Right.ToString + "px", _ 
"z-index: 10")

If caption = "" Or caption = " " Then caption = "&amp;nbsp;"
Var html As String = "&lt;span class=""" + String.FromArray(classes) + _
""" style=""" + String.FromArray(styles, ";") + """&gt;" + caption + "&lt;/span&gt;"

Var js() As String
js.Add("$('#" + control.ControlID + " .xojo-badge').remove();") 
js.Add("$('#" + control.ControlID + "').append(`" + html + "`);")
control.ExecuteJavaScript(String.FromArray(js))</pre>



<p>What this little sorcery does is appending a new HTML layer into our control, using some Bootstrap’s component CSS classes. Did you notice we are using &#8220;control&#8221; instead of &#8220;Self&#8221;? It matches the “control” variable from the method definition.</p>



<p>Add another Extension Method for removing the badges, called “RemoveBadge”.</p>



<p>The method definition reads like this:</p>



<pre class="wp-block-preformatted">Extends control As WebUIControl</pre>



<p>The content is a bit easier this time:</p>



<pre class="wp-block-preformatted">Var js As String = "$('#" + control.ControlID + " .xojo-badge').remove();"
control.ExecuteJavaScript(js)</pre>



<p>That’s it. Plumbing done.</p>



<p>Now, if you have a WebButton called&#8230; &#8220;AwesomeButton&#8221;, you can set its badge using this code:</p>



<pre class="wp-block-preformatted">AwesomeButton.SetBadge("Hello!")</pre>



<p>And to remove it:</p>



<pre class="wp-block-preformatted">AwesomeButton.RemoveBadge()</pre>



<p>You can use these badges in different scenarios. From displaying a pending notifications counter in a WebButton, to validation errors in a WebTextField.</p>



<p>Adjust and play with the code to meet your needs!&nbsp;<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>You can download the example from the <a href="https://github.com/piradoiv/xojo-web-badges">GitHub code repository</a>.</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How did I not know this?</title>
		<link>https://blog.xojo.com/2022/09/03/how-did-i-not-know-this/</link>
		
		<dc:creator><![CDATA[Dana Brown]]></dc:creator>
		<pubDate>Sat, 03 Sep 2022 15:10:40 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10738</guid>

					<description><![CDATA[Xojo MVP Anthony Cyphers has been using Xojo for nearly 20 years and is currently building a User Interface framework for a project he is working on. This project needs to have the ability to tweak colors as needed and have those changes applied across every element of that framework. Read on Anthony's blog about the way he solved this problem.]]></description>
										<content:encoded><![CDATA[
<p>Xojo MVP Anthony Cyphers has been using Xojo for nearly 20 years and is currently building a User Interface framework for a project he is working on. This project needs to have the ability to tweak colors as needed and have those changes applied across every element of that framework. Read on <a rel="noreferrer noopener" href="https://graffitisuite.com/news/from-anthony-how-did-i-not-know-this/" target="_blank">Anthony&#8217;s blog</a> about the way he solved this problem.</p>



<p>We love to share Xojo tips and tricks! Please <a href="mailto:hello@xojo.com">write us</a> if you have something to share.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Simplified: Adding User Interface Controls at Runtime</title>
		<link>https://blog.xojo.com/2022/01/21/simplified-adding-user-interface-controls-at-runtime/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Fri, 21 Jan 2022 15:07:22 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Container]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=9793</guid>

					<description><![CDATA[The process of adding new controls to windows (or containers) at runtime has been greatly simplified. Instead of having to deal with control arrays, when you use Xojo 2021r3 or later you can call the new AddControl method on the DesktopWindow (or DesktopContainer) where you want to add the new control. ]]></description>
										<content:encoded><![CDATA[
<p>The process of adding new controls to windows (or containers) at runtime has been greatly simplified. Instead of having to deal with control arrays, when you use Xojo 2021r3 or later you can call the new AddControl method on the DesktopWindow (or DesktopContainer) where you want to add the new control. Continue reading and I will show you how!</p>



<span id="more-9793"></span>



<p>The new AddControl method on <a href="https://documentation.xojo.com/api/user_interface/desktop/desktopwindow.html">DesktopWindow</a> and <a href="https://documentation.xojo.com/api/user_interface/desktop/desktopcontainer.html">DesktopContainer</a> accepts any <a href="https://documentation.xojo.com/api/user_interface/desktop/desktopuicontrol.html">DesktopUIControl</a> instance you want to add to a window or container.</p>



<p>To make the new DesktopUIControl instance really visible in the target window or container, you&#8217;ll need to set some basic properties; specifically the desired width and height values for the new instance control and also the left and top coordinate values where you expect the control to be added. These values are relative to the left/top corner of the target window/container, so a value of top = 0 and left = 0 means to add the control at the top/left corner of the target window itself.</p>



<p>In order to see how this works, this example creates a Desktop project that includes multiple DesktopButton instances at runtime while also removing them from the target DesktopContainer (calling the Close method on the instance to do that). Plus we&#8217;ll make them adjust as the size of the Container changes like you see in this example below.</p>



<div class="wp-block-image is-style-default"><figure class="aligncenter"><img loading="lazy" decoding="async" width="618" height="442" src="https://blog.xojo.com/wp-content/uploads/2021/12/AddControl.gif" alt="" class="wp-image-9796"/></figure></div>



<h3 class="wp-block-heading">1. Creating the Base Container</h3>



<p>Open Xojo and create a new Desktop project. Double click on the Container in the Library so it is added to the Navigator in the IDE. Use the Inspector panel to change the following properties:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> <code>BaseContainer</code></li></ul>



<p>Add a new property to the BaseContainer subclass in the Navigator (use the contextual menu for that), setting the following values in the Inspector panel:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> <code>Controls()</code></li><li><strong>Type:</strong> <code>DesktopUIControl</code></li><li><strong>Scope:</strong> <code>Public</code></li></ul>



<h3 class="wp-block-heading">2. Adding New Controls to the BaseContainer</h3>



<p>We are going to need some Methods in the BaseContainer, starting with the one responsible for adding new DesktopButton instances. Add a new Method setting the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> <code>AddNewControl</code></li><li><strong>Scope:</strong> <code>Public</code></li></ul>



<p>Write the following snippet of code in the associated Code Editor for the Method:</p>



<pre class="wp-block-preformatted">// Setting static values for the new Button instances
// Width and Name values
Static cWidth As Integer = 40
Static cInitialName As String = "ControlName"

// Initial X and Y coordinates for the control instance
Var startX As Integer = If(Controls.Count = 0, 20, Controls(Controls.LastIndex).Left + cWidth + 20)
Var startY As Integer = If(Controls.Count = 0, 20, Controls(Controls.LastIndex).Top)

// We need to adjust the X/Y coordinates if the control
// exceeds the available BaseContainer width
If startX + cWidth &gt; Me.Width Then
  startX = 20
  startY = startY + Controls(Controls.LastIndex).Height + 20
End If

// Creating the new DesktopButton instance to be added
// and setting the expected values so it is visible
// at the desired size and position.
Var nControl As New DesktopButton
Var idxNumber As Integer = Controls.LastIndex + 1
nControl.Name = cInitialName + idxNumber.ToString
nControl.Caption = idxNumber.ToString
nControl.Left = startX
nControl.Top = startY
nControl.Width = cWidth

// On macOS we get the default height for free
// this is not the case on Windows
#If TargetWindows Then
  nControl.Height = 22
#EndIf

// We set the method to be called by the instance
// when the user presses the button
// so we can catch it and forward it to the
// BaseControl instance
AddHandler nControl.Pressed, AddressOf ControlActionCallback

// Adding the new control instance to the array
controls.Add(nControl)

// …and adding it to the BaseContainer
// calling the new AddControl method for that
Me.AddControl(nControl)</pre>



<p>As you can see, we are using the AddHandler method to substitute the original Event fired by the control with our own Method; so let&#8217;s create that. Add a new Method to BaseContainer using the following values in the Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> <code>ControlActionCallback</code></li><li><strong>Parameters:</strong> <code>tControl As DesktopUIControl</code></li><li><strong>Scope:</strong> <code>Public</code></li></ul>



<p>And write this line of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">RaiseEvent ControlPressed(tControl)</pre>



<h3 class="wp-block-heading">3. Removing Controls From the BaseContainer</h3>



<p>The third and last method we need to add to our BaseContainer subclass is the one responsible of removing the last added control; add a new method to the BaseContainer subclass using the following values:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> <code>RemoveLastControl</code></li><li><strong>Scope:</strong> <code>Public</code></li></ul>



<p>And write the following snippet of code in the associated Code Editor for the Method:</p>



<pre class="wp-block-preformatted">If Controls.LastIndex &lt;&gt; -1 Then

  Var tControl As DesktopUIControl = Controls.Pop

  // We need to remove the callback method from the original
  // Pressed event on the instance
  RemoveHandler DesktopButton(tControl).Pressed, AddressOf ControlActionCallback

  // Closing the control instance so it is removed from the
  // containing BaseControl
  tControl.Close

End If</pre>



<h3 class="wp-block-heading">4. Forwarding Events</h3>



<p>Because we are forwarding the received Pressed event from the DesktopButton to the ControlActionCallback method, and it is raising the ControlPressed method passing along the received instance, we need to define that Event in our BaseContainer subclass using the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Event Name:</strong> <code>ControlPressed</code></li><li><strong>Parameters:</strong> <code>tControl As DesktopUIControl</code></li></ul>



<h3 class="wp-block-heading">5. Reacting to Resizing</h3>



<p>We want our BaseContainer to react to changes in its width and/or height, so it has the chance to change the layout (position) of the controls added to it. With the BaseContainer selected in the Navigator, add the Resizing Event and type the following code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">#Pragma DisableBackgroundTasks
#Pragma DisableBoundsChecking

Var startX As Integer = 20
Var startY As Integer = 20

Var lastIndex As Integer = Controls.LastIndex
Var tControl As DesktopUIControl

For n As Integer = 0 To lastIndex

  tControl = Controls(n)

  If n &lt;&gt; 0 Then startX = Controls(n - 1).Left + Controls(n - 1).Width + 20

  If startX &gt; Me.Width - tControl.Width Then
    startx = 20
    If n &lt;&gt; 0 Then startY = startY + tControl.Height + 20
  End If

  tControl.Left = startX
  tControl.top = startY

Next n</pre>



<h3 class="wp-block-heading">6. Designing the User Interface</h3>



<p>Select the Window1 window in the Navigator so it is displayed in the Layout Editor. Next, drag a Button from the Library and place it at the top/left corner leaving the expected margins recommended by the Layout Guides.</p>



<p>With the just added button still selected, change the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> <code>AddControlButton</code></li><li><strong>Caption:</strong> &#8220;Add Control&#8221;</li></ul>



<p>Add the Pressed Event to the button and type the following line of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">BaseContainer1.AddNewControl</pre>



<p>Add a second button and place it just below the previous one. Use the associated Inspector Panel to set the following values:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> <code>RemoveControlButton</code></li><li><strong>Locking:</strong> Left and Top locks closed</li><li><strong>Caption:</strong> &#8220;Remove Control&#8221;</li></ul>



<p>Use the resizing handlers on the control to make its width enough to display the Caption properly.</p>



<p>Add the Pressed Event to just added button and type the following line of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">BaseContainer1.RemoveLastControl</pre>



<p>Add a Label from the Library and place it to the right of the first button. Use the Inspector Panel to set the following values:</p>



<ul class="wp-block-list"><li><strong>Locking:</strong> Left and Top locks closed</li><li><strong>Text:</strong> &#8220;Control Pressed:&#8221;</li></ul>



<p>Use the resizing handlers on the control to make its width enough to display the Text properly.</p>



<p>Add a second Label and place it to the right of the previous one, using the Inspector Panel to set the following values:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> <code>ControlPressedName</code></li><li><strong>Locking:</strong> Left and Top locks closed</li><li><strong>Text:</strong> &#8220;&#8221;</li></ul>



<p>Finally, drag the BaseContainer from the Navigator and place it below the second button. Use the resizing handlers on the control to make it width and tall enough to fill all the remaining area on the window. The final layout should look more or less like this:</p>



<div class="wp-block-image is-style-default"><figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="791" src="https://blog.xojo.com/wp-content/uploads/2021/12/AddControlUI-1024x791.png" alt="" class="wp-image-9795" srcset="https://blog.xojo.com/wp-content/uploads/2021/12/AddControlUI-1024x791.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/12/AddControlUI-300x232.png 300w, https://blog.xojo.com/wp-content/uploads/2021/12/AddControlUI-768x593.png 768w, https://blog.xojo.com/wp-content/uploads/2021/12/AddControlUI.png 1346w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>Use the Inspector Panel to set the following values:</p>



<ul class="wp-block-list"><li><strong>Locking:</strong> left, top, right and bottom clocks closed (locked)</li></ul>



<p>With the BaseContainer1 instance selected in the Layout Editor, add the ControlPressed Event to it and write the following line of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">ControlPressedName.Text = tControl.name</pre>



<h3 class="wp-block-heading">7. Running the App</h3>



<p>All set! Run the App, press the &#8220;Add Control&#8221; button to add as many buttons you want to the BaseContainer1 control, and press the &#8220;Remove Control&#8221; button to remove controls. Try to resize the window and you&#8217;ll see how the controls change their position as needed.</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Xojo and Windows 11</title>
		<link>https://blog.xojo.com/2021/06/24/xojo-and-windows-11/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Thu, 24 Jun 2021 22:04:34 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[Windows 11]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8713</guid>

					<description><![CDATA[We are excited about Microsoft's announcement regarding Windows 11. A large portion of Xojo users develop on and/or for Windows. The new UI looks fantastic and will be a welcome upgrade for Windows users. Xojo and apps written in Xojo will run without modification on Windows 11.]]></description>
										<content:encoded><![CDATA[
<p>We are excited about Microsoft&#8217;s announcement regarding Windows 11. A large portion of Xojo users develop on and/or for Windows. The new UI looks fantastic and will be a welcome upgrade for Windows users. Xojo and apps written in Xojo will run without modification on Windows 11.<br><br>How will the new UI in Windows 11 affect apps written in Xojo? Historically Microsoft has had many different API sets for providing the user experience on Windows ranging from Win32 to .NET to WPF. Earlier this year Microsoft announced that WinUI 3.0 will bring all of these together allowing for a unified look and feel and user experience regardless of which API is being used under the hood. Microsoft plans to finalize WinUI 3.0 by the end of this year. Once they do, we can begin planning to update the Xojo Windows framework to support it.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="600" height="409" src="https://blog.xojo.com/wp-content/uploads/2021/06/Windows11Controls.png" alt="" class="wp-image-8716" srcset="https://blog.xojo.com/wp-content/uploads/2021/06/Windows11Controls.png 600w, https://blog.xojo.com/wp-content/uploads/2021/06/Windows11Controls-300x205.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /><figcaption>Windows 11 UI Controls, Image Credit: Microsoft</figcaption></figure></div>



<p>The first beta of Windows 11 is scheduled to be released next week and we will be testing the Xojo Windows framework on it. We will have more blog posts as more information becomes available about the next generation of Windows.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>ContainerControl: Composed User Interface Components</title>
		<link>https://blog.xojo.com/2021/05/20/containercontrol-composed-user-interface-components/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 20 May 2021 14:48:50 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[ContainerControl]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8459</guid>

					<description><![CDATA[Through this tutorial we practiced  the basics of using ContainerControls in Desktop projects: adding them to the project, using them at design time, how to forward values from the container's controls to the window where these can be added, how to create a ContainerControl subclass that shares its method and events with any ContainerControl subclassed from it, how to add new ContainerControl instances to a window at runtime, and also how to delegate the execution of a event so it can be handled by a window method.]]></description>
										<content:encoded><![CDATA[<p>Xojo&#8217;s Library offers a good amount of UI controls ready to use: buttons, input text controls, lists, popup menus, progress bars, panels, labels, a control to play movies, etc. However, sometimes we need to display exactly the same combination of controls, using the same layout, in several windows of an app. What&#8217;s the best approach in these cases?<span id="more-8459"></span></p>
<p>Obviously, adding the same bunch of controls again and again on each window is not the best solution; even less so when we consider the need to add the exact same code in each of these controls.</p>
<p>The ContainerControl is your best bet to avoid these repetitive tasks. The ContainerControl is a component half way between the available controls in the Library (inherited from the Control class) and a Window. If you look at the properties, methods and events offered by the <a href="http://documentation.xojo.com/api/deprecated/containercontrol.html"><strong>ContainerControl</strong></a> you&#8217;ll find many of these are the same ones available in the Window class.</p>
<blockquote><p><a href="https://bit.ly/3huMxzs">Download the Example Project for this tutorial</a></p></blockquote>
<h2>ContainerControl Layout</h2>
<p>Adding other controls to a ContainerControl couldn&#8217;t be simpler. Start by adding a new ContainerControl from the Library to the Navigator (by default, it will be named <code>ContainerControl1</code>), select it in the Navigator to access the Layout Editor. You can use the Inspector Panel to setup the properties. Please note, control&#8217;s locks will act on the top, left, right and bottom sides of <em>the ContainerControl</em> they are embedded on; as opposed to using the locks on the ContainerControl itself which locks the position of the container over the top, left, right and bottom sides of <em>the Window</em> where the container is used.</p>
<p><figure id="attachment_8460" aria-describedby="caption-attachment-8460" style="width: 300px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-8460 size-medium" src="https://blog.xojo.com/wp-content/uploads/2021/05/ControlLock-300x201.jpg" alt="" width="300" height="201" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/ControlLock-300x201.jpg 300w, https://blog.xojo.com/wp-content/uploads/2021/05/ControlLock-1024x685.jpg 1024w, https://blog.xojo.com/wp-content/uploads/2021/05/ControlLock-768x514.jpg 768w, https://blog.xojo.com/wp-content/uploads/2021/05/ControlLock.jpg 1154w" sizes="auto, (max-width: 300px) 100vw, 300px" /><figcaption id="caption-attachment-8460" class="wp-caption-text">Locked ContainerControl</figcaption></figure></p>
<p><figure id="attachment_8461" aria-describedby="caption-attachment-8461" style="width: 300px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-8461 size-medium" src="https://blog.xojo.com/wp-content/uploads/2021/05/ContainerLock-300x227.jpg" alt="" width="300" height="227" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/ContainerLock-300x227.jpg 300w, https://blog.xojo.com/wp-content/uploads/2021/05/ContainerLock-1024x774.jpg 1024w, https://blog.xojo.com/wp-content/uploads/2021/05/ContainerLock-768x581.jpg 768w, https://blog.xojo.com/wp-content/uploads/2021/05/ContainerLock.jpg 1107w" sizes="auto, (max-width: 300px) 100vw, 300px" /><figcaption id="caption-attachment-8461" class="wp-caption-text">Locked Window</figcaption></figure></p>
<h2></h2>
<h2>Using ContainerControls in the Window Layout</h2>
<p>Now that the layout of the ContainerControl is done, it&#8217;s time to add it to the Windows or Panels. Select a Window to access the associated Layout Editor and then drag the ContainerControl from the Navigator to the desired position onto the window frame displayed on the Layout Editor. Once done, that instance will be added under the <code>Controls</code> section for the Window in the Navigator (by default it will be named <code>ContainerControl11</code> because is an instance from <code>ContainerControl1</code>).</p>
<p>Something interesting to observe is that once you add the container to the Window, you won&#8217;t be able to change the position or behavior of the embedded controls in the container from the Window Layout Editor. The controls embedded in the container are displayed as &#8220;disabled&#8221;.</p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8462 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/ContainerOnWindow-1024x565.png" alt="" width="1024" height="565" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/ContainerOnWindow-1024x565.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/05/ContainerOnWindow-300x166.png 300w, https://blog.xojo.com/wp-content/uploads/2021/05/ContainerOnWindow-768x424.png 768w, https://blog.xojo.com/wp-content/uploads/2021/05/ContainerOnWindow-1536x848.png 1536w, https://blog.xojo.com/wp-content/uploads/2021/05/ContainerOnWindow-2048x1131.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>Select the item <code>ContainerControl1</code> in the Navigator to change the layout, add new UI controls, and change the position, size or behavior.</p>
<p>Since we only can add Event Handlers to the controls added to <code>ContainerControl1</code>, but not when those containers are added to a window or panel, how do you &#8220;communicate&#8221; with the windows using these containers? There are several approaches to achieve this. In this example, set the Scope to Public so the Window can access the controls added to a ContainerControl.</p>
<p>If we had added a ListBox control (default name <code>ListBox1</code>) to our <code>ContainerControl1</code>, setting its <code>Scope</code> property as <code>Public</code> in the Inspector Panel, it can be accessed using the usual dot notation. For example, from the Open Event Handler added to the <code>Window1</code> item:</p>
<pre>Me.ContainerControl11.ListBox1.AddRow("New Item")</pre>
<p>This solves one of the communication problems; but, how can the controls embedded in a container &#8220;communicate&#8221; with the Window containing the container? That is, how do we send the value of the selected row in the <code>ListBox1</code> control to the Window?</p>
<p>Let&#8217;s think about that scenario for a moment: the Window <code>Window1</code> knows the name of the ContainerControl added to it (<code>ContainerControl11</code>), and also the names of the controls added to that container because their Scope has been set to Public. On the other hand, the controls know about the ContainerControl they are embedded in, but they don&#8217;t know in advance the name of the Window where such ContainerControls can be added as part of the layout. In addition, the ContainerControl knows the name of the controls added to it, but it doesn&#8217;t know in advance the name of the Window or Panels where the container can be displayed. Moreover, it is possible to add ContainerControls to a Window or Panel layout in Design Mode (in the IDE), as well as at runtime!</p>
<p>Considering all of this, the simple solution to communicate between the controls added to a ContainerControl and the Window or Windows that will be using that container is by adding new methods and new Event Definitions on that ContainerControl (in this example, the one named <code>ContainerControl1</code>). There are other techniques, but we are going to use this one in this tutorial.</p>
<p>Continuing with our example,  add a new method to <code>ContainerControl1</code> using the following method signature:</p>
<pre>RowSelected(value As String)</pre>
<p>Next, with <code>ContainerControl1</code> still selected in the Navigator, choose the Insert &gt; Event Definition option in order to create a Event using the following signature:</p>
<pre>RowSelected(value As String)</pre>
<p>Click on the method added previously to access the associated Code Editor and type the following line of code:</p>
<pre>RaiseEvent RowSelected(value)</pre>
<p>The method will simply raise the defined event passing along the received value as the argument.</p>
<p>Now, select the <code>ListBox1</code> item on the <code>ContainerControl1</code> item, and add the <code>Changed</code> Event Handler. This is the event raised every time the user changes the selected row in the ListBox. Type the following code in the associated Code Editor:</p>
<pre>If Me.SelectedRowIndex &lt;&gt; -1 Then
    Self.RowSelected(Me.SelectedRowValue)
End if</pre>
<p>Add the <code>Open</code> event to the <code>ListBox1</code> item, type the following code in the associated Code Editor:</p>
<pre>For n As Integer = 0 To 10
    Me.AddRow(n.ToString)
Next</pre>
<p>Now, add the defined event in <code>ContainerControl1</code> to the <code>ContainerControl11</code> instance added to the <code>Window1</code> layout. Select that item and choose the Add &gt; Event Handler option. Choose the <code>SelectedRow</code> event handler and confirm the selection clicking the &#8220;OK&#8221; button.</p>
<p>Type the following line of code in the associated Code Editor:</p>
<pre>MessageBox("Selected value: " + value)</pre>
<p>Of course, you can do something more useful with the received value; but this is useful enough to show how the values can be sent from the ListBox control to any window where the container can be used.</p>
<h2>Subclassing ContainerControl</h2>
<p>Some projects may require using several ContainerControls, and many of them may be using a ListBox. As it is when using any other class, it would be great to have both the <code>SelectedRow</code> method and the <code>SelectedRow</code> Event Definition in their own ContainerControl subclass, and they are available by default to any ContainerControl added to the project and embedding a ListBox. The good news is that it is also possible to create a subclass for a ContainerControl, as it is explained in the <a href="https://documentation.xojo.com/topics/user_interface/desktop/desktop_controls/container.html_Control">User Guide</a>.</p>
<p>Add a new Class to the project and use the Inspector Panel to change its name to <code>MyContainerClass</code> and the Super field to <code>ContainerControl</code>.</p>
<p>Next, select the <code>SelectedRow</code> method and the Event Definition with the same name in <code>ControlContainer1</code>, cut them (Edit &gt; Cut), select <code>MyContainerClass</code> and paste them (Edit &gt; Paste). Both the method and the event definition are now available under <code>MyContainerClass</code>.</p>
<p>Select <code>ContainerControl1</code> in the Navigator and use the Inspector Panel to change its <code>Super</code> field to <code>MyContainerClass</code>. Add a second ContainerControl from the Library to the Navigator (by default it will be named <code>ContainerControl2</code>). With the new item selected in the Navigator, use the Inspector Panel to change its <code>Super</code> field to <code>MyContainerClass</code>. Add the ListBox control from the Library to the layout of the new container and type the following code in the <code>Open</code> event for the <code>ListBox1</code> item:</p>
<pre>For n As Integer = 0 To 10
    me.AddRow(n.ToString)
Next</pre>
<p>Add the <code>Changed</code> event to <code>ListBox1</code> and type the following code:</p>
<pre>If Me.SelectedRowIndex &lt;&gt; -1 Then
    Self.SelectedRow(Me.SelectedRowValue)
End If</pre>
<p>Next, add the second container <code>ContainerControl2</code> to the project window <code>Window1</code>. The layout could be similar to that of this screenshot:</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-8463 size-medium" src="https://blog.xojo.com/wp-content/uploads/2021/05/TwoContainersLayout-300x223.png" alt="" width="300" height="223" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/TwoContainersLayout-300x223.png 300w, https://blog.xojo.com/wp-content/uploads/2021/05/TwoContainersLayout-1024x762.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/05/TwoContainersLayout-768x572.png 768w, https://blog.xojo.com/wp-content/uploads/2021/05/TwoContainersLayout.png 1494w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>Select the <code>ContainerControl21</code> item under Window1 &gt; Controls and add the <code>SelectedRow</code> event handler. Add this line of code to display the received value in a message box:</p>
<pre>MessageBox("Selected value: " + value)</pre>
<p>As you can see, both <code>ContainerControl1</code> and <code>ContainerControl21</code> do not include the <code>SelectedRow</code> method. These are inherited from their super class: <code>MyContainerClass</code>.</p>
<h2>Adding ContainerControls at Runtime</h2>
<p>Xojo also lets you add ContainerControls at runtime, something that is really interesting and makes Xojo apps flexible and powerful. Let&#8217;s do that in a simple example:</p>
<p>Select the <code>Window1</code> item in the Navigator and delete the <code>ContainerControl11</code> and <code>ContainerControl21</code> items. With <code>Window1</code> still selected, add a new property using the following values in the Inspector Panel:</p>
<ul>
<li><strong>Name:</strong> Containers()</li>
<li><strong>Type:</strong> MyContainerClass</li>
</ul>
<p>Add the <code>Open</code> event to <code>Window1</code>, type the following code in the associated Code Editor:</p>
<pre>Var leftContainer As New ContainerControl1

leftContainer.Width = 200
leftContainer.LockTop = True
leftContainer.LockRight = False
leftContainer.LockBottom = False
leftContainer.LockLeft = True

leftContainer.EmbedWithin(Me, 20, 20)

Containers.Add(leftContainer)

Var rightContainer As New ContainerControl2

rightContainer.Width = 200
rightContainer.LockLeft = True
rightContainer.LockTop = True
rightContainer.LockBottom = True
rightContainer.LockRight = True
rightContainer.EmbedWithin(Me, Me.Width - 20 - rightContainer.Width, 20)

Containers.Add(rightContainer)</pre>
<p>Run the app, change the window size and you&#8217;ll notice how the container at the right side adjusts its height and width to match the changes made in the window while the container at the left side keeps its original position.</p>
<p>Try to change the selected row in any of the ListBoxes. Nothing happens! As you may remember, in order to &#8220;forward&#8221; the selected row value from the ListBox to the window we needed to add the <code>SelectedRow</code> event handler. This is something we can&#8217;t do when adding new container instances at runtime. In order to do that we need to use the <a href="http://documentation.xojo.com/api/code_execution/addhandler.html"><code>AddHandler</code></a> keyword. This lets us redirect an event handler to a delegated method. Quit the app to return to the IDE and, with <code>Window1</code> still selected in the Navigator, add a new method using the following signature:</p>
<pre>ListBoxSelectedRow(item As MyContainerClass, value As String)</pre>
<p>Notice that the first parameter will contain a reference to the instance of the <code>MyContainerClass</code> raising the event, while the second parameter will contain the value itself.</p>
<p>The only thing left is to associate the event name with the memory address of the method that will handle it for each of the Container instances added at runtime. Again, select the <code>Open</code> event tied to the <code>Window1</code> item and change its code like so:</p>
<pre>Var leftContainer As New ContainerControl1

leftContainer.Width = 200
leftContainer.LockTop = True
leftContainer.LockRight = False
leftContainer.LockBottom = False
leftContainer.LockLeft = true

AddHandler leftContainer.SelectedRow, WeakAddressOf ListBoxSelectedRow

leftContainer.EmbedWithin(Me, 20, 20)

Containers.Add(leftContainer)

Var rightContainer As New ContainerControl2

AddHandler rightContainer.SelectedRow, WeakAddressOf ListBoxSelectedRow

rightContainer.Width = 200
rightContainer.LockLeft = True
rightContainer.LockTop = True
rightContainer.LockBottom = True
rightContainer.LockRight = True
rightContainer.EmbedWithin(Me, Me.Width - 20 - rightContainer.Width, 20)

Containers.Add(rightContainer)</pre>
<p>The lines of code really are interesting:</p>
<pre>AddHandler leftContainer.SelectedRow, WeakAddressOf ListBoxSelectedRow
AddHandler rightContainer.SelectedRow, WeakAddressOf ListBoxSelectedRow</pre>
<p>As you can see, through <code>AddHandler</code> we are instructing the <code>SelectedRow</code> event from every container instance to be handled by the <code>ListBoxSelectedRow</code> method added to <code>Window1</code>.</p>
<p>On the other hand, <code>WeakAddressOf</code> is a Xojo programming language operator allowing us to get a &#8220;weak&#8221; reference to the memory address where the <code>ListboxSelectedRow</code> is found so it can be invoked.</p>
<h2>Summary</h2>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-8464 size-medium" src="https://blog.xojo.com/wp-content/uploads/2021/05/RunningApp-300x212.jpg" alt="" width="300" height="212" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/RunningApp-300x212.jpg 300w, https://blog.xojo.com/wp-content/uploads/2021/05/RunningApp-1024x724.jpg 1024w, https://blog.xojo.com/wp-content/uploads/2021/05/RunningApp-768x543.jpg 768w, https://blog.xojo.com/wp-content/uploads/2021/05/RunningApp.jpg 1248w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>Through this tutorial we practiced some of the basics of using ContainerControls in Desktop projects: adding them to the project, using them at design time, how to forward values from the container&#8217;s controls to the window where these can be added, how to create a ContainerControl subclass that shares its method and events with any ContainerControl subclassed from it, how to add new ContainerControl instances to a window at runtime, and also how to delegate the execution of a event so it can be handled by a window method.</p>
<p>Questions? Ask me on Twitter <a href="https://twitter.com/xojoes">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary">Xojo Forum</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Updating the User Interface with the New Thread Class</title>
		<link>https://blog.xojo.com/2019/11/18/updating-the-ui-with-the-new-thread-class/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 18 Nov 2019 10:00:12 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Threads]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=6263</guid>

					<description><![CDATA[With Xojo 2019R2, everything related to updating the UI is much simpler thanks to the new UserInterfaceUpdate event in the Thread class.]]></description>
										<content:encoded><![CDATA[<p>Xojo 2019R2 has a lot of new features and enhancements, including the simplification of updating the User Interface in apps from threads running in combination with the main app thread. Doing that in previous releases required the use of a thread in combination with a Timer, for example.<span id="more-6263"></span></p>
<p>With Xojo 2019R2, everything related to updating the UI is much simpler thanks to the new <code>UserInterfaceUpdate</code> event in the Thread class. This provides, as an Array of Dictionaries, all the values we need to pass along from the <code>Run</code> event of the running Thread.</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-6264 size-large" src="https://blog.xojo.com/wp-content/uploads/2019/11/Xojo-Threads-API-2-1-1024x751.png" alt="" width="1024" height="751" srcset="https://blog.xojo.com/wp-content/uploads/2019/11/Xojo-Threads-API-2-1-1024x751.png 1024w, https://blog.xojo.com/wp-content/uploads/2019/11/Xojo-Threads-API-2-1-300x220.png 300w, https://blog.xojo.com/wp-content/uploads/2019/11/Xojo-Threads-API-2-1-768x563.png 768w, https://blog.xojo.com/wp-content/uploads/2019/11/Xojo-Threads-API-2-1.png 1456w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>In order to add new values to these dictionaries, we only need to call the <code>AddUserInterfaceUpdate</code> method, providing as parameter a <code>Pair</code>.</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-6265 size-large" src="https://blog.xojo.com/wp-content/uploads/2019/11/Xojo-Thread-API-2-Project-1024x612.png" alt="" width="1024" height="612" srcset="https://blog.xojo.com/wp-content/uploads/2019/11/Xojo-Thread-API-2-Project-1024x612.png 1024w, https://blog.xojo.com/wp-content/uploads/2019/11/Xojo-Thread-API-2-Project-300x179.png 300w, https://blog.xojo.com/wp-content/uploads/2019/11/Xojo-Thread-API-2-Project-768x459.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>The first (left) value of this pair will be the one acting as the Key for the Dictionary, while the second value of the pair (right) will be the value itself we want to forward to the main thread in order to update our user interface.</p>
<p>In addition, the overloaded <code>AddUserInterfaceUpdate</code> method also accepts a Dictionary as a parameter.</p>
<p>The two ways we can use the new thread class are the same available in previous releases:</p>
<ul>
<li>Draging and dropping an object from the Library panel to the Tray in the Window Layout, so the IDE creates a new instance that we can use to implement the <code>Run</code> and, now, also the <code>UserInterfaceUpdate</code> events. The <code>Run</code> event is the one intended to run the code usually associated with a long task, so it doesn&#8217;t <em>freeze</em> the responsiveness of the rest of the app (mainly the user interaction or user interface refreshes). The <code>UserInterfaceUpdate</code> event is the new Event whose parameter will provide all the data we are interested in previously added from the <code>Run</code> event calling the <code>AddUserInterfaceUpdate</code> method. That is: every time we call the <code>AddUserInterfaceUpdate</code> method, the Thread will fire its <code>UserInterfaceUpdate</code> event. Think about this as a <em>bridge</em> between our Thread and the main app thread.</li>
<li>The second approach is the one we use when creating the Thread instances from code. In this case, the solution is simple and is the one we usually use to <em>delegate</em> the code to execute in the Action event of the Timer class. <code>AddHandler</code> sets the method we want to execute in substitution of the <code>UserInterfaceUpdate</code> event handler of a Thread instance. As usual, make sure that the delegated method has the right signature: receiving a Thread object as its first parameter and the data we are interested in as the second parameter.</li>
</ul>
<p><iframe loading="lazy" title="Threads en Xojo 2019R2 y Posterior" width="500" height="375" src="https://www.youtube.com/embed/XHLL5hCQSSo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
<p>The example project available <a href="https://bit.ly/2Ni156h">here</a>, shows the implementation of both cases, how the Threads sends the data to update the user interface and how such data is received and accessed in the corresponding Thread Event Handler or delegated Method.</p>
<p>As you can see in the example, the user interface is responsive to the user interaction while the two threads do their work.</p>
<p>Easier and faster!</p>
<p><em data-rich-text-format-boundary="true">Javier Rodri­guez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages <a href="http://www.aprendexojo.com">AprendeXojo.com</a> and is the developer behind the GuancheMOS plug-in for Xojo Developers, GuancheID, AXControlGrid, AXImageCanvas, Markdown Parser for Xojo, and HTMLColorizer for Xojo among others.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Canvas: How to Create Custom UI Controls</title>
		<link>https://blog.xojo.com/2019/04/15/canvas-how-to-create-custom-ui-controls/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 15 Apr 2019 10:00:47 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[AprendeXojo]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Canvas]]></category>
		<category><![CDATA[iOSCanvas]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[WebCanvas]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5649</guid>

					<description><![CDATA[Sometimes, subclassing the available controls is the answer to add specific behaviors you need. But what happen when none of the controls offer what you need, whether visually or functionally? The answer is the Canvas class (for Desktop projects), WebCanvas class (for Web projects) and iOSCanvas class for iPhone and iPad devices. ]]></description>
										<content:encoded><![CDATA[<p>Xojo includes a good amount of <b>UI</b> controls available from the Library for <strong>Desktop</strong>, <strong>Web</strong>, <strong>iOS</strong> and <strong>Raspberry Pi</strong> targets. These are the pieces that allow you to layout the user interface of your apps: properties, methods and events that, when combined, define the specific behavior of the project at hand.</p>
<p>Sometimes, subclassing the available controls is the answer to add specific behaviors you need. But what happen when none of the controls offer what you need, whether visually or functionally? The answer is the Canvas class (for Desktop projects), WebCanvas class (for Web projects) and iOSCanvas class for iPhone and iPad devices. But how do you create your own UI controls from scratch? Read on to learn&#8230;<span id="more-5649"></span></p>
<p>Before starting with this basic tutorial about customized UI controls, there is much more to take into consideration about providing the same behavior on your designed controls for multiplatform deployments. For example, in the case of desktop projects, we should add to the mix some things like <strong>HiDPI</strong> / <strong>Retina</strong> detection and adaptation on the fly (specially in the case of Windows deployment, with multiple dpi / Windows OS version combinations), and <strong>Dark Mode</strong> support for macOS. A well as other performance hints and differences when it&#8217;s about doing desktop multiplatform layouts; for example, when to set the <code>Transparent</code> or <code>DoubleBuffer</code> properties to <code>True</code> or not.</p>
<p>As the name implies, the Canvas control acts like a painting canvas and you can set its look for all the supported states based on the available events. This is done through the <code>Paint</code> Event and all the <a href="http://documentation.xojo.com/api/graphics/graphics.html"><b>Graphic</b></a> classes availables in the Framework. In fact, the <b>Paint</b> event provides as a parameter the graphical context (canvas height and width) you can paint on. In addition, you can combine these graphic classes (or completely substitute them) with any prepared <b>Picture</b> of your choice as the customize control background (<a href="http://documentation.xojo.com/getting_started/using_the_ide/image_set_editor.html"><b>ImageSet</b></a> recommended, so it supports all the needed resolutions based on display dpi). In addition, and as you can do with the drawing via the Graphic class and functions, you can choose to use a different <a href="http://documentation.xojo.com/api/graphics/picture.html"><b>Picture</b></a> as the control background based on several events, for example, when the mouse pointer is entering or exiting the control limits in a Desktop or Web app, or as response to the user clicking on it.</p>
<h2>Canvas: A matter of Events</h2>
<p>The <a href="http://documentation.xojo.com/api/deprecated/canvas.html">Canvas class</a> provides all the needed Events you probably would want to implement in order to react to the user interaction. These are listed and described in the available documentation online and as part of the Xojo IDE interactive Help.</p>
<p>While you can drag and drop a Canvas instance directly to your project layout window or view, implementing and writing the code associated with  any of the available Events, the recommended way to go is to create your own subclass taking as its parent the Canvas class. This way, you can implement and fine-tune every aspect that makes you control unique and, most importantly, re-use your customized UI controls as many times you want both in current and future projects (or even <a href="https://documentation.xojo.com/Resources:Free_Source_Code_and_Tools">offer them</a> to the Xojo community or <a href="https://www.xojo.com/store/#addons">sell them</a> to other developers!).</p>
<p>As you probably already know, in an <b>OOP programming language</b>, subclassing is the method to get a specialized behavior from an existing Class: We get for free all the available properties, methods and events from the parent (and all its parent hierarchy), including also the code executed in the Paint event to truly paint or provide its look on screen; so we just need to implement the specific behavior and/or control drawing/painting we need over these.</p>
<p>This is also the way to go when you are in the inital stages of designing your own customized UI control: will you need to create even more specialized behaviors based on a &#8220;parent&#8221; or base customized control? Maybe variations on the behavior? In cases like these, you should define your UI control base class at the bare-minimum set of painting, behavior (events and methods) and properties that will be shared from all the future UI Controls inherited from your base/parent UI Control class. (i.e: more specialized or with behavior variations).</p>
<p>Creating a subclass in Xojo is truly simple: just drag and drop the Canvas icon from the <b>Library</b> to the <b>Navigator</b> (the leftmost column in the Xojo IDE), or choose <code>Insert &gt; Class</code> from the Insert menu.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-5650 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2019/04/Canvas-Library.png" alt="" width="260" height="317" /></p>
<h2>Points vs Pixels: HiDPI and Retina</h2>
<p>Once you have added the new Class to your project, select it, go to the Inspector and set the name you want to use for your new Class (using a &#8220;company&#8221; or personal prefix it&#8217;s always a good idea to avoid collision with other existing or future classes in the Xojo Framework, or when using third party classes). Then, in the <b>Super</b> field of the Inspector Panel, type <code>Canvas</code> and confirm the entry. You&#8217;ll see how your class icon changes to the one that uniquely identifies Canvas based classes and instances. The most important thing: your new subclass will have all the properties, events and methods you may expect from a Canvas.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-5651 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2019/04/Subclase-Canvas.png" alt="" width="261" height="234" /></p>
<p>This will be the base class in our short tutorial for creating a customized button that will change its associated image (picture) when the mouse pointer is inside the button area, outside the button bounds or when the user click on the control. In the last case, the button will change both the image and its internal state represented by a property as a Boolean value (named <code>Status</code>).</p>
<p>As our customized UI control will not draw itself via the Paint event, we will need to design the images so these precisely fit in the size we want to use for our button. In this example a size of 32 x 32 points.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-5652 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2019/04/Sketch-Graficos-1024x650.png" alt="" width="1024" height="650" /></p>
<p>In general, when designing images to use in our Xojo projects we need to change our mindset from thinking in pixels to points. That&#8217;s because Xojo apps do support <b>HiDPI</b> on Windows/Linux and <b>Retina</b> on macOS; that is: hi-def graphics. Thus, it&#8217;s important to use a design tool that simplifies the process. Personally, I use the vectorial app Sktech on macOS because it automates the 2x creation of the final images. (Remember that HiDPI/Retina is enabled by default in the Building Settings on every new Desktop project.)</p>
<p>How do you support HiDPI/Retina if you want to draw the control look on the fly? Avoid the use of pixels in your calculations or when setting the values of the existing Graphic class properties, and use Points instead. If you really need to access the Pixels values underneath, then you can resort to the <code>RGBSurface</code> class (if available) and make use of the <code>ScaleFactorChanged</code> event available on the Canvas class. This way, your class will be notified on every change between displays with or withour Retina/HiDPI support.</p>
<p>Good rule of thumb: do all your control drawing inside the Paint event! And, when you need to update or redraw it (maybe as consequence of some change in the app behavior, or from the change made in other UI control), invoke the method <code>Invalidate</code> instead of <code>Refresh</code>. In general, this will speed up the drawing and, thus, the main app performance.</p>
<h2>If you use an existing Event… Define the Event again</h2>
<p>As our customized class makes use of the <b>Open</b>, <b>MouseEnter</b>, <b>MouseExit</b> and <b>MouseDown</b> Events, we need to make sure we define these events again to the class, so they are also available for the developer using our canvas-based UI subclass. After all, it&#8217;s very probable he needs or wants to add extra code on top of ours! This is something we can do choosing <code>Add to "class_name" &gt; Event definition</code> when our subclass icon is selected in the Navigation Browser.</p>
<p>Thus, once we have created the same events (using the same parameters and returning the same kind of Type values as the original ones), we need to make sure we call them; usually as the last line of code for the already used Event. For example, this is the code for our implementation of the <code>MouseDown</code> event in our Canvas subclass:</p>
<pre>me.Backdrop = if(me.Status = false, ShellRunSelected, ShellRun)
me.Status = not me.Status
return RaiseEvent MouseDown(X, Y)</pre>
<p>Note how, in this case, our implementation of the <code>MouseDown</code> event returns the value returned by the consumer of our subclass instances, called with the <code>RaiseEvent</code> statement. Just remember that returning the <code>True</code> value from this event means that such events will not be propagated further along the Events Chain.</p>
<h2>Putting it all Together</h2>
<p>With this information at hand, and the basic concepts explained, <a href="https://youtu.be/7NYwpdXN-SA">this video</a> (in Spanish) shows how you can join all the needed pieces: pictures, events, definition of already consumed events by the subclass; creating a new very basic control from scratch. Obviously, from this point on, you can find in the available documentation all the information needed to create more complex UI controls based on the Canvas class (WebCanvas or iOSCanvas). The possibilities are limitless!</p>
<p>Other useful topics:</p>
<ul>
<li><a href="https://documentation.xojo.com/topics/user_interface/desktop/desktop_controls/canvas.html">User Guide: Desktop Canvas</a></li>
<li><a href="https://documentation.xojo.com/api/deprecated/canvas.html">Canvas</a>, <a href="https://documentation.xojo.com/api/graphics/graphics.html">Graphics</a> classes</li>
<li><a href="https://documentation.xojo.com/UserGuide:iOS_Canvas">User Guide: iOS Canvas</a></li>
<li><a href="https://documentation.xojo.com/topics/user_interface/web/controls/canvas.html">User Guide: Web Canvas</a></li>
</ul>
<p><em>Javier Rodri­guez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages <a href="http://www.aprendexojo.com">AprendeXojo.com</a> and is the developer behind the GuancheMOS plug-in for Xojo Developers, Markdown Parser for Xojo, HTMLColorizer for Xojo and the Snippery app, among others.</em></p>
<p>*<a href="https://www.aprendexojo.com/2016/10/canvas-crea-tus-propios-controles/">Read this post in Spanish</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Add User Interface Controls at Runtime</title>
		<link>https://blog.xojo.com/2018/01/26/how-to-add-ui-controls-at-runtime/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Fri, 26 Jan 2018 07:10:59 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[AprendeXojo]]></category>
		<category><![CDATA[Control Set]]></category>
		<category><![CDATA[User Interface]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=3770</guid>

					<description><![CDATA[How can I add new UI controls to the Window at runtime? And if you are considering this too, then the good news is that the answer is more simple than you probably expect… sitting right there on the Inspector Panel under the Attributes tab. Yes, this is all about the Control Set!]]></description>
										<content:encoded><![CDATA[<p>Admit it &#8211; this is one of those questions that, sooner or later, arise to every Xojo newcomer: How can I add new UI controls to the Window at runtime? And if you are considering this too, then the good news is that the answer is more simple than you probably expect… sitting right there on the Inspector under the Attributes tab. Yes, this is all about the Control Set!<span id="more-3770"></span></p>
<p>Before we put our hands on it, let&#8217;s make some things clear about the <a href="http://developer.xojo.com/userguide/desktop-control-sets">Control Set</a>:</p>
<ul>
<li>You can use this feature to dynamically create any kind of control based on the <a href="http://developer.xojo.com/userguide/desktop-control-sets"><b>RectControl</b></a> class.</li>
<li>You can use Control Sets on <b>Desktop</b> and <b>Web</b> projects (although web projects cannot use Control Sets to dynamically create controls at runtime).</li>
<li>You cannot create Control Sets for Container Controls.</li>
<li>The Control Sets may seem like Arrays, because you will use an <b>index</b> to refer every instance from the same Control Set, but they are not. So, don&#8217;t think about them in that way.</li>
<li>All of the instances of the Control Set will share the same <b>Event Handlers</b>, so you will have to use the additional <b>index</b> argument, passed to the Event Handler, in order to identify over which instance are you handling.</li>
</ul>
<p>But, how can we create one of these Control Set after all? Well, we just need to put any control we want to use as a <em>clonation template</em> on the Window, even if it is placed outside the visible limits of the Window itself. Then, and with the control still selected, you just have to push on the attributes button (the one with the image of a gearwheel) on the Inspector, selecting the <code class="inlinecode">New Control Set</code> option from the <code class="inlinecode">Member Of</code> entry under the <code class="inlinecode">Control Set</code> Section.</p>
<blockquote><p><b>Tip</b>: If you change the name of the Control used to create a Control Set, then you will have to recreate the Control Set, so rename the template Control in the first place!</p></blockquote>
<p>Once you have created the new Control Set, you will see that the first instance of the Control Set is assigned the <b>index</b> number 0; succesive instances will have their index increassed by one, both the ones you may add to the Window (not what we want to do in this case), and those created at runtime (what we want to do).</p>
<p>Now, probably you will want to change the <code class="inlinecode">Visibility</code> Property to <code class="inlinecode">False</code> on this first cloning template control, so it will not be visible to the users of the app no matter the resizing of the containing Window.</p>
<p>Once our cloning control is all set, it’s time to reveal all the code we will need in order to create new instances of the control at run time. Let’s indicate that we have used as cloning template Control a PushButton and that we have named it <code class="inlinecode">btClon</code>. Then, we just need this to create a new instance, making it visible on the Window:</p>
<pre>Dim newInstance as PushButton = new btClon
newInstance.visible = true</pre>
<p>Remember that every <b>UI</b> component is based on (<em>inherits from</em>) the RectControl class, so you also can do this:</p>
<pre>Dim newInstance as RectControl = new btClon
PushButton(newinstance).visible = true</pre>
<p>As you can see, the difference is that in this case you have to <a href="http://developer.xojo.com/userguide/advanced-oop-features"><b>Cast</b></a> the generic RectControl instance to the PushButton class in order for you to use and access all the PushButton methods and properties from code.</p>
<p>Why should you use this formula, then? Well, if you are thinking about creating several Types of UI components at runtime, then you will probably prefer to create them using a more generic RectControl variable or reference (maybe a RectControl Array containing all of your dinamically created controls).</p>
<p>As you may expect, the new instances created from a template will have the same properties, events and methods the template control has, with the difference that it will also inherit the clone properties values. This is why once a new instance is created we need to make it visible again and you will want to change other properties too, for example the <code class="inlinecode">Caption</code> and the <code class="inlinecode">Left</code> and <code class="inlinecode">Top</code> properties among others.</p>
<h2>Modifying the Z axis order of the Control</h2>
<p>We already know that every new created instance of the Control Set gets its index increased by one. What you have to know is that every new instance is above the previous one on the Z axis of the Window. I mean, if the control with the <code class="inlinecode">Index</code> set to 2 partially overlays the position of the control with the <code class="inlinecode">Index</code> 1, then the first one will overlay the second. What if you decide to have a control with a low index value above the others?</p>
<p>Currently there is no easy way we can dynamically change the Z order of a control to any desired value, but there is an easy way we can move any control to the foreground, so it can stay in front of all of them!</p>
<p>Let’s say that we have our cloned control with the <code class="inlinecode">Index</code> 1 and want to show it in the foreground, with the highest possible value in the Z axis. All we have to do is assign it to another RectControl as its <code class="inlinecode">parent</code> property value, for example the control we are using as cloning template. Once done, we will assign the Window again as the <code class="inlinecode">parent</code> property value of the control. The code could be something similar to this:</p>
<pre>btClon(2).parent = btClon(0)
btClon(2).parent = Window1 //Or Self or Me, depending where you place the code</pre>
<p>In conclusion, as you can see, the creation of UI controls at runtime is something really easy to do in Xojo! But what if you need to dynamically add a group or layout of control at runtime? Well, in that case don&#8217;t forget about the <a href="https://blog.xojo.com/2017/04/26/containercontrol-making-a-multiplatform-search-field/" target="_blank" rel="noopener">ContainerControls</a>!</p>
<p><em>Javier Rodri­guez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages <a href="http://www.aprendexojo.com">AprendeXojo.com</a> and is the developer behind the GuancheMOS plug-in for Xojo Developers and the Snippery app, among others.</em></p>
<p>*<a href="https://www.aprendexojo.com/2018/01/anadir-controles-de-ui-en-tiempo-de-ejecucion/">Read this post in Spanish</a></p>
<p>*<a href="https://www.youtube.com/watch?v=9NAap4Ipmnc">Watch the video in Spanish</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>THIS IS NOT A DRILL: Poor Interface Design and its Potentially Dangerous Impact</title>
		<link>https://blog.xojo.com/2018/01/16/this-is-not-a-drill-poor-interface-design-and-its-potentially-dangerous-impact/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Tue, 16 Jan 2018 22:08:58 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[User Interface]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=3728</guid>

					<description><![CDATA[This warning, as well all now know, turned out to be a false alarm accidentally set off by a state employee who was attempting to perform an internal test. Let's please not spend $1 million or more of the taxpayer's hard-earned money on a $100 fix. With this simple, 5 minute fix, it would be nearly impossible for someone to accidentally send out a warning when they meant to only perform an internal test.



The first thing that went through my mind was how exactly is such an important function of a state emergency management system triggered so easily that it could be done by accident? It is my hope that every member of every similar emergency management team around the world with a similar system is rechecking that system now to see how poorly or well-designed their user interface is.]]></description>
										<content:encoded><![CDATA[<p>As most of you know, this past Saturday morning, the people of Hawaii got a shocking notification on their smartphones warning of a <strong>incoming ballistic missile</strong> and that this warning was <strong>not a drill</strong>. I can only imagine the fear that raced through the minds of more than a million people. This warning, as well all now know, turned out to be a false alarm accidentally set off by a state employee who was attempting to perform an internal test.</p>
<p><span id="more-3728"></span></p>
<p>The first thing that went through my mind was how exactly is such an important function of a state emergency management system triggered so easily that it could be done by accident? Did a radar system show an incoming missile that was later discovered to be a mistake? No. As the Washington Post <a href="https://www.washingtonpost.com/news/post-nation/wp/2018/01/14/hawaii-missile-alert-how-one-employee-pushed-the-wrong-button-and-caused-a-wave-of-panic/?utm_term=.db7f46a108c3">reported</a>, the user interface for the system has a drop down menu with two items: <em>Test Missile Alert</em> and <em>Missile Alert</em>. The facts that these two options are so similarly named and that there is no confirmation dialogue for such an important command is at a minimum bad user interface design.</p>
<p>If I want do something as relatively innocuous as erasing all the data from my iPhone, I have to first find the feature that does this buried two levels deep in the Settings app where it&#8217;s clearly titled, &#8220;Erase All Contents and Settings.&#8221; Tapping it displays a dialog box asking me if I want to <em>Backup Then Erase</em> or just go ahead and <em>Erase Now</em>. If memory serves from the last time I did this, choosing Erase Now then reconfirms that I truly do want to erase all the contents and settings on my iPhone. That&#8217;s a lot of steps to accomplish a task that only affects one person: me. However, considering the magnitude of the result, it makes good sense that the user interface doesn&#8217;t make this very easy to do and actual makes sure you are deliberately trying to erase your phone.</p>
<p>Hawaii&#8217;s emergency management system does none of this. There apparently are just two menu items, one next to the other and once chosen, the computer immediately completes the task without confirmation. That&#8217;s just astonishing. What&#8217;s even worse, however, than the poor interface design on the part of whomever designed it, is that at a minimum (a) someone had to accept this poor interface design, (b) others had to use it without complaint that it could potentially cause the very situation it has caused.</p>
<p>The Chairman of the FCC wants an an <a href="https://www.commondreams.org/news/2018/01/15/will-ajit-pais-fcc-probe-hawaii-false-alarm-expose-role-telecom-giants-played">expensive investigation</a>. Let&#8217;s please not spend $1 million or more of the taxpayer&#8217;s hard-earned money on a $100 fix. First, these two menu items should be reduced to a single menu item entitled, &#8220;Missile Alert&#8230;&#8221; The ellipsis tells the user that before this item performs its function, a dialog will be displayed to confirm it. The dialog that appears should be on that requires deliberate actions by the user to initiate a true warning to the population of Hawaii:</p>
<p><img loading="lazy" decoding="async" class="alignleft size-full wp-image-3738" src="https://blog.xojo.com/wp-content/uploads/2018/01/Screen-Shot-2018-01-16-at-3.39.55-PM.png" alt="" width="1000" height="390" /></p>
<p>&nbsp;</p>
<p>In the above example dialog box notice that in order to initiate a real warning, the user will not only have to uncheck the &#8220;Internal Test Only&#8221; checkbox but also have to deliberately click the Proceed button as the Cancel button is the default.</p>
<p>After taking those two deliberate actions, the user is then presented with a second dialog box to confirm that requires again clicking the Proceed button, another deliberate action.</p>
<p>&nbsp;</p>
<p><img loading="lazy" decoding="async" class="alignleft size-full wp-image-3746" src="https://blog.xojo.com/wp-content/uploads/2018/01/Screen-Shot-2018-01-16-at-4.52.11-PM.png" alt="" width="1128" height="408" /></p>
<p>With this simple, 5 minute fix, it would be nearly impossible for someone to accidentally send out a warning when they meant to only perform an internal test.</p>
<p>Not all user interfaces have functions with such wide-reaching results. However, user interface guidelines for many years now have said that <strong>an action that cannot be undone should be confirmed</strong>. That&#8217;s a simple rule that all of us that design user interfaces would do well to remember.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>First Impressions Matter: 8 Surefire User Interface Design Tips</title>
		<link>https://blog.xojo.com/2017/07/20/first-impressions-matter-8-surefire-user-interface-design-tips/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 20 Jul 2017 06:52:05 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[User Interface]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=2699</guid>

					<description><![CDATA[With today's development tools, it's easy to create user interfaces for your apps. Here are 8 tips to help ensure you create UIs that your users will love.]]></description>
										<content:encoded><![CDATA[<p>Your app&#8217;s user interface makes the first impression with your user and is vitally important to its success. With today&#8217;s modern development tools, it&#8217;s easy to create great <a href="https://en.wikipedia.org/wiki/User_interface_design">user interfaces</a> for your app.</p>
<p>Here are 8 proven tips to help ensure you create a user interface that your users will love.</p>
<p><span id="more-2699"></span></p>
<p><strong>1. Limit choices.</strong><br />
Don’t provide an overwhelming number of options or preferences for your users. Too many choices can be intimidating and confusing and can make people not enjoy using your app. Your job is to design the software, which means choosing what it should do. Don&#8217;t take the easy way out and provide loads of options for your users all at one time.</p>
<p><strong>2. Be familiar.</strong><br />
Sometimes you may need to implement an entirely new user interface metaphor in order to design your app. But typically this is unnecessary. Though it can be fun creating new and snazzy UI layouts, your users will likely not appreciate them much. Why? Because they won’t understand them or won’t know how to use them. A unique UI design isn&#8217;t always practical &#8211; stick to what people are familiar with.</p>
<p><strong>3. Be consistent.</strong><br />
Your app should be consistent within itself. Don’t use UI controls in different ways on different screens because that is just confusing. For example, don&#8217;t use buttons on one screen to indicate actions, but then use link text on another screen to indicate the same action.</p>
<p><strong>4. Put the user in charge.</strong><br />
Let the user feel like they are controlling the software. This means don’t force them down a single path to solve something. Let them try things and make mistakes. Have an undo feature so that they can easily fix their mistakes.</p>
<p><strong>5. People can&#8217;t.</strong><br />
Don’t spend time writing long text for the user as they likely won’t read it. Keep the language short and simple. Make it easy for people to enter text because they are not good at it. If the user has to enter lots of text, give them lots of room, enable a spell checker and use a larger font to make it easier for them to read the text.</p>
<p>Make your UI targets easy to find and use because people can’t control the mouse, trackpad or even their finger for touch devices. And lastly, users likely won’t remember how they did something the last time, so make it easy to figure out.</p>
<p><strong>6. Design first.</strong><br />
Have a design process &#8211; it doesn’t need to be anything complex. Sketching designs on paper or a whiteboard is a great way to get a feel for things. Software to mockup UI designs (such as <a href="http://balsamiq.com/" target="_blank" rel="noopener noreferrer">Balsamiq</a>) can also be quite useful. You can also use development tools like Xojo to mockup UI designs, but be careful not to make your mockup too functional or the users might think it is nearly complete!</p>
<p><strong>7. Time is relative.</strong><br />
Users perceive time differently than you might expect. For example, they typically hate waiting for tasks to complete. But if you make it seem like they are not waiting, they often don’t notice how long a task takes. For example, if your main window takes 5 seconds to appear, that will irritate your users. If you instead display the window immediately with a loading indicator, users are far less likely to notice the delay. In general, users more easily notice delays when the UI becomes unresponsive so try to minimize that.</p>
<p>Also keep in mind that features you have spent a large amount of time creating may only be used for a very short period of time. Don’t let yourself become comfortable with a difficult design because you use it frequently.</p>
<p><strong>8. Help out.</strong><br />
Your app should provide assistance to your users. Tips and guides are a great way to gently remind users how to use your software. It’s also a great idea to provide default data for the first launch of your app so that users can see how it is actually used in the real world. Another strategy is to prevent the user from making a mistake in the first place. Disable things when they cannot be used and enable them when they can be used.</p>
<p>For more tips like these, I recommend <a href="http://www.apress.com/us/book/9781893115941">User Interface Design for Programmers by Joel Spolsky</a>.</p>
<p>If you want to try your next app in Xojo, <a href="http://www.xojo.com/download/">download</a> it free anytime.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
