<?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>Raspberry Pi &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/category/cross-platform/raspberry-pi/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Tue, 25 Mar 2025 15:54:45 +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>Xojo IDE on Pi: A Game-Changer in Embedded Development</title>
		<link>https://blog.xojo.com/2025/03/25/xojo-ide-on-pi-a-game-changer-in-embedded-development/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 15:33:47 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[2025r1]]></category>
		<category><![CDATA[ARM64]]></category>
		<category><![CDATA[Embedded Development]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14616</guid>

					<description><![CDATA[Prior to Xojo 2025r1, Raspberry Pi developers had to rely on a two-step process: programming on a separate computer that could run the Xojo IDE,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Prior to Xojo 2025r1, Raspberry Pi developers had to rely on a two-step process: programming on a separate computer that could run the Xojo IDE, then either remotely debugging the app on the Pi or manually copying the executable over. While this worked, it added extra steps and potential complexities, especially when dealing with debugging and deployment.</p>



<h2 class="wp-block-heading">Introducing the Xojo IDE for Linux ARM64</h2>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="548" src="https://blog.xojo.com/wp-content/uploads/2025/03/XojoIDEonRPi-1024x548.png" alt="" class="wp-image-14620" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/XojoIDEonRPi-1024x548.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/XojoIDEonRPi-300x160.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/XojoIDEonRPi-768x411.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/XojoIDEonRPi-1536x821.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/XojoIDEonRPi-2048x1095.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">8GB Raspberry Pi 5, running Bookworm</figcaption></figure>



<p>With the release of Xojo 2025r1, however, everything has changed. Now, for the first time, developers can run the Xojo IDE directly on their Raspberry Pi 64-bit device. This means you can write, build, and test your applications all from within the same environment. The seamless integration allows for faster iteration and a smoother workflow, giving you more control over your development process. Not only can you now run the Xojo IDE on a Pi, but also on any Linux ARM64 distro.</p>



<h2 class="wp-block-heading">What is Supported?</h2>



<p>Nearly all the features you love about working in the Xojo IDE on other platforms are now available with the Linux ARM64 IDE, with the exception of building macOS and Mobile (Android/iOS) apps. Instead of remotely debugging your Raspberry Pi app using the Xojo IDE on Windows, you can now remotely debug your Windows app using the Xojo IDE on Pi!</p>



<p>For best results, we recommend a Raspberry Pi 5 or 500 with 8GB of RAM.</p>



<h2 class="wp-block-heading">Xojo Loves Pi!</h2>



<p>With the <a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Xojo</a> IDE now available for Linux ARM64, we&#8217;re making our case as the go-to solution for Raspberry Pi developers. The simplicity, cross-platform support, and power makes Xojo an attractive choice for those looking to build apps on the Pi, without the complexity of traditional programming environments.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>NOTE:</strong> You can build Linux apps with Xojo <a href="https://blog.xojo.com/2024/03/26/version-control-ready-xojo-lite-and-free-xojo-lite-linux-for-everyone/#free-linux" target="_blank" rel="noreferrer noopener">for free</a>, no license required. Just select Linux in Build Settings, then choose ARM or x86 architecture in the Inspector.</p>
</blockquote>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></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>Spotlight On: Tim Dietrich</title>
		<link>https://blog.xojo.com/2025/03/10/spotlight-on-tim-dietrich/</link>
		
		<dc:creator><![CDATA[Alyssa Foley]]></dc:creator>
		<pubDate>Mon, 10 Mar 2025 16:00:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[FileMaker]]></category>
		<category><![CDATA[NetSuite]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14631</guid>

					<description><![CDATA[Spotlight On posts focus on Xojo community members. We’ll use this space to tell the stories of people using Xojo, share amazing Xojo-made apps and&#8230;]]></description>
										<content:encoded><![CDATA[
<p><em>Spotlight On posts focus on Xojo community members. We’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,&nbsp;<a href="mailto:hello@xojo.com" target="_blank" rel="noreferrer noopener">tell us about it</a>!</em></p>



<p>I&#8217;ve had the pleasure of working with Tim multiple times over nearly 10 years now. Tim is one of those people who makes a community, he&#8217;s a connector, bringing people into a group and highlighting common ground for the benefit of us all. It&#8217;s not hard to find out what Tim is doing these days, you can read all about it on his blog, watch his videos and webinars and read his Xojo interview series in xDev Magazine. In this month&#8217;s Spotlight On feature, Tim answers questions about his latest, and biggest, project and his ongoing success using Xojo.</p>



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



<p>All three.</p>



<p>I do all of my work on a MacBook Pro. That&#8217;s where I&#8217;m running the Xojo IDE, doing testing, and so on. But I&#8217;m developing apps that also run on Windows and Linux, too. When I&#8217;m developing a Windows app, I usually do my initial testing using a Windows VM running in Parallels. Over the past few years, the amount of Linux projects that I work on has increased significantly. I&#8217;m developing a lot of console apps that run on Linux.</p>



<p>Here&#8217;s something that I discovered about a year ago, and that your readers might find interesting. Xojo apps that are compiled for Linux (Linux x86 64-bit in particular) will run on servers that are running Oracle&#8217;s &#8220;Oracle Linux Server&#8221; operating system. Oracle&#8217;s cloud (which they call &#8220;Oracle Cloud Infrastructure&#8221; or &#8220;OCI&#8221; for short) run that version of Linux, which is similar to Fedora. A lot of companies that are running on NetSuite (which Oracle owns) are &#8220;all in&#8221; with OCI. So the fact that Xojo apps can be compiled to run on OCI servers is a pretty big deal. I think there&#8217;s a lot of opportunity for Xojo developers to meet the demand for custom software coming from companies that are in investing in OCI.</p>



<h3 class="wp-block-heading"><strong>What do you wish more people would ask/talk to you about regarding programming?</strong></h3>



<p>I have a pretty popular blog, and I do get a lot of technical questions from readers. Occasionally, I get questions like &#8220;How can I break into the NetSuite space?&#8221; What they&#8217;re really asking about are strategies for finding opportunities, technical things that they should learn about, and so on. </p>



<p>But it&#8217;s the non-technical things that they don&#8217;t ask about that I think are really important. For example, learning about business in general. Learning about accounting. And if they&#8217;re looking to &#8220;go solo,&#8221; learning how to build authority, stay organized, and so on.</p>



<h3 class="wp-block-heading"><strong>How would you explain your most recent project to a new developer?</strong></h3>



<p>One of the biggest challenges that companies face when they&#8217;re switching from one business system to another is migrating data between the two systems. Some companies think that this is the final step before &#8220;going live&#8221; with the new system &#8211; and it certainly is.</p>



<p>But the reality is that they&#8217;ll likely need to do this data migration several times, especially as they test the new system. In some cases, they&#8217;ll run the two systems in parallel and compare the results of the two systems, to make sure the new system is being implemented correctly.</p>



<p>I&#8217;m currently working on a very large, very complicated NetSuite implementation, and we ran into this need. Using Xojo, I developed an app called the &#8220;Data Bridge&#8221; which we&#8217;re using to sync data between their current system (which was developed using Progress &#8211; https://progress.com) and their NetSuite instance. It takes data that was exported from Progress as pipe-delimited files, parses and validates the data, and then makes API calls to push the data into NetSuite. This is helping us test NetSuite more thoroughly, using current, real data, so that there will be no surprises when we do go live.</p>



<h3 class="wp-block-heading"><strong>What’s next on your “Learn Next” list?</strong></h3>



<p>For the longest time, I&#8217;ve felt that AI &#8211; and especially generative AI &#8211; is overhyped. So I mostly ignored it. Now that the excitement has settled down a bit, I&#8217;ve started to look at AI in a serious way. NetSuite recently made some generative AI APIs available to developers, so I&#8217;ve been experimenting with those. One of the projects that I&#8217;m currently working on involves developing a Xojo-based mobile app that integrates with NetSuite, leveraging the data stored in NetSuite as well as its AI functionality.</p>



<h3 class="wp-block-heading"><strong>What is something that has surprised you about coding in the last 10 years?</strong></h3>



<p>I think that like a lot of developers that have been working professionally for awhile, I was surprised by the popularity of Javascript, and how widespread it&#8217;s used, especially for developing backend Web apps. The other thing that has surprised me is the increasing number of developers that really don&#8217;t want to write code. There seem to be a lot of people that pursue careers in software development simply because they think it&#8217;s a way to &#8220;make big money.&#8221; One of the things that<br>I love about the Xojo community is that most of the Xojo developers that I&#8217;ve talked to seem to find joy in writing code. (You can also see this on the Forum, too.)</p>



<h3 class="wp-block-heading"><strong>Xojo isn’t the only tool in your kit. What is a piece of software more people should know about?</strong></h3>



<p>There are a couple of other development tools that I use and recommend, and that I encourage other Xojo developers to check out.</p>



<p>One is <a href="https://www.jetbrains.com/datagrip/" target="_blank" rel="noreferrer noopener">DataGrip</a> by JetBrains, which I started using about a year ago. DataGrip is a cross- platform database tool that supports a very wide range of relational databases. I use it often in my NetSuite work, especially when I need to explore the schema of the Oracle database that a NetSuite instance is powered by. </p>



<p>Another tool that I recommend is <a href="https://rapidapi.com/" target="_blank" rel="noreferrer noopener">RapidAPI</a> (which was formerly known as &#8220;Paw&#8221;). I&#8217;ve been using RapidAPI since it was first released, and it&#8217;s my API tool of choice. There&#8217;s another API tool called &#8220;Postman&#8221;that is certainly much more popular, but I really prefer RapidAPI. It seems to me to be much more Mac-like. </p>



<p>One more tool that I want to mention &#8211; and this one is brand new &#8211; is called &#8220;<a href="https://apps.apple.com/us/app/framous-screenshot-frames/id6636520519?mt=12" target="_blank" rel="noreferrer noopener">Framous</a>.&#8221; Framous makes it easy to add device frames around screenshots. So you can take a screenshot of an app &#8211; such as one running on your Mac or in a simulator &#8211; and then drop the screenshot into a device frame &#8211; such as a Mac or iPhone. It&#8217;s great for creating images to be used for marketing purposes. The app is available on the Mac App Store.</p>



<h3 class="wp-block-heading"><strong>When did you start using Xojo?</strong></h3>



<p>I started using Xojo in August of 2015 &#8211; nearly 10 years ago!</p>



<h3 class="wp-block-heading"><strong>How did you find Xojo?</strong></h3>



<p>Hal Gumbert encouraged me to check out Xojo, and I&#8217;m so glad that he did. At the time, we were both FileMaker developers. I had grown frustrated with the FileMaker platform and was looking for a new development tool to work with.</p>



<h3 class="wp-block-heading"><strong>What did you first&nbsp;build with Xojo?</strong></h3>



<p>When I first started working with Xojo, I was interested in developing iOS apps &#8211; and Xojo&#8217;s support for the iOS framework had just been released. So the timing was perfect. In fact, then first Xojo license that I purchased was only for iOS. There were two iOS apps that I immediately developed with Xojo. One integrated with FileMaker and the other integrated with Airtable. (At the time, I was serving as Airtable&#8217;s &#8220;Developer Evangelist.&#8221;)</p>



<h3 class="wp-block-heading"><strong>What do you build with it now?&nbsp;</strong></h3>



<p>I now use Xojo to develop all kinds of apps &#8211; desktop, mobile, Web, and console apps &#8211; and for all of the platforms that Xojo supports too (macOS, Windows, Linux, iOS, and Android). When I first started using Xojo, I never would have guessed that someday I&#8217;d be developing so many different types of apps.</p>



<p>It surprises me that out of all of the types of apps that I develop with Xojo, these days it&#8217;s Linux console apps that I&#8217;m developing the most. These apps are primarily used to automate processes involving NetSuite, such as batch file processors, webhook listeners and senders, and more. So essentially I&#8217;m using Xojo &#8211; and console apps especially &#8211; to extend NetSuite&#8217;s capabilities.</p>



<h3 class="wp-block-heading"><strong>What is something you worked on recently that you want to talk about?</strong></h3>



<p>I mentioned a few of my current projects earlier, but two of the more interesting projects that I&#8217;m working on are Suite.js (a JavaScript runtime that’s designed to make NetSuite integration easy) and SuiteBrowser (a Web browser designed specifically for use with NetSuite). Both of those projects might sound like crazy ideas. I mean, what kind of crazy person develops their own web browser?!? But I can tell you, based on the level of interest in them from the NetSuite community, that there&#8217;s a genuine need for both of them.</p>



<h3 class="wp-block-heading"><strong>Do you earn a living with Xojo?&nbsp;</strong></h3>



<p>Absolutely. So much of my work these days &#8211; including my NetSuite work &#8211; involves Xojo. I honestly don&#8217;t know what I&#8217;d do without it.</p>



<p>Also, I want to give a shout out to Christian Schmitz and <a href="https://www.monkeybreadsoftware.de/xojo/">MonkeyBread Software</a>. His Xojo plug-ins have enabled me to work on Xojo projects that I never would have dreamed of working on, including projects that utilize things like MQTT, Phidgets, and more.</p>



<h3 class="wp-block-heading"><strong>Do you use it for your hobbies?&nbsp;</strong></h3>



<p>Yes, I do. My main hobby these days is developing apps that run on Raspberry Pi&#8217;s, and of course, I&#8217;m using Xojo to create them. As a side note, I recently purchased my fifth Raspberry Pi &#8211; a Raspberry Pi 500 &#8211; and I love working with it. It reminds me what it was like to use Macs and PCs &#8220;back in the day.&#8221;</p>



<h3 class="wp-block-heading"><strong>What’s your biggest Xojo success?</strong></h3>



<p>Out of all of the apps that I&#8217;ve developed with Xojo, the one that I use every day is called SuiteTransmit. SuiteTransmit is a desktop app that monitors the files that I&#8217;m working on, detects changes to them, and automatically uploads them to NetSuite. It allows me to develop NetSuite &#8220;SuiteScript&#8221; apps using my preferred IDE (BBEdit). This simple app, which, thanks to Xojo, took only a few hours to develop, has saved me a lot of time. SuiteTransmit is one of my &#8220;secret weapons,&#8221; and I don&#8217;t think I could have, or would have ever even attempted to develop it, without Xojo.</p>



<p>But my biggest &#8220;Xojo success&#8221; doesn&#8217;t involve any one particular app that I&#8217;ve developed with it. Over the years, I&#8217;ve blogged about my Xojo work, and been a guest on several Xojo webinars. Last summer, a company that was looking for help implementing NetSuite stumbled upon my NetSuite / Xojo work, liked what they saw, and reached out to me for help. They&#8217;re now my biggest client, and the biggest client I&#8217;ve had throughout my entire career. And I owe that to Xojo.</p>



<p><em>Thank you to Tim Dietrich for answering questions and sharing his Xojo experience with the community.&nbsp;Learn more about&nbsp;<a href="https://timdietrich.me/">Tim on his blog</a>, find him on <a href="https://www.linkedin.com/in/tim-dietrich/">LinkedIn</a></em> and read his interviews in <a href="https://xdevmag.com/">xDev Magazine</a>.</p>



<p><em>If you have an app, a project or a person you want to see featured in Spotlight On,&nbsp;<a href="mailto:hello@xojo.com" target="_blank" rel="noreferrer noopener">tell us about it</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>



<ul class="wp-block-list">
<li><a href="https://www.facebook.com/goxojo" target="_blank" rel="noreferrer noopener"></a></li>
</ul>
]]></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 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="(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>Don&#8217;t throw that Pi into the garbage</title>
		<link>https://blog.xojo.com/2024/03/26/dont-throw-that-pi-into-the-garbage/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 26 Mar 2024 15:27:20 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2024r1]]></category>
		<category><![CDATA[Bookworm]]></category>
		<category><![CDATA[DesktopHTMLViewer]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Pi]]></category>
		<category><![CDATA[Workaround]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12692</guid>

					<description><![CDATA[The most recent iteration of Pi, operating on the Bookworm OS, may cause Xojo's DesktopHTMLViewer to appear like garbage, but that's no reason to discard either the Pi or Xojo!]]></description>
										<content:encoded><![CDATA[
<p>The most recent iteration of Pi, operating on the Bookworm OS, may cause Xojo&#8217;s DesktopHTMLViewer to appear like garbage, but that&#8217;s no reason to discard either the Pi or Xojo!</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="602" height="461" src="https://blog.xojo.com/wp-content/uploads/2024/03/DesktopHTMLViewerOnPi5.png" alt="" class="wp-image-12694" srcset="https://blog.xojo.com/wp-content/uploads/2024/03/DesktopHTMLViewerOnPi5.png 602w, https://blog.xojo.com/wp-content/uploads/2024/03/DesktopHTMLViewerOnPi5-300x230.png 300w" sizes="auto, (max-width: 602px) 100vw, 602px" /></figure>
</div>


<p>If you&#8217;re encountering display anomalies with the DesktopHTMLViewer on a Pi 5 running Bookworm OS, rest assured you&#8217;re not alone. This issue stems from the version of WebKitGTK the DesktopHTMLViewer relies on.  While efforts to address this persist, a viable workaround exists: disabling hardware acceleration when utilizing WebKitGTK.  Fortunately, in Xojo, we&#8217;ve facilitated this by exposing an environment variable.  You can conveniently set this variable before the creation of the DesktopHTMLViewer, such as within your App.Opening event.</p>



<p>To turn hardware acceleration OFF, you can assign that to the WEBKIT_HARDWARE_ACCELERATION environment variable:</p>



<pre id="Xojo" class="wp-block-code"><code>System.EnvironmentVariable("WEBKIT_HARDWARE_ACCELERATION") = "OFF"</code></pre>



<p>By default, hardware acceleration is enabled/disabled as requested by web contents, but you can also force hardware acceleration to be enabled even for websites not requesting it:</p>



<pre id="Xojo" class="wp-block-code"><code>System.EnvironmentVariable("WEBKIT_HARDWARE_ACCELERATION") = "ON"</code></pre>



<p>To revert it to its default state, simply assign any value other than ON/OFF. While we remain optimistic that this issue will be resolved at some point, in the interim, this environment variable stands ready to function as a temporary solution.</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></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>Graphic Charts for Xojo Desktop and Mobile</title>
		<link>https://blog.xojo.com/2023/03/28/graphic-charts-for-xojo-desktop-and-mobile/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 28 Mar 2023 11:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Charts]]></category>
		<category><![CDATA[Data Visualization]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Graphing]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Xojo Code]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11320</guid>

					<description><![CDATA[Graphic Charts support is new in Xojo Desktop and Xojo Mobile (iOS) in Xojo 2023r1. Graphic Charts offer a similar look and behavior to what you find when using Xojo's WebChart control in web projects. Let's review all the things you can do with the new DesktopChart in your desktop projects, and new MobileChart in your iOS projects.]]></description>
										<content:encoded><![CDATA[
<p>Graphic chart support is new in Xojo Desktop and Xojo Mobile (iOS) in Xojo 2023r1. The new DesktopChart and MobileChart offer a similar look and behavior to what you find when using Xojo&#8217;s WebChart. Let&#8217;s review all the things you can do with the new DesktopChart and MobileChart in your Xojo projects.</p>



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



<p>Just as with Xojo&#8217;s <a href="https://documentation.xojo.com/api/user_interface/web/webchart.html#webchart">WebChart</a>, <a href="https://documentation.xojo.com/api/user_interface/desktop/desktopchart.html">DesktopChart</a> and <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilechart.html">MobileChart</a> offer the following chart types: Line, Bar, Pie, Doughnut, PolarArea, Scatter, Bubble and Radar. You can access these charts using the Inspector Panel or via code through the Mode property. You can even change the Mode (or chart type) at runtime on Desktop and Mobile.</p>


<div class="wp-block-image size-large wp-image-11322 is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="641" src="https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeDesktop-1024x641.png" alt="" class="wp-image-11322" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeDesktop-1024x641.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeDesktop-300x188.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeDesktop-768x481.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeDesktop-1536x962.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeDesktop.png 2032w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">DesktopChart Mode set in the Inspector Panel.</figcaption></figure>
</div>

<div class="wp-block-image size-large wp-image-11323 is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="832" src="https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeiOS-1024x832.png" alt="" class="wp-image-11323" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeiOS-1024x832.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeiOS-300x244.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeiOS-768x624.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeiOS-1536x1248.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartModeiOS.png 1758w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">MobileChart Mode set in the Inspector Panel.</figcaption></figure>
</div>


<p>Line and Bar types are similar; both display sets of data that have been set to Line or Bar Modes. Display as many data sets as you need in your DesktopChart or MobileChart by setting the Mode to Line or Bar.&nbsp;The only difference is how these will be displayed along the x axis.</p>



<p>To better understand, let&#8217;s write some code in the Opening Event Handler of a DesktopChart control added to a Desktop project:</p>



<pre class="wp-block-code xojo"><code><code>Var labels() As String
Var firstSetOfData() As Double
Var secondSetOfData() As Double
Var thirdSetOfData() As Double

For n As Integer = 0 To 9
  labels.add "LB"+n.ToString
  firstSetOfData.add System.Random.InRange(0,1000)
  secondSetOfData.add System.Random.InRange(0,1000)
  thirdSetOfData.add System.Random.InRange(0,1000)
Next

Me.mode = DesktopChart.Modes.Line
Me.Title = "Chart Example With Two Datasets"
Me.AddLabels labels

Var DS1 As New ChartLinearDataset("DS1", Color.Blue, True, firstSetOfData)
DS1.ChartType = ChartLinearDataset.ChartTypes.Line

Var DS2 As New ChartLinearDataset("DS2", Color.Red, True, secondSetOfData)
DS2.ChartType = ChartLinearDataset.ChartTypes.Bar

Var DS3 As New ChartLinearDataset("DS2", Color.Green, True, thirdSetOfData)
DS3.ChartType = ChartLinearDataset.ChartTypes.Bar

Me.AddDatasets DS1, DS2, DS3</code></code></pre>



<p>This is how it will look when the Chart has been set to Line, displaying three data sets: one of which has been set to Line and the other two to Bar:</p>


<div class="wp-block-image size-large wp-image-11321 is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="777" src="https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToLine-1024x777.png" alt="" class="wp-image-11321" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToLine-1024x777.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToLine-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToLine-768x582.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToLine.png 1424w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Chart instance set to Line Mode.</figcaption></figure>
</div>


<p>As you can see, when the ChartType is Line, the data sets that are set to Line start drawing at the origin of the X axis, where the labels are also drawn for each column of data. This also happens when drawing data sets whose ChartType is set to Bar; thus, the first bar on the first column has half the width.</p>



<p>Below shows the same data sets but the ChartType is Bar. Now the Bar data sets overlay the position for the labels drawn along the X axis (they are centered on each column), and also have full the width. However, because of that, the data set whose ChartType is set to Line starts drawing at half the width of the column.</p>


<div class="wp-block-image wp-image-11324 size-large is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="777" src="https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToBar-1024x777.png" alt="" class="wp-image-11324" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToBar-1024x777.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToBar-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToBar-768x582.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartSetToBar.png 1424w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Chart instance set to Bar Mode.</figcaption></figure>
</div>


<p>You can add as many new data sets as you want, remove them, update their values, color, etc. The chart will update to reflect the changes, including the minimum and maximum values displayed in the Y axis. Keep in mind, if a chart&#8217;s Mode has been set to Line or Bar it will only display data sets created as ChartLinearDataset (by default they are set to the Line ChartType). WebChart will behave the same, starting with Xojo 2023r1.</p>



<p>One difference to note when using ChartLinearDataset is that you can set the Transparency property ranging from 0 (fully opaque) to 100 (fully transparent), as well as the CornerSize when the ChartLinearDataset ChartType is set to Bar.</p>



<h3 class="wp-block-heading">ChartDataset and Chart Modes</h3>



<p>I already showed you that a chart set to Line or Bar only displays data sets created from the ChartLinearDataset class. A similar rule applies when the chart is set to other Modes. For example, Pie, Doughnut, PolarArea or Radar charts only display data sets created from the ChartCircularDataset class.</p>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="1024" height="232" src="https://blog.xojo.com/wp-content/uploads/2023/02/CircularDataset-1024x232.png" alt="" class="wp-image-11325" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/CircularDataset-1024x232.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/CircularDataset-300x68.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/CircularDataset-768x174.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/CircularDataset-1536x349.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/02/CircularDataset-2048x465.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ul class="wp-block-list">
<li>In the same vein, Scatter and Bubble charts only display data sets created from the ChartScatteredDataset class.</li>
</ul>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="300" height="277" src="https://blog.xojo.com/wp-content/uploads/2023/02/Scatter-Bubble-300x277.png" alt="" class="wp-image-11326" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/Scatter-Bubble-300x277.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/Scatter-Bubble-1024x945.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/Scatter-Bubble-768x709.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/Scatter-Bubble.png 1330w" sizes="auto, (max-width: 300px) 100vw, 300px" /></figure>
</div>


<h3 class="wp-block-heading">DesktopChart and MobileChart, additional Properties</h3>



<p>DesktopChart and MobileChart offer additional customisation properties. For example, you can set the font, font size and font color for the title, legend, labels and values on the Y axis.</p>



<p>When setting the maximum font size used for the drawing of the Y axis values based on the chart control instance size (height), if the height of the control is not enough to display the values at the specified font size, it automatically adjusts.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="484" src="https://blog.xojo.com/wp-content/uploads/2023/02/ChartFontSize-1024x484.png" alt="" class="wp-image-11327" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/ChartFontSize-1024x484.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartFontSize-300x142.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartFontSize-768x363.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartFontSize-1536x727.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartFontSize-2048x969.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>Other properties to further customize the look of the chart include BackgroundColor and GridColor.</p>



<p><em>Tip: You may want to set the color to Color.Clear if you want your charts to be drawn or &#8220;visible&#8221;, like if you plan to layout the chart control on top of other UI controls.</em></p>



<p>In addition, you can control whether or not to display that popup that shows the underlying value as the user moves the cursor (or while dragging their finger, on iOS). This is done through the AllowPopover property (True, by default).</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="840" height="392" src="https://blog.xojo.com/wp-content/uploads/2023/02/ChartPopoverCustom.png" alt="" class="wp-image-11328" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/ChartPopoverCustom.png 840w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartPopoverCustom-300x140.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartPopoverCustom-768x358.png 768w" sizes="auto, (max-width: 840px) 100vw, 840px" /></figure>
</div>


<p>Set the background and text color in the Popover using the PopoverBackgroundColor and PopoverTextColor properties. These expect a ColorGroup instance, so they can adjust when the control is in Light or Dark Mode.</p>



<h3 class="wp-block-heading">Getting informed</h3>



<p>As you may expect from their WebChart counterpart, DesktopChart and MobileChart offer a Pressed event handler to receive the index and dataset instance over which the user clicked/tapped.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="206" src="https://blog.xojo.com/wp-content/uploads/2023/02/ChartPressed-1024x206.png" alt="" class="wp-image-11329" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/ChartPressed-1024x206.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartPressed-300x60.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartPressed-768x154.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartPressed.png 1194w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>Because the chart control can handle different ChartDatasets you&#8217;ll probably want to cast the received ChartDataset instance received in the Pressed handler to the right one before proceeding with any actions that are not common to all kind of ChartDatasets.</p>



<h3 class="wp-block-heading">Draw it!</h3>



<p>You can call the DrawInto method on a chart, provide the expected graphic context and also the left and top values to proceed with the drawing. For example, this is what a DesktopChart looks like when drawn on a Picture of the same size:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="560" height="322" src="https://blog.xojo.com/wp-content/uploads/2023/02/ToPicture.png" alt="" class="wp-image-11330" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/ToPicture.png 560w, https://blog.xojo.com/wp-content/uploads/2023/02/ToPicture-300x173.png 300w" sizes="auto, (max-width: 560px) 100vw, 560px" /></figure>
</div>


<p>It is also possible to render the chart to PDF in a vectorial way using the AddChart method on a PDFDocument instance. The parameters this method expects are the chart instance itself, the X and Y values (where it will be placed in the current PDF page), and the width and height values for the rendering.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="573" src="https://blog.xojo.com/wp-content/uploads/2023/02/ChartToPDF-1024x573.png" alt="" class="wp-image-11331" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/ChartToPDF-1024x573.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartToPDF-300x168.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartToPDF-768x429.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/ChartToPDF.png 1452w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>For example, this code will create a PDF file in the Desktop with the same height value of the chart instance, with the width set to the width of the page, minus the margins:</p>



<pre class="wp-block-code xojo"><code><code>Var d As New PDFDocument</code>
<code><span style="font-family: inherit; font-size: inherit;">Var g As Graphics = d.Graphics</span>
d.AddChart(chart1, 20, 20, g.Width-40, chart1.Height )
d.Save(SpecialFolder.Desktop.Child("ChartPDF.PDF"))</code></code></pre>



<h3 class="wp-block-heading">In summary</h3>



<p>As you can see, now it is possible to add Graphical Charts to your Desktop and iOS projects with the same ease and in the same way it is already possible on web projects, plus some more customization options. Watch a <a href="https://youtu.be/zO_UNDlERwE">quick video</a> on this topic. No license is required to learn, develop and test your projects in the latest Xojo release! <a href="https://xojo.com/download/">Download Xojo</a> 2023r1 today!</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>Algorithm: Equally Spaced Ranges</title>
		<link>https://blog.xojo.com/2023/02/13/algorithm-equally-spaced-ranges/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 13 Feb 2023 20:52:06 +0000</pubDate>
				<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[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11217</guid>

					<description><![CDATA[There are some situations where you may need a range of numbers that is equally spaced. For example, when given a minimum and a maximum&#8230;]]></description>
										<content:encoded><![CDATA[
<p>There are some situations where you may need a range of numbers that is equally spaced. For example, when given a minimum and a maximum value within which a set of numbers that need to be equally spaced. This is useful if you are designing an UI control displaying &#8220;ticks&#8221; or for the axis of a graphic chart displaying cartesian values. Continue reading to see a technique to do just this.</p>



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



<p>This technique is strongly based in the NiceLabels algorithm that can be found in <a href="https://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks">StackOverflow</a> ported to several programming languages, so…&nbsp;why not to Xojo too? In fact, it was a piece of cake porting it from JavaScript to Xojo due to the similarities of both languages,</p>



<p>Of course, if you just want to jump into the class itself, you can <a href="https://drive.google.com/file/d/1RVyXLoe_R0IA01HKAla9Vc-dknYn2Oql/view?usp=share_link">download the project from this link</a>.</p>



<p>Let&#8217;s start creating the class itself. I&#8217;ve named it NiceScale with all the required properties. To begin, add a new Class to a Xojo project. Then, with the class selected in the Navigator, add the following properties:</p>



<ul class="wp-block-list">
<li>MaxPoint As Double, setting the Scope to Protected</li>



<li>MinPoint As Double, setting the Scope to Protected</li>



<li>Spacing As Double, setting the Scope to Public</li>



<li>NiceMaximum As Double, setting the Scope to Public</li>



<li>NiceMinimum As Double</li>
</ul>



<p>Next, add the methods starting with the Constructor.</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> Constructor</li>



<li><strong>Parameters:</strong> min As Double, max As Double</li>



<li><strong>Scope:</strong> Public</li>
</ul>



<p>And type the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code><code>If Min = Max Then Max = Min + 1

Self.MinPoint = Min(Min, Max)
Self.MaxPoint = Max(Max, Min)
Self.Calculate</code></code></pre>



<p>As you can see here, the Constructor calls the Calculate method; so let&#8217;s add that one:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> Calculate</li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>And type this code in the associated Code Editor:</p>



<pre class="wp-block-code xojo"><code><code>Var range As Double

range = niceNum(MaxPoint - MinPoint, False)

Spacing = niceNum(range / 9, True)

NiceMinimum = Floor(MinPoint / Spacing) * Spacing
NiceMaximum = Ceiling(MaxPoint / Spacing) * Spacing</code></code></pre>



<p>Once again, this method is calling the NiceNum method,&nbsp;so let&#8217;s add that one to the<br>NiceScale class:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> NiceNum</li>



<li><strong>Parameters:</strong> range As Double, round As Boolean</li>



<li><strong>Return Type:</strong> Double</li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>And type the following snippet in the associated Code Editor:</p>



<pre class="wp-block-code"><code><code>Var exponent As Double
Var fraction As Double
Var niceFraction As Double

exponent = Floor(Log(range) / Log(10))
fraction = range / Pow(10, exponent)

If (round) Then
  If (fraction &lt; 1.5) Then
    niceFraction = 1
  ElseIf (fraction &lt; 3) Then
    niceFraction = 2
  ElseIf (fraction &lt; 7) Then
    niceFraction = 5
  Else
    niceFraction = 10
  End If
Else
  If (fraction &lt;= 1) Then
    niceFraction = 1
  ElseIf (fraction &lt;= 2) Then
    niceFraction = 2
  ElseIf (fraction &lt;= 5) Then
    niceFraction = 5
  Else
    niceFraction = 10
  End If
End If

Return niceFraction * Pow(10, exponent)</code></code></pre>



<p>Lastly, let&#8217;s add a couple of useful methods for the class: GetValues and SetMinMaxPoints. The first one will let us get the Array of the already equally spaced Double values, while the second one will let us set a new pair of minimum and maximum values without needing to create a new instance of the class:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> GetValues</li>



<li><strong>Return Type:</strong> Double()</li>



<li><strong>Scope:</strong> Public</li>
</ul>



<p>Typing the following snippet in the associated Code Editor:</p>



<pre class="wp-block-code"><code><code>Var values() As Double

For n As Double = Self._NiceMinimum To Self._NiceMaximum Step Self._mSpacing
  values.add n
Next

If values(0) &gt; 0 Then
  While values(0) &lt;&gt; 0
    values.AddAt(0, values(0) - Self._mSpacing)
  Wend
End If

Return values</code></code></pre>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> SetMinMaxPoints</li>



<li><strong>Parameters:</strong> min As Double, max As Double</li>



<li><strong>Scope:</strong> Public</li>
</ul>



<p>And type these lines of code in the associated Code Editor:</p>



<pre class="wp-block-code xojo"><code><code>If Min = Max Then Max = Min + 1

MinPoint = Min(Min, Max)
MaxPoint = Max(Max, Min)
Calculate</code></code></pre>



<h3 class="wp-block-heading">&nbsp;</h3>



<h3 class="wp-block-heading">NiceScale in Practice</h3>



<p>Let&#8217;s create the UI for a Desktop project so we can put our NiceScale class in practice; and because we are going to need some custom drawing, drag a Canvas from the Library to the project Navigator. That will create a canvas subclass. With the just added Canvas subclass selected in the Navigator use the associated Inspector Panel to set the following values:</p>



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



<p>Then, add the following property to it:</p>



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



<li><strong>Type:</strong> NiceScale</li>



<li><strong>Scope:</strong> Private</li>
</ul>



<p>Add a new Method to our ScaleDrawing subclass using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> Constructor</li>
</ul>



<p>And typing these lines of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code><code>Super.Constructor
Self.range = New NiceScale(0, 1)</code></code></pre>



<p>Then, add a second method using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> Redraw</li>



<li><strong>Parameters:</strong> minValue As Double, maxValue As Double</li>
</ul>



<p>And typing these two lines of code in the associated Code Editor:</p>



<pre class="wp-block-code xojo"><code><code>range.SetMinMaxPoints(minValue, maxValue)

Self.Refresh</code></code></pre>



<p>After that, let&#8217;s do the drawing itself! So we need to add the Paint event to our ScaleDrawing class. When done, add the following lines of code to the associated Code Editor:</p>



<pre class="wp-block-code"><code><code>g.DrawRectangle(0, 0, g.Width, g.Height)

Var values() As Double = range.GetValues
Var offset As Double = (( g.Width ) / values.LastIndex) - 10
Var x As Double = 20
Var y As Double = g.Height / 2 - 5
Var tx As Double
Var Val As Double

For n As Integer = 0 To values.LastIndex
  Val = values(n)

  g.DrawLine( x, y, x, y + 10 )

  tx = x - g.TextWidth(values(n).ToString) / 2

  g.DrawText(values(n).ToString, tx, y + 10 + g.FontAscent)

  x = x + offset
Next

g.DrawLine(20, y, x - offset, y)</code></code></pre>



<h3 class="wp-block-heading">&nbsp;</h3>



<h3 class="wp-block-heading">Creating the NiceScale Example UI</h3>



<p>Select the Window1 window in the Navigator so it is displayed in the Layout Editor. Next drag the ScaleDrawing class from the Navigator and drop it into the Layout Editor so it looks like like this (locking the four locks for ScaleDrawing1 in the Inspector Panel):</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="743" src="https://blog.xojo.com/wp-content/uploads/2023/02/CanvasSubclassUI-1024x743.png" alt="" class="wp-image-11222" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/CanvasSubclassUI-1024x743.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/CanvasSubclassUI-300x218.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/CanvasSubclassUI-768x557.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/CanvasSubclassUI.png 1364w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>Next, add a couple of Labels, two TextFields and a Button below ScaleDrawing1 in the Layout Editor so our final UI looks like this:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="736" src="https://blog.xojo.com/wp-content/uploads/2023/02/CompletedUI-1024x736.png" alt="" class="wp-image-11223" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/CompletedUI-1024x736.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/CompletedUI-300x215.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/CompletedUI-768x552.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/CompletedUI.png 1356w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>Rename Label1 as MinimumLabel, Label2 as MaximumLabel, TextField1 as MinimumTF, TextField2 as MaximumTF, and Button1 as DrawBT. Then, add the Pressed event to DrawBT and type the following code in the associated Code Editor:</p>



<pre class="wp-block-code xojo"><code><code>ScaleDrawing1.Redraw(MinimumTF.Text.ToDouble, maximumtf.Text.ToDouble)</code></code></pre>



<p>That&#8217;s all!</p>



<h3 class="wp-block-heading">Running the app!</h3>



<p>Everything is in place, so run the app and put some values in the Minimum and Maximum textfields, clicking the button to refresh the drawing. These are some examples you will get for the following range values:</p>



<ul class="wp-block-list">
<li>By Default:</li>
</ul>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="974" height="142" src="https://blog.xojo.com/wp-content/uploads/2023/02/DefaultRange.png" alt="" class="wp-image-11218" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/DefaultRange.png 974w, https://blog.xojo.com/wp-content/uploads/2023/02/DefaultRange-300x44.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/DefaultRange-768x112.png 768w" sizes="auto, (max-width: 974px) 100vw, 974px" /></figure>



<ul class="wp-block-list">
<li>Minimum: 12, Maximum: 112</li>
</ul>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="950" height="116" src="https://blog.xojo.com/wp-content/uploads/2023/02/12-112Range.png" alt="" class="wp-image-11221" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/12-112Range.png 950w, https://blog.xojo.com/wp-content/uploads/2023/02/12-112Range-300x37.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/12-112Range-768x94.png 768w" sizes="auto, (max-width: 950px) 100vw, 950px" /></figure>



<ul class="wp-block-list">
<li>Minimum: -345, Maximum: 835</li>
</ul>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="1024" height="129" src="https://blog.xojo.com/wp-content/uploads/2023/02/345-835Range-1024x129.png" alt="" class="wp-image-11219" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/345-835Range-1024x129.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/02/345-835Range-300x38.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/345-835Range-768x97.png 768w, https://blog.xojo.com/wp-content/uploads/2023/02/345-835Range.png 1050w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ul class="wp-block-list">
<li>Minimum: -816, Maximum: 25</li>
</ul>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="1000" height="154" src="https://blog.xojo.com/wp-content/uploads/2023/02/816-25Range.png" alt="" class="wp-image-11220" srcset="https://blog.xojo.com/wp-content/uploads/2023/02/816-25Range.png 1000w, https://blog.xojo.com/wp-content/uploads/2023/02/816-25Range-300x46.png 300w, https://blog.xojo.com/wp-content/uploads/2023/02/816-25Range-768x118.png 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<p>As you can see, having these classes in your developer bag is a good thing if you need to draw this kind of scale! Use the ScaleDrawing class as a start point for your own needs.</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>Quick Tip: Opening, Shown, Closing and Closed</title>
		<link>https://blog.xojo.com/2023/02/09/quick-tip-opening-shown-closing-and-closed/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 09 Feb 2023 17:38:29 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></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[Beginner Tips]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11215</guid>

					<description><![CDATA[Knowing the firing order of the Opening event in Xojo apps, and the Shown event for Xojo Web apps, is important to using these correctly for the control's initialization. The same can be said for Closing and Closed events. Read to for a breakdown of this order for Desktop, Web and Mobile apps developed in Xojo. ]]></description>
										<content:encoded><![CDATA[
<p>Knowing the firing order of the Opening event in Xojo Desktop and Mobile apps, and the Shown event for Xojo Web apps, is important to using these correctly for a control&#8217;s initialization. The same can be said for Closing and Closed events. Read on for a breakdown of this order for Desktop, Web and Mobile apps developed in Xojo. </p>



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



<h3 class="wp-block-heading">Opening in Desktop and Mobile Apps</h3>



<ul class="wp-block-list">
<li>First, the App Opening event will be fired first. </li>



<li>Next, the Opening event on every control of the default Window assigned to the App project. In this case, it will follow the same order in which the controls were added to the Window in the Layout Editor. It is possible to change that order using the Order buttons in the <a href="https://documentation.xojo.com/getting_started/using_the_ide/layout_editor.html#command-bar">Command Bar</a> in the Layout Editor. </li>



<li>Last, the Opening event will be fired on the default Window containing the controls.</li>
</ul>



<h3 class="wp-block-heading">Closing in Desktop Apps</h3>



<p>When a Window is closed in a Desktop app, the Closing event will be fired following this order:</p>



<ul class="wp-block-list">
<li>First, the Closing event will be raised on every control added to the Window, following the same order used when adding the controls to the Window in the Layout Editor. It is possible to change that order using the Order buttons in the Layout Editor toolbar.</li>



<li>Next, the Closing event will be raised in the Window itself.</li>



<li>Last, the Closing event will be raised in the App object of the Desktop app when the user quits the application.</li>
</ul>



<h3 class="wp-block-heading">Opening in Web Apps</h3>



<p>This is the event firing order for Xojo Web apps:</p>



<ul class="wp-block-list">
<li>First, the Opening event will be raised in the WebApp object.</li>



<li>Next, the Opening event in the WebSession object.</li>



<li>Next, the Opening event on every control added to the by default WebPage set in the WebApp object. In this case, it will follow the same order used when adding the controls to the web page in the Layout Editor. (It is possible to change that order using the Order buttons in the Layout Editor toolbar.)</li>



<li>Next, the Opening event will be raised on the default web page itself.</li>



<li>Next, the app will start to raise the Shown event on every one of the webpage controls following the same order used when they have been added to the page. (It is possible to change that order using the Order buttons in the Layout Editor toolbar.)</li>



<li>Last, the Shown event will be raised in the default webpage.</li>
</ul>



<h3 class="wp-block-heading">Closing in Web Apps</h3>



<p>Regarding the Closing and Closed events, the Web App will follow this order:</p>



<ul class="wp-block-list">
<li>First, the Closing event will be raised in the WebSession object.</li>



<li>Next, the Closed event will be raised on every one of the default webpages (or the pages shown), following the same order used when adding the controls to the page in the Layout Editor. (It is possible to change that order using the Order buttons in the Layout Editor toolbar.)</li>



<li>Last, the Closed event will be fired in the webpage itself.</li>
</ul>



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



<p>As you can see, Xojo follows the firing same regardless of the target you choose for your project &#8211; Desktop, Web or Mobile apps. Obviously, Web apps do change a bit, because they deal with the WebSession object and also with the Shown event in addition to the Opening event. In Web projects, the Opening event happens on the server side, while the Shown event happens in the client (browser) side.</p>



<p>See related <a href="https://youtu.be/E3iFTJt2V1Y">video</a> at the Xojo Programming Language YouTube Channel.</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>Running Xojo Web projects on Raspberry Pi 64-bit ARM boards</title>
		<link>https://blog.xojo.com/2022/12/13/running-xojo-web-projects-on-raspberry-pi-64-bit-arm-boards/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 13 Dec 2022 15:22:45 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[64-bit]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Raspbian]]></category>
		<category><![CDATA[Remote Debugging]]></category>
		<category><![CDATA[Single Board Computer]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Forum]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11065</guid>

					<description><![CDATA[Xojo 2022r4 opens the door for running projects on 64-bit Raspberry Pi ARM boards. Console, Desktop and Web are supported.]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2022r4 opens the door for running projects on 64-bit Raspberry Pi ARM boards. Console, Desktop and Web are supported.</p>



<p>Xojo Web is an excellent way to expose the features of your electronics projects without having to attach any screen to them. It&#8217;s never been easier to build a Web GUI for your smart clocks, drones, POS, domotics, robots or just some automation services. Thinking about building a solar powered server to automate your tweets? Why not!</p>



<p>If you prefer, you can just expose a Web API instead that can be remotely consumed from another device.</p>



<h2 class="wp-block-heading">What Raspberry Pi boards support ARM 64-bit Linux OS?</h2>



<ul class="wp-block-list">
<li>Raspberry Pi Zero 2</li>



<li>Raspberry Pi 3</li>



<li>Raspberry Pi 4</li>



<li>Raspberry Pi 400</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="763" src="https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-zero-2-1024x763.png" alt="" class="wp-image-11066" srcset="https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-zero-2-1024x763.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-zero-2-300x224.png 300w, https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-zero-2-768x573.png 768w, https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-zero-2.png 1336w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">One of my Raspberry Pi Zero 2, running a 64-bit Xojo Web application.</figcaption></figure>



<h2 class="wp-block-heading">Preparing your Raspberry Pi</h2>



<p>The easiest way to get your operating system ready is by using the <a href="https://www.raspberrypi.com/software/" data-type="URL" data-id="https://www.raspberrypi.com/software/" target="_blank" rel="noreferrer noopener">Raspberry Pi Imager</a>.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="690" src="https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-imager-1024x690.png" alt="" class="wp-image-11067" srcset="https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-imager-1024x690.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-imager-300x202.png 300w, https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-imager-768x518.png 768w, https://blog.xojo.com/wp-content/uploads/2022/12/raspberry-pi-imager.png 1510w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Raspberry Pi Imager v1.7.3.</figcaption></figure>



<p>At the moment of writing this article, it selects the 32-bit flavor by default. If you have one of the supported boards, go ahead and try Raspberry Pi OS (64-bit) or Raspberry Pi OS Lite (64-bit). The later won&#8217;t include any desktop environment, you&#8217;ll have to access by SSH.</p>



<p>Select your SD Card storage and press on Write. Optionally, if you want to set a hostname for your board, enable SSH, or even configure your Wifi, press on the gears icon.</p>



<p>In just a few minutes you will have a ready to boot SD card for your Raspberry Pi.</p>



<h2 class="wp-block-heading">Remotely debugging your projects</h2>



<p>This is one of my favorite features of Xojo.</p>



<p>In your Xojo installation Extras folder, you will find a &#8220;Remote Debugger Console&#8221; and &#8220;Remote Debugger Desktop&#8221;, that also works for your Linux 64-bit OS.</p>



<p>Depending on which flavor of Linux you&#8217;ve selected in the previous step, send the Console or Desktop ZIP to your board, run it and configure the settings.</p>



<p>Inside Xojo, go to Preferences and press on the Debugging tab.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="599" src="https://blog.xojo.com/wp-content/uploads/2022/12/xojo-preferences-debugging-1024x599.png" alt="" class="wp-image-11068" srcset="https://blog.xojo.com/wp-content/uploads/2022/12/xojo-preferences-debugging-1024x599.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/12/xojo-preferences-debugging-300x176.png 300w, https://blog.xojo.com/wp-content/uploads/2022/12/xojo-preferences-debugging-768x449.png 768w, https://blog.xojo.com/wp-content/uploads/2022/12/xojo-preferences-debugging.png 1480w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Xojo Debugging Preferences panel.</figcaption></figure>



<p>That&#8217;s it. Now you will be able to remotely run and debug your applications. Add a few breakpoints and the execution will stop as soon as it reaches it, allowing you to explore the current state.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="667" src="https://blog.xojo.com/wp-content/uploads/2022/12/xojo-remote-debug-1024x667.png" alt="" class="wp-image-11070" srcset="https://blog.xojo.com/wp-content/uploads/2022/12/xojo-remote-debug-1024x667.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/12/xojo-remote-debug-300x195.png 300w, https://blog.xojo.com/wp-content/uploads/2022/12/xojo-remote-debug-768x500.png 768w, https://blog.xojo.com/wp-content/uploads/2022/12/xojo-remote-debug-1536x1000.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/12/xojo-remote-debug.png 1910w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Running your project remotely, to debug.</figcaption></figure>



<h2 class="wp-block-heading">Deploying the final version</h2>



<p>Once you&#8217;re ready to build the final version of your application, all the wires attached and components soldered, the last step is to &#8220;Deploy&#8221; your application.</p>



<p>There is a tutorial covering this step in detail: <a href="https://blog.xojo.com/2021/05/28/tutorial-deploying-web-apps-on-linux/" data-type="post" data-id="8552">Deploying Web Apps on Linux</a>.</p>



<p>If you create a Raspberry Pi project, please make sure you open a <a href="https://forum.xojo.com" data-type="URL" data-id="https://forum.xojo.com" target="_blank" rel="noreferrer noopener">Forum thread</a>. The Xojo community loves seeing this kind of projects!</p>



<p>What will you build?</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>Adding Tables to PDFDocument</title>
		<link>https://blog.xojo.com/2022/10/12/adding-tables-to-pdfdocument/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 12 Oct 2022 13:45:45 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10756</guid>

					<description><![CDATA[Starting with Xojo 2022r3 it is possible to create and add tables to PDF documents using Xojo&#8217;s PDFTable class and the PDFTableDataSource class interface. Among&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2022r3 it is possible to create and add tables to PDF documents using Xojo&#8217;s PDFTable class and the PDFTableDataSource class interface. Among other things, your code will not need to be in charge of calculating rows sizes in order to decide if it needed to add a new page or not, or even complex calculations in order to draw the content on every cell of every row/column pair in the table.</p>



<p>You can download the example project <a href="https://www.dropbox.com/s/bkdpoem0vn3vqcx/PDFTable-Example.zip?dl=1">from this link</a>.</p>



<h3 class="wp-block-heading">Features of Tables in PDFDocument</h3>



<p>The main features available with tables in PDFDocument are:</p>



<ul class="wp-block-list"><li>PDFTable / PDFTableDataSource is compatible with Desktop, Web, Console and RaspberryPi projects</li><li>Variable height rows</li><li>Automatically add new pages to the PDF</li><li>The ability to repeat (or not) the table header at the start of every new page added</li></ul>



<p>In order to achieve this, the PDFTable class works side by side with the PDFTableDataSource class interface. This class interface declares the methods that will be called by a given PDFTable instance in order to generate the table on the fly.</p>



<ul class="wp-block-list"><li>PDFTableDataSource</li></ul>



<p>Because it is a class interface, you will be able to add it to any window/web page or any class/subclass you  create, so it can work as the provider of the data in the drawing of a given PDF table.</p>



<p>The PDFTableDataSource has these five methods:</p>



<ul class="wp-block-list"><li><strong>AddNewRow(rowCount As Integer) As Boolean</strong>&#8211; The rowCount parameter contains the value of the rows already added to the table. Returning True from this method will add a new row to the table; otherwise it will end the creation of the associated table.</li><li><strong>HeaderHeight As Double</strong>&#8211; In the implementation of this method you will set the height value used in order to draw the table header.</li><li><strong>PaintCell(g As Graphics, row As Integer, column As Integer)</strong>&#8211; This is the method called by the PDFTable instance in order to draw the cell for the row/column pair stored in the associated parameters. The method receives its own graphic context in the &#8216;g&#8217; variable, so you can use any of the supported methods and properties of the Graphic class to draw the contents in the table cell.</li><li><strong>PaintHeaderContent(g As Graphics, column As Integer)</strong>&#8211; This is the method called by the PDFTable instance every time it needs to draw the header of the table. As you can see, it receives as parameters the column number and its own graphic context.</li><li><strong>RowHeight As Double</strong>&#8211; This is the method called by the PDFTable instance so your code can set the height for the current row.</li></ul>



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



<p>This is a really simple class exposing a total of four properties:</p>



<ul class="wp-block-list"><li><strong>ColumnCount As Integer</strong>&#8211; This is the property that sets the number of columns for the table to be drawn.</li><li><strong>ColumnWidths As String</strong>&#8211; This is the property that sets as a string the width of every column in the table, separated by the comma character.</li><li><strong>DataSource As PDFTableDataSource</strong>&#8211; This is the property that sets the object acting as the data source object for the table. Remember that such an object needs to implement the methods declared in the PDFTableDataSource class interface.</li><li><strong>HasRepeatingHeader As Boolean</strong>&#8211; Use this property to instruct the PDFTable instance if it needs to repeat the header on every new page that is added to the document as the table is generated.</li></ul>



<p>For example, the following fragment of code will create a table with a total of three columns that have the same size. The table will be drawn horizontally centered in the page. The object acting as the data source for the table will be the same where this snippet of code has been added, that is: &#8216;Self&#8217;:</p>



<pre class="wp-block-preformatted"><code>Var d As New PDFDocument

Var tTable As New PDFTable
tTable.ColumnCount = 3
tTable.ColumnWidths = "150,150,150"
tTable.DataSource = Self
tTable.HasRepeatingHeader = True</code></pre>



<p>The way to add a PDFTable instance to the current page of the PDF document is through the AddTable(table As PDFTable, x As Double, y As Double) method; for example:</p>



<pre class="wp-block-preformatted"><code>Var x As Double = d.PageWidth/2 - 450/2

d.addTable(tTable,x,20)</code></pre>



<h3 class="wp-block-heading">&nbsp;</h3>



<h3 class="wp-block-heading">PDFTable in Practice</h3>



<p>In this example, you can see how to create a PDF document with a table added to it (horizontally centered on the pages). This table will have three columns equally sized and a total of 100 rows with a variable —random— height—, and giving the option to the user so they can choose to repeat the table header on every new page added to the document or not.</p>



<p>The cell contents of the table will be chosen randomly, varying between filling the cell with a random color, drawing text with the row and column numbers for the cell, rendering an image that has been added to the project, or keeping the cell empty.</p>



<p>Create a new Desktop project. With the Window1 selected in the Navigator, click on the &#8220;Choose…&#8221; button found in the associated Inspector Panel under the Interface section. This action will open a new window displaying all the available Class Interfaces. Select the PDFTableDataSource entry and confirm the selection click the Ok button.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="927" height="1024" src="https://blog.xojo.com/wp-content/uploads/2022/10/Selector-PDFDataTableSource-927x1024.png" alt="" class="wp-image-10757" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/Selector-PDFDataTableSource-927x1024.png 927w, https://blog.xojo.com/wp-content/uploads/2022/10/Selector-PDFDataTableSource-272x300.png 272w, https://blog.xojo.com/wp-content/uploads/2022/10/Selector-PDFDataTableSource-768x848.png 768w, https://blog.xojo.com/wp-content/uploads/2022/10/Selector-PDFDataTableSource.png 1012w" sizes="auto, (max-width: 927px) 100vw, 927px" /></figure>
</div>


<p>As result, the methods declared by the PDFTableDataSource are now added to the Window1 item.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="505" height="270" src="https://blog.xojo.com/wp-content/uploads/2022/10/PDFTableDataSource-Methods.png" alt="" class="wp-image-10758" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/PDFTableDataSource-Methods.png 505w, https://blog.xojo.com/wp-content/uploads/2022/10/PDFTableDataSource-Methods-300x160.png 300w" sizes="auto, (max-width: 505px) 100vw, 505px" /></figure>
</div>


<p>Grab a CheckBox control from the Library and drop it in the upper-left corner of the window in the Layout Editor. Use the associated Inspector Panel to change the following values:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> RepeatHeaderCB</li><li><strong>Visual State:</strong> Checked</li></ul>



<p>In order to complete this basic user interface, drag a Button control from the Library and drop it in the upper-right corner of the window in the Layout Editor. With Button1 selected in the Navigator, choose the Add to &#8220;Button1&#8221; &gt; Event Handler…&nbsp;option from the contextual menu. Next, select the Pressed event from the resulting window and confirm the selection so it is added to the Window1 object.</p>



<p>With the Pressed event selected in the Navigator, add the following fragment of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted"><code>Var d As New PDFDocument

Var tTable As New PDFTable
tTable.ColumnCount = 3
tTable.ColumnWidths = "150,150,150"
tTable.DataSource = Self
tTable.HasRepeatingHeader = RepeatHeaderCB.Value

Var x As Double = d.PageWidth/2 - 450/2

d.addTable(tTable,x,20)

d.Save(SpecialFolder.Desktop.Child("Table.pdf"))</code></pre>



<p>Drop any image you want to use from your computer drive into the Xojo&#8217;s IDE Navigator. Our example uses an image named &#8220;XojoLogo100&#8221;. When adding your own image, you can opt to rename it to the name name used in the code of this example, or changing all the references where &#8220;XojoLogo100&#8221; is referenced to the name of your image.</p>



<p>Now it is time to implement the code in every one of the five methods required by the PDFTableDataSource class interface.</p>



<p>In the AddNewRow method:</p>



<pre class="wp-block-preformatted"><code>Return rowCount &lt; 100 // Our example table has a total of 100 rows.</code></pre>



<p>In the HeaderHeight method:</p>



<pre class="wp-block-preformatted"><code>Return 30 // This is the height for the cells of the header in the table.</code></pre>



<p>In the PaintCell method:</p>



<pre class="wp-block-preformatted"><code>Var rd As New Random

Var option As Integer = rd.InRange(1,4)

Select Case option

Case 1

  Var s As String = "row: " + row.ToString + " column: " + Column.ToString
  Var h As Double = g.Height/2 + g.TextHeight/2
  g.DrawText s,5,h

Case 2

  g.DrawPicture(XojoLogo100,0,0)

Case 3

  g.DrawingColor = Color.RGB(rd.InRange(0,255), rd.InRange(0,255), rd.InRange(0,55))
  g.FillRectangle(2,2,g.Width-4,g.Height-4)

Case 4

 // Empty cell
End Select

g.DrawingColor = Color.Black
g.DrawRectangle 0,0, g.Width,g.Height</code></pre>



<p>And this is the code we will use in order to draw the content of the table Header cells in the PaintHeaderContent:</p>



<pre class="wp-block-preformatted"><code>Var tRandom As New Random

Var c As Color

Select Case Column
Case 0
  c = color.Red
Case 1
  c = Color.Green
Case 2
  c = Color.Blue
End Select

g.DrawingColor = c
g.FillRectangle 0,0,g.Width,g.Height

Var s As String = "Column: " + Column.ToString

Var x, y As Double
x = (g.Width/2) - (g.TextWidth(s)/2)
y = (g.Height/2) + (g.TextHeight/2)

g.DrawingColor = color.Black
g.DrawText s,x, y</code></pre>



<p>Now add the code responsible for setting the height of every new row added to the table in the RowHeight method. As you can see, this value is a random value between 25 and 100 points:</p>



<pre class="wp-block-preformatted"><code>Var rd As New Random

return rd.InRange(25,100)</code></pre>



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



<p>Run the app, click on the button and you will see how a new PDF document named &#8220;Table.pdf&#8221; is created in your computer desktop. The number of pages of the PDF document may vary because the height of the table rows vary on every iteration.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1018" height="1024" src="https://blog.xojo.com/wp-content/uploads/2022/10/Table-PDF-1018x1024.png" alt="" class="wp-image-10759" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/Table-PDF-1018x1024.png 1018w, https://blog.xojo.com/wp-content/uploads/2022/10/Table-PDF-298x300.png 298w, https://blog.xojo.com/wp-content/uploads/2022/10/Table-PDF-150x150.png 150w, https://blog.xojo.com/wp-content/uploads/2022/10/Table-PDF-768x772.png 768w, https://blog.xojo.com/wp-content/uploads/2022/10/Table-PDF-1527x1536.png 1527w, https://blog.xojo.com/wp-content/uploads/2022/10/Table-PDF-2036x2048.png 2036w" sizes="auto, (max-width: 1018px) 100vw, 1018px" /></figure>
</div>


<p>This time, unselect the checkbox and click the button to create the PDF document again. Now, the table header is only rendered in the first page of the document.</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>PDFDocument Improvements</title>
		<link>https://blog.xojo.com/2022/10/12/pdfdocument-improvements/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 12 Oct 2022 13:45:29 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10810</guid>

					<description><![CDATA[While PDFTable and PDFDataTableSource ease the way to render tables in your PDF documents on Desktop, Web, Raspberry Pi and Console projects (iOS to come!) are the big new features for PDFDocument in Xojo 2022r3, that's not all that improved. There are additional features added to PDFDocument you might find helpful such as more control while using PDFForm and improvements to dealing with TOC indexes. Learn more about how to get advantage of these additions!]]></description>
										<content:encoded><![CDATA[
<p>While <a href="https://blog.xojo.com/2022/10/12/adding-tables-to-pdfdocument/">PDFTable</a> and PDFDataTableSource ease the way to render tables in your PDF documents on Desktop, Web, Raspberry Pi and Console projects (iOS to come!) and are the big new features for PDFDocument in Xojo 2022r3, that&#8217;s not all that improved. There are additional features added to PDFDocument you might find helpful such as more control while using PDFForm and improvements to dealing with TOC indexes. Learn more about how to get advantage of these additions!</p>



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



<h3 class="wp-block-heading">More Control with PDFForm Controls</h3>



<p>It is possible to add forms to your PDF documents using controls as text fields, text areas, list boxes, radio buttons, check boxes, popup menus, combo boxes, etc. Starting with Xojo 2022r3 you&#8217;ll be able to set if the items of PDFComboBox, PDFListBox and PDFPopupMenu are displayed sorted or as they were added using the Boolean IsSorted property.</p>



<p>As for the PDFTextArea and PDFTextField controls, there is a new property AllowSpellChecking so you can set if these will enable spell check or not. And in the case of the PDFTextField, it is also possible to set the HasPassword property so the text typed by the user is substituted in the PDF document with the usual replacement character, hiding what the user is typing from prying eyes!</p>



<h3 class="wp-block-heading">Dealing with TOC Indexes</h3>



<p>Lastly, there are also improvements to dealing with TOC creation in your PDF documents. For example, you can get now the Parent instance from a PDFToc entry through the Parent property; and there are new methods to get all the child items hanging from a PDFTOCEntry —Entries() As PDFTOCEntry()— and to remove existing entries from a PDFTOCEntry instance: PDFTOCEntry.RemoveEntry(ParamArray entries As PDFTOCEntry) and PDFTOCEntry.RemoveEntry(entries() as PDFTOCEntry).</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>Using Emojis in Xojo</title>
		<link>https://blog.xojo.com/2022/09/15/using-emojis-in-xojo/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Thu, 15 Sep 2022 19:00:18 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Emoji]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10674</guid>

					<description><![CDATA[Xojo has very good graphics support. You can drop images into your project and use them with several controls. You can use the various Paint events to draw your own graphics. And there's another source of graphics you may not have considered: emojis. Emojis can be used anywhere that text can be used because they are simply Unicode characters. That means they can be used in textfields, buttons, labels, popup menus, listboxes and more.]]></description>
										<content:encoded><![CDATA[
<p>Xojo has very good graphics support. You can drop images into a Xojo project and use them with several controls. You can use the various Paint events to draw your own graphics. And there&#8217;s another source of graphics you may not have considered: emojis. Emojis can be used anywhere that text can be used because they are Unicode characters. That means they can be used in textfields, buttons, labels, popup menus, listboxes and more.</p>



<p>Emojis are available on every operating system and platform that Xojo supports from desktop to mobile to web. Because they are built-in to the OS as characters, they are client-side which means that web applications don&#8217;t have to load them from the server as they are already available to the browser from the user&#8217;s OS. As characters, they are scalable to any font size. There are also a lot of them. According to <a href="https://emojipedia.org/stats/">Emojipedia</a> (yes, that&#8217;s a thing), there are over 3,600 emojis as of September 2021. </p>



<p>Emojis can be especially useful for listboxes in web applications because unlike the <a href="https://documentation.xojo.com/api/user_interface/desktop/desktoplistbox.html#desktoplistbox">DesktopListBox</a>, the <a href="https://documentation.xojo.com/api/user_interface/web/weblistbox.html#weblistbox">WebListBox</a> does not have a PaintCellBackground event that can be used to draw graphics into a cell. Instead, if you can find an emoji that represents what you&#8217;d otherwise draw into a cell, you can simply assign it without having to deal with graphics at all. For example, there are a series of emojis that are just boxes in different colors that could be used to indicate the state of something: <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e9.png" alt="🟩" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e5.png" alt="🟥" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e6.png" alt="🟦" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e7.png" alt="🟧" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e8.png" alt="🟨" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7eb.png" alt="🟫" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b1b.png" alt="⬛" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b1c.png" alt="⬜" class="wp-smiley" style="height: 1em; max-height: 1em;" />. The famous web game <a href="https://www.nytimes.com/games/wordle/index.html">Wordle</a> uses these when you share your results. With over 3600 available, you can likely find an emoji to represent nearly anything you might need from the common smiling face <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f600.png" alt="😀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> to the less common umbrella on the ground<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26f1.png" alt="⛱" class="wp-smiley" style="height: 1em; max-height: 1em;" /> , banjo <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1fa95.png" alt="🪕" class="wp-smiley" style="height: 1em; max-height: 1em;" /> or moai <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f5ff.png" alt="🗿" class="wp-smiley" style="height: 1em; max-height: 1em;" />from Easter Island.</p>



<p>Again, emojis can be used in any type of application, desktop, mobile or web. Here&#8217;s an example of them in a web popup menu:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="366" height="368" src="https://blog.xojo.com/wp-content/uploads/2022/09/drop.png" alt="" class="wp-image-10748" srcset="https://blog.xojo.com/wp-content/uploads/2022/09/drop.png 366w, https://blog.xojo.com/wp-content/uploads/2022/09/drop-298x300.png 298w, https://blog.xojo.com/wp-content/uploads/2022/09/drop-150x150.png 150w" sizes="auto, (max-width: 366px) 100vw, 366px" /></figure>



<p>And here they are in a web list box:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="390" height="378" src="https://blog.xojo.com/wp-content/uploads/2022/09/box.png" alt="" class="wp-image-10749" srcset="https://blog.xojo.com/wp-content/uploads/2022/09/box.png 390w, https://blog.xojo.com/wp-content/uploads/2022/09/box-300x291.png 300w" sizes="auto, (max-width: 390px) 100vw, 390px" /></figure>



<p>The key thing is to realize that they are individual characters which means they can appear alone or mixed in with other characters. If you need them to be larger, increase the font size. Here&#8217;s the lion for example at 60 point size:</p>



<p style="font-size:60px"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f981.png" alt="🦁" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>Because they are characters, you can copy and paste emojis anywhere you&#8217;d use a character, including in your code:</p>



<pre class="wp-block-code"><code>ListBox1.AddRow("Fox &#x1f98a;")
ListBox1.AddRow("Lion &#x1f981;")
ListBox1.AddRow("Chipmunk &#x1f43f;")</code></pre>



<p>Just remember that emojis are characters, not graphics, so you should treat them as such. Notice in the code above, they are inside the quotes. You could even use them to name a variable:</p>



<pre class="wp-block-code"><code>Var &#x1f30b;&#x1f965;&#x1f4b0; As String = "Yes, you can do this!"</code></pre>



<p>I&#8217;m not sure that&#8217;s useful, but it clearly demonstrates how an emoji is a characters like any other.</p>



<p>On Emojipedia you can search for emojis by keyword and copy them to the clipboard. Again because they are simply characters, you can then paste them into a Xojo constant, make them the default value of a property or even paste them into the Code Editor to assign them in code.</p>



<p>Keep emojis in mind the next time you need an image in an application.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PDFDocument: How To Encrypt PDFs</title>
		<link>https://blog.xojo.com/2022/07/25/pdfdocument-how-to-encrypt-pdfs/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 25 Jul 2022 13:54:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[2022r2]]></category>
		<category><![CDATA[Encryption]]></category>
		<category><![CDATA[PDF]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10486</guid>

					<description><![CDATA[One of the PDFDocument features added in Xojo 2022r2 is the ability to encrypt PDF files created with Xojo. Continue reading and I will show&#8230;]]></description>
										<content:encoded><![CDATA[
<p>One of the PDFDocument features added in Xojo 2022r2 is the ability to encrypt PDF files created with Xojo. Continue reading and I will show you how.</p>



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



<p>Encrypting PDF files with PDFDocument is based in the use of the PDFPermissions class. You&#8217;ll need to create a new instance of the class passing along the &#8220;Owner&#8221; and &#8220;User&#8221; passwords. For example:</p>



<pre class="wp-block-code"><code>Var d As New PDFDocument
Var g As Graphics = d.Graphics

Var p As New PDFPermissions("OwnerPassword","UserPassword")</code></pre>



<p>In addition, you can set other properties for the PDFPermissions instance; all of them are read/write and will be applied by the PDF viewer app for when the document is opened using the &#8220;user&#8221; password.</p>



<ul class="wp-block-list"><li><strong>AllowCopyingContents</strong> is set to <code>False</code> by default. When set to <code>True</code> it will allow copying contents from the PDF, as for example the selected text or image.</li><li><strong>AllowModifyingContents</strong> is set to <code>False</code> by default. When set to <code>True</code> it will all to modify the contents of the protected PDF document.</li><li><strong>AllowPrinting</strong> is se to <code>False</code> by default. When it is set to <code>True</code> it will be possible to print the PDF.</li></ul>



<p>Once the PDFPermissions instance has been created and the desired properties had been set, all you need to do is to assign such instance to the Permissions property for the PDFDocument instance you want to encrypt:</p>



<pre class="wp-block-code"><code>d.Permissions = p</code></pre>



<p>Then, when it&#8217;s saving the document to a file, PDFDocument will encrypt all the streams of data containing sensitive information, as it can be the text or Images rendered on every one of the PDF pages plus the metadata information itself. The used encryption algorithm is AES 128 bits.</p>



<p>That&#8217;s all! You can distinguish an encrypted PDF file from an unencrypted one because, usually, the first one will be displayed with the image of a Lock in the icon. When you open an encrypted PDF in the viewer app you&#8217;ll be asked to type a password. If you enter the passord set to the &#8220;Owner&#8221; user, you&#8217;ll be able to do all the kind of operations allowed by the viewer app, while if you enter the &#8220;User&#8221; password, then the kind of options available will be determined by those set using the PDFPermissions properties.</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>PDFDocument: New Annotations Types</title>
		<link>https://blog.xojo.com/2022/07/25/pdfdocument-new-annotations-types/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 25 Jul 2022 13:53:00 +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[2022r2]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10488</guid>

					<description><![CDATA[The annotations feature on PDFDocument has been significantly extended in the release of Xojo 2022r2. Continue reading to learn about the new annotation types. Currently,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The annotations feature on PDFDocument has been significantly extended in the release of Xojo 2022r2. Continue reading to learn about the new annotation types.</p>



<p>Currently, Xojo&#8217;s PDFDocument supports the most common type of annotations for PDF &#8211; you know those little yellow boxes displayed like sticky notes on the pages of the PDF document that display their contents when clicked on.</p>



<p>Now with Xojo 2022r2 and later you have more options! And while most of these don&#8217;t look like &#8220;real&#8221; annotations or like something made using the Graphics methods, they will behave as the annotations you are familiar with using in PDF. What I mean by this is that they will display the associated text for the annotation while also allowing the user to Accept/Decline the annotation or interact with them by adding, for example, new replies.</p>



<p>Before reviewing the new options, let me just remind you: The PDF Standard dictates how some features must be implemented for a PDF. After that, it is up to the developers of the PDF viewer app to decide what features are implemented, keep in mind results can vary depending on the PDF viewer you or your user chose to use. As other many things related with PDF files, don&#8217;t expect every PDF viewer apps out there to support or adhere to the annotations outside of the most basic ones.</p>



<p>Adobe is the original creator of the PDF specification and its free PDF viewer, <a href="https://www.adobe.com/acrobat/pdf-reader.html">Acrobat Reader</a> app does support everything Xojo&#8217;s PDFDocument offers.</p>



<h3 class="wp-block-heading">Attaching Files to the PDF</h3>



<p>You&#8217;ll be able to embed any kind of file (except for those based in a Bundle structure) into the PDF document itself, for example an Excel file, a Hi-Res image, etc. Then the user viewing the PDF document will be able to open the attached file clicking in the annotation using whichever PDF Viewer app their computer/device has installed for the attached file format. Because this is an annotation, the user will be able to also edit the annotation or add new replies to it.</p>



<p>This is an example about how to create these kind of annotations:</p>



<pre class="wp-block-code"><code>Var d As New PDFDocument
Var g As Graphics = d.Graphics
Const kContentText As String = "Attached File Annotation: double click on me!"

g.FontSize = 20
g.DrawText(kContentText, 40, 60)

If exampleFile &lt;&gt; Nil Then
  
  // Creating a new EmbeddedSound.
  d.AddEmbeddedFile(exampleFile, 40, 60, g.TextWidth(kContentText), 20)
  
  // Saving the created PDF document to the selected path.
  Var f As FolderItem = FolderItem.ShowSaveFileDialog("","PDFAttachedFile.pdf")
  
  If f &lt;&gt; Nil Then
    
    d.Save(f)
    
  End If
End If
</code></pre>



<p>Here <code>exampleFile</code> is a FolderItem property that has been added to the project and that&#8217;s pointing to the file to embed.</p>



<p>And this is how it looks like in the resulting PDF file:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="439" src="https://blog.xojo.com/wp-content/uploads/2022/06/AttachedFilePDF-1024x439.png" alt="" class="wp-image-10490" srcset="https://blog.xojo.com/wp-content/uploads/2022/06/AttachedFilePDF-1024x439.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/06/AttachedFilePDF-300x129.png 300w, https://blog.xojo.com/wp-content/uploads/2022/06/AttachedFilePDF-768x329.png 768w, https://blog.xojo.com/wp-content/uploads/2022/06/AttachedFilePDF-1536x658.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/06/AttachedFilePDF-2048x878.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<h3 class="wp-block-heading">Callout Annotations</h3>



<p>These kind of annotations are perfect for pointing our or calling attention to any other item in the PDF page. They are highly customizable- you can decide for example a solid or dashed line, the termination of the line, the color and, of course the text to be displayed in the annotation itself.</p>



<p>This is an example showing how to add a Callout annotation to a PDFDocument:</p>



<pre class="wp-block-code"><code>Var d As New PDFDocument
Var g As Graphics = d.Graphics
Const kContentText As String = "Callout Annotation in PDF"

g.FontSize = 40
g.Bold = True
g.DrawText(kContentText, 40, 60)

g.Bold = False
g.FontSize = 12
g.DrawText(kSampleText, 40, 100, 200)

Var originY As Double = (g.TextHeight(kSampleText, 200) / 2)

Var tCallout As New PDFCallout("Callout Example", New Point(250, originY), New Point(300, originY + 50), _
 New Point(350, originY + 50), 100, 50)

tCallout.BorderStyle = PDFAnnotation.BorderStyles.Dashed
tCallout.DashPattern = Array(2.0, 2.0)
tCallout.DrawingColor = Color.Orange
tCallout.LineEndingStyle = PDFAnnotation.LineEndingStyles.OpenArrow
tCallout.Text = "Some sample text in the annotation"
tCallout.FontSize = 9.5

d.AddCallout(tCallout)

// Saving the created PDF document to the selected path.
Var f As FolderItem = FolderItem.ShowSaveFileDialog("","PDFCalloutExample.pdf")

If f &lt;&gt; Nil Then
  
  d.Save(f)
  
End If
</code></pre>



<p>Where <code>kSampleText</code> is a Constant added to the project containing some sample text to be put in the page of the PDF.</p>



<p>And this is how the Callout will look like when opening the resulting PDF file in the viewer app:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="599" src="https://blog.xojo.com/wp-content/uploads/2022/06/Callout-1024x599.png" alt="" class="wp-image-10491" srcset="https://blog.xojo.com/wp-content/uploads/2022/06/Callout-1024x599.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/06/Callout-300x176.png 300w, https://blog.xojo.com/wp-content/uploads/2022/06/Callout-768x450.png 768w, https://blog.xojo.com/wp-content/uploads/2022/06/Callout-1536x899.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/06/Callout-2048x1199.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<h3 class="wp-block-heading">Line Annotations</h3>



<p>A &#8220;Line&#8221; annotation displays a straight line on the page with a text caption inside the line or above it.</p>



<p>It is also possible to add leader lines to both sides of the main line (with possitive or negative values) plus set other properties as the type of the line (solid, dashed, etc), the kind of termination used on both ends of the main line (i.e: open/close arrow, butt, circle, diamond, square…), the drawing color, line width or font size.</p>



<p>This is how a Line annotation looks like when the resulting PDFDocument is viewed using Acrobat Reader (in this case, using Leader lines):</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="605" src="https://blog.xojo.com/wp-content/uploads/2022/06/Line-1024x605.png" alt="" class="wp-image-10493" srcset="https://blog.xojo.com/wp-content/uploads/2022/06/Line-1024x605.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/06/Line-300x177.png 300w, https://blog.xojo.com/wp-content/uploads/2022/06/Line-768x454.png 768w, https://blog.xojo.com/wp-content/uploads/2022/06/Line-1536x907.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/06/Line-2048x1210.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<h3 class="wp-block-heading">Video Annotations</h3>



<p>Yes, you can embed .mp4 files in the PDF created with PDFDocument, and these will be played from the PDF itself. This will increase the size of the generated PDF file because it will add the size of the embedded mp4 file itself! So it is good practice to optimize the video files as much as possible and use the video resolution you want them to be played and not a higher one.</p>



<p>You can also add this kind of content as an Attached File annotation too. In both cases the data of the file will be embedded in the generated PDF file. The main difference in this case is that the mp4 file will be opened using an external app and that you&#8217;ll be able to include other video file format besides .mp4.</p>



<p>The way to add this kind of annotation to a PDFDocument instance is quite simple, for example:</p>



<pre class="wp-block-code"><code>Var d As New PDFDocument
Var g As Graphics = d.Graphics
Const kContentText As String = "Embedded Video Annotation"

g.FontSize = 30
g.DrawText(kContentText, 40, 60)

If exampleVideo &lt;&gt; Nil Then
  
  // Creating a new EmbeddedSound.
  d.AddEmbeddedMovie(exampleVideo, 40, 100, 478, 360)
  
  // Saving the created PDF document to the selected path.
  Var f As FolderItem = FolderItem.ShowSaveFileDialog("","PDFEmbeddedVideo.pdf")
  
  If f &lt;&gt; Nil Then
    
    d.Save(f)
    
  End If
End If
</code></pre>



<p>Where <code>exampleVideo</code> is a FolderItem Property that has been added to the project. This is how a video annotation will look like when opening the resulting PDF in Acrobat Reader:</p>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="918" height="600" src="https://blog.xojo.com/wp-content/uploads/2022/06/VideoAnnotation.gif" alt="" class="wp-image-10494"/></figure>



<h3 class="wp-block-heading">Sound Annotations</h3>



<p>In addition to video annotations, it is also possible to add sound files that can be played from the PDF itself. In this case, the audio files need to be in AIFF format with 2 audio channels (stereo), 16 bits of resolution and a sampling frequency of 44,1 kHz.</p>



<p>As it is the case with video annotations, you can opt to add this kind of content as an Attached File annotation, so it will be opened with an external app and opens the range of sound file formats you can embed into the PDF.</p>



<p>The way to add Sound annotations using PDFDocument is shown here:</p>



<pre class="wp-block-code"><code>Var d As New PDFDocument
Var g As Graphics = d.Graphics
g.FontSize = 30

Const kContentText As String = "Embedded Sound Annotation"

Var x, y, width, height As Double

x = g.Width/2 - width/2
y = 60

width = g.TextWidth(kContentText)
height = g.TextHeight

g.DrawText(kContentText, x, y)

If exampleSound &lt;&gt; Nil Then
  
  // Creating a new EmbeddedSound.
  d.AddEmbeddedSound(exampleSound,x,y,width,height)
  
  // Saving the created PDF document to the selected path.
  Var f As FolderItem = FolderItem.ShowSaveFileDialog("","PDFEmbeddedSound.pdf")
  
  If f &lt;&gt; Nil Then
    
    d.Save(f)
    
  End If
End If
</code></pre>



<p>Here <code>exampleSound</code> is a FolderItem Property added to the project. And this is how a Sound annotation will look when the PDF document is opened using Acrobat Reader:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="361" src="https://blog.xojo.com/wp-content/uploads/2022/06/SoundAnnotation-1024x361.png" alt="" class="wp-image-10495" srcset="https://blog.xojo.com/wp-content/uploads/2022/06/SoundAnnotation-1024x361.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/06/SoundAnnotation-300x106.png 300w, https://blog.xojo.com/wp-content/uploads/2022/06/SoundAnnotation-768x271.png 768w, https://blog.xojo.com/wp-content/uploads/2022/06/SoundAnnotation-1536x542.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/06/SoundAnnotation-2048x722.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<h3 class="wp-block-heading">Markup Annotations</h3>



<p>A Markup annotation is intended to mark an underlying text content using any of the different available types, for example &#8220;Highlight&#8221;, &#8220;Squiggly&#8221; (usually used to mark a text that needs some kind of correction), &#8220;Underline&#8221; or &#8220;Strikeout&#8221;. Besides the Markup type, it is also possible to set the color of the annotation.</p>



<p>For example, the following snippet of code adds two Markup annotations to the page of the PDFDocument using the Highlight and Squiggly types:</p>



<pre class="wp-block-code"><code>Var d As New PDFDocument
Var g As Graphics = d.Graphics
Const kContentText As String = "Markup Annotation in PDF"

g.FontSize = 40
g.Bold = True
g.DrawText(kContentText, 40, 60)

// Adding a Markup annotation with the Highlight type (Default)
d.AddMarkup(40,40,g.TextWidth(kContentText),g.FontSize,"Let's focus on this Section")

g.Bold = False
g.FontSize = 12
g.DrawText(kSampleText, 40, 100, g.Width-80)

// Adding a Markup annotation with the Squiggly type
d.AddMarkup(40,195,210,g.FontSize,"Some text to correct!",Color.Red,PDFAnnotation.MarkupTypes.Squiggly)

// Saving the created PDF document to the selected path.
Var f As FolderItem = FolderItem.ShowSaveFileDialog("","PDFMarkupExample.pdf")

If f &lt;&gt; Nil Then
  
  d.Save(f)
  
End If</code></pre>



<p>And this is how it looks when the resulting document is opened in Adobe Acrobat Reader:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="632" src="https://blog.xojo.com/wp-content/uploads/2022/06/MarkupAnnotation-1024x632.png" alt="" class="wp-image-10499" srcset="https://blog.xojo.com/wp-content/uploads/2022/06/MarkupAnnotation-1024x632.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/06/MarkupAnnotation-300x185.png 300w, https://blog.xojo.com/wp-content/uploads/2022/06/MarkupAnnotation-768x474.png 768w, https://blog.xojo.com/wp-content/uploads/2022/06/MarkupAnnotation-1536x949.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/06/MarkupAnnotation-2048x1265.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


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



<p>Let me end with one other minor improvement to PDFDocument annotations: starting with Xojo 2022r2 all of them include metadata information about the creation and modification date and time. this information will be displayed as part of the annotation metadata when the item is selected in the viewer app.</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>Creating Presentations with PDF and Xojo</title>
		<link>https://blog.xojo.com/2022/05/26/creating-presentations-with-pdf-and-xojo/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 26 May 2022 15:35:00 +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[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[XDC]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10319</guid>

					<description><![CDATA[I know, I know, it's not the usual thing to do when making presentations, but did you know that it is possible to create presentations using Xojo's and PDF? If you're interested in this little experiment, read on and I'll show you how to do it using Xojo's PDFDocument. ]]></description>
										<content:encoded><![CDATA[
<p>I know, I know, it&#8217;s not the <em>usual</em> thing to do when making presentations, but did you know that it is possible to create presentations using Xojo&#8217;s and PDF? If you&#8217;re interested in this little experiment, read on and I&#8217;ll show you how to do it using Xojo&#8217;s <a href="https://documentation.xojo.com/api/pdf/pdfdocument.html#pdfdocument">PDFDocument</a>. </p>



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



<p>Why, you ask? What are the advantages of using a PDF for your presentations? PDF is portable, meaning you can distribute these files easily, usually, with a small file footprint. The content is vectorial (except for images), what means that it will look great no matter the screen resolution of the display/projector used for playing the presentation.</p>



<p>There is one current issue to watch out for, currently <a href="https://acrobat.uservoice.com/forums/590923-acrobat-for-windows-and-mac/suggestions/44616444-fullscreen-page-transitions-in-pdfs-no-longer-work">there&#8217;s a bug on macOS</a> where Acrobat Reader is not able to apply the assigned transitions on Big Sur and later; they still work under Catalina and previous versions of macOS.</p>



<p>In this example project I will create a shortened version of the slides I used in the <a href="https://youtu.be/aSfff3hQaX4">Using Xojo&#8217;s PDFDocument</a> presentation. You&#8217;ll need to change the font names (and any other item) to those you are using and that are installed in your computer.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="960" height="540" src="https://blog.xojo.com/wp-content/uploads/2022/04/Presentation.gif" alt="" class="wp-image-10320"/></figure>
</div>


<h3 class="wp-block-heading">Setting the Viewer Options</h3>



<p>Start by creating a new project for the target you&#8217;re most comfortable with &#8211; Xojo&#8217;s PDFDocument is cross-platform and supported on Desktop, Web, iOS and Console projects. Next, add the Opening Event Handler to the default DesktopWindow/WebWindow/MobileScreen, or choose the Run Event Handler if you chose to create a new Console Project.</p>



<p>Write the following lines of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">// Let's create a new PDFDocument instance with
// the page size set to HD resolution

Var Presentation As New PDFDocument(1920, 1080)

// Let's make sure that the fonts used are embedded in the
// document, so there are no unexpected problems when the
// PDF is opened in a device that doesn't have that
// same fonts installed

Presentation.EmbeddedFonts = True</pre>



<p>The next lines of code will set the default for the View mode of the document when it is opened in Acrobat Reader or any other PDF reader. Since it&#8217;s a presentation, you&#8217;ll likely want the document to be opened in Full Screen mode by default, so let&#8217;s make that happen:</p>



<pre class="wp-block-preformatted">// Let's create a new Instance from the PDFViewerOptions class

Var ViewerOptions As New PDFViewerOptions

// And set the FullScreen property to True
// so the document will set that view size
// when opened in the PDF Viewer app

ViewerOptions.FullScreen = True</pre>



<h3 class="wp-block-heading">Drawing the Background of the Page</h3>



<p>Use a linear gradient brush to fill in the background of all the slides. For convenience, create a new method for it using the following values in the Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> DrawPageBackground</li><li><strong>Parameters:</strong> g As Graphics</li></ul>



<p>Type the following code in the associated Code Editor for the method:</p>



<pre class="wp-block-preformatted">Static backgroundfilling As LinearGradientBrush

If backgroundfilling = Nil Then
  backgroundfilling = New LinearGradientBrush
  backgroundfilling.StartPoint = New Point(g.Width / 2, 0)
  backgroundfilling.EndPoint = New Point(g.Width / 2, g.Height)
  backgroundfilling.GradientStops.Add(New Pair(0.0, &amp;c000000))
  backgroundfilling.GradientStops.Add(New Pair(0.7, &amp;c000000))
  backgroundfilling.GradientStops.Add(New Pair(1.0, &amp;ccccccc))
End If

g.Brush = backgroundfilling
g.FillRectangle(0, 0, g.Width, g.Height)</pre>



<p>All this code does is create a LinearGradientBrush instance ranging from full black to some degree of gray at the bottom of the page. Because we are not going to change the values of the gradient every time we need to call the method, it makes sense to assign it to a Static instead of a Variable.</p>



<p>Then the LinearGradientBrush is assigned to the Brush property of the received Graphic context and, finally, used as the &#8220;filling color&#8221; when drawing the filled rectangle.</p>



<h3 class="wp-block-heading">Drawing the Header</h3>



<p>Now add the method that will be responsible for drawing the header shared by all the slides. Use the following values in the Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> DrawTopHeader</li><li><strong>Parameters:</strong> g As Graphics</li></ul>



<p>And type the following code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">Const kPDFDocumentHeader As String = "PDFDocument"

DrawUpperBand(g, 0, 50)

g.FontName = "Helvetica"
g.FontSize = 180
g.Bold = True

Var x As Double = g.Width / 2 - g.TextWidth(kPDFDocumentHeader) / 2
Var y As Double = 220

g.DrawingColor = &amp;cC9F2C900
g.DrawText(kPDFDocumentHeader, x + 4, 224)

g.DrawingColor = Color.Black

Static linearGradient As LinearGradientBrush

If linearGradient = Nil Then
  Lineargradient = New LinearGradientBrush
  linearGradient.StartPoint = New point(x, y - 224)
  linearGradient.EndPoint = New point(x, y)
  linearGradient.GradientStops.Add(New Pair(0.0, &amp;c00BD4E00))
  linearGradient.GradientStops.Add(New Pair(0.7, &amp;c00FD1F00))
  linearGradient.GradientStops.Add(New Pair(1.0, &amp;c25712900))
End If

g.Brush = LinearGradient
g.DrawText(kPDFDocumentHeader, x, y)</pre>



<p>As you can see, this is quite similar to the previous code. We are using a new Linear Gradient as the filling for the &#8220;PDFDocument&#8221; text. But first, it calls the DrawUpperBand method. This is a method that will draw a picture with a 50% opacity behind the header text, as well as the XDC logo in the lower left corner of the slide. Add a new method using the following values:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> DrawUpperBand</li><li><strong>Parameters:</strong> g As Graphics, x As Integer, y As Integer</li></ul>



<p>Type the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">g.Transparency = 50.0
g.DrawPicture(UpperBand, x, y)
g.Transparency = 0
g.DrawPicture(XDC2x, 20, g.Height - XDC2x.Height)</pre>



<p>Both &#8220;UpperBand&#8221; and &#8220;XDC2x&#8221; are PNG image files added to the project.</p>



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



<p>Because the background and the header are common items in all the slides, we will render them every time we add a new slide (page) to the presentation (document). Create a new method using the following values:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> NextPage</li><li><strong>Parameters:</strong> g As Graphics</li></ul>



<p>And type the following lines of code:</p>



<pre class="wp-block-preformatted">g.NextPage(1920, 1080)
DrawPageBackground(g)
DrawTopHeader(g)</pre>



<h3 class="wp-block-heading">Creating the Content of the Slides</h3>



<p>Now let&#8217;s add the method that will be responsible for adding the text of the main topic on every slide:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> DrawTopic</li><li><strong>Parameters:</strong> g As Graphics, topic As String</li></ul>



<p>And type the following code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">Var x, y As Double
g.FontName = "Anoxic Light"
g.FontSize = 150

x = g.Width / 2 - g.TextWidth(topic) / 2
y = g.Height / 2 - g.TextHeight / 2

Static LinearGradient As LinearGradientBrush

If LinearGradient = Nil Then
  linearGradient = New LinearGradientBrush
  linearGradient.StartPoint = New Point(x, y)
  linearGradient.EndPoint = New Point(x, y - 80)
  linearGradient.GradientStops.Add(New pair(1.0, &amp;c9FE1FF00))
  linearGradient.GradientStops.Add(New pair(0.0, &amp;cF6F6F600))
End If

g.Brush = linearGradient
g.DrawText(topic, x, y)</pre>



<h3 class="wp-block-heading">Setting Transitions Between Slides</h3>



<p>PDFDocument does support the range of transitions available under the PDF standard. In this case we are going to use the simplest: Fade. So, create a new method with the following values:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> AddTransitions</li><li><strong>Parameters:</strong> d as PDFDocument</li></ul>



<p>And type the following lines of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">// New PDFTransition instance, using the Fade style
// with one second of length.

Var t As New PDFTransition(PDFTransition.Styles.Fade, 1)

// And apply it on every page of the PDFDocument, starting on Page 2.
If d.PageCount &gt; 2 Then
  For n As Integer = 2 To d.PageCount
    d.TransitionAt(n) = t
  Next
End If</pre>



<h3 class="wp-block-heading">Putting It All Together</h3>



<p>Now we have all the pieces needed to create this small presentation in PDF. Go back to the Opening Event Handler and type the following lines of code below the last one:</p>



<pre class="wp-block-preformatted">DrawPageBackground(g)
DrawTopHeader(g)
DrawTopic(g, "First Slide")
NextPage(g)
DrawTopic(g, "Second Slide")
NextPage(g)
DrawTopic(g, "Third Slide")
NextPage(g)
DrawTopic(g, "Fourth Slide")

AddTransitions(d)

d.Save(SpecialFolder.Desktop.Child("Presentation.pdf"))</pre>



<p>Done! Run the project and the PDF document will be saved to your computer Desktop. Once you open it in Adobe Reader, the app will detect that the document wants to use the full screen mode and, as soon as you confirm, it will begin the presentation. Depending on your preferences in Acrobat Reader, you may need to use the mouse button or arrow keys to change slides, or it may automatically advance to the next slide after the amount of time set.</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>Graphics: Right and Center Aligned Text</title>
		<link>https://blog.xojo.com/2022/05/17/graphics-right-and-center-aligned-text/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 17 May 2022 13:00:00 +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[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10351</guid>

					<description><![CDATA[The DrawText method from the Graphics class offers a simple way to left-align text at the given X and Y coordinates, even applying a wrap value to wrap every line of the text block at the provided width value. Wouldn't it be great to be able to do the same thing while aligning blocks of text to the right and center? Continue reading and I will show you a technique you can use as the starting point which you can fine-tune to your specific needs.]]></description>
										<content:encoded><![CDATA[
<p>The <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-drawtext">DrawText</a> method from the <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics">Graphics</a> class offers a simple way to left-align text at the given X and Y coordinates, even applying a wrap value to wrap every line of the text block at the provided width value. Wouldn&#8217;t it be great to be able to do the same thing while aligning blocks of text to the right and center? Continue reading and I will show you a technique you can use as the starting point which you can fine-tune to your specific needs.</p>



<div class="wp-block-image wp-image-10353 size-large is-style-default"><figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="665" src="https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentLinux-1024x665.png" alt="" class="wp-image-10353" srcset="https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentLinux-1024x665.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentLinux-300x195.png 300w, https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentLinux-768x499.png 768w, https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentLinux.png 1472w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Right-aligned and centered text on Linux Desktop, both in a Picture and a document created with PDFDocument.</figcaption></figure></div>



<h3 class="wp-block-heading">Graphics Extensions</h3>



<p>To start, and because we want to provide this ability to any graphic context, it makes sense to include all our logic in a Module. Let&#8217;s name it GraphicExtensions (as usual you can opt to use any other name). Start a new Xojo project and add a new Module to it using the following values in the Inspector Panel:</p>



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



<p>Next, and with the GraphicsExtensions item selected in the Navigator, add a new method to it using the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> DrawText</li><li><strong>Parameters:</strong> Extends g As Graphics, value As String, x As Double, y As Double, wrap As Double, alignment As TextAlignments = TextAlignments.Left</li><li><strong>Scope:</strong> Global</li></ul>



<p>As you can see, it nearly replicates the standard DrawText method from the Graphics class. Some things to note here, we are using the <a href="https://documentation.xojo.com/api/language/extends.html#extends">Extends</a> keyword in combination with the first parameter to instruct the compiler that this method will &#8220;extend&#8221; the existing functionality of the Graphics class, so you&#8217;ll be able to invoke it using the usual dot notation on any instance created from the Graphics class.</p>



<p>The second thing is the last of the parameters &#8220;alignment As TextAlignments&#8221; <a href="https://documentation.xojo.com/api/text/textalignments.html#textalignments">TextAlignments</a> is a global enumeration that we are going to use to learn the text alignment the user wants to apply to the block of text.</p>



<p>Next, type the following snippet of code in the associated Code Editor for the method:</p>



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

value = value.ReplaceLineEndings(EndOfLine)

Select Case Alignment
  
Case TextAlignments.Default, TextAlignments.Left
  
  g.DrawText(value, x, y + g.TextHeight, wrap - x)
  
Case TextAlignments.Center, TextAlignments.Right
  
  Var tOutput() As String = PrepareOutput(g, value, wrap, x)
  
  Var tx, ty As Double
  ty = y + g.TextHeight
  
  Select Case Alignment
    
  Case TextAlignments.Center
    
    For Each s As String In tOutput
      
      tx = If(Wrap = 0, ((g.Width - Wrap) / 2 - g.TextWidth(s) / 2) + (x / 2), (wrap / 2 - g.TextWidth(s) / 2) + (x / 2))
      g.DrawText(s, tx, ty)
      ty = ty + g.TextHeight
      
      If ty &gt; g.Height Then Exit
      
    Next
    
  Case TextAlignments.Right
    
    For Each s As String In tOutput
      
      tx = If(Wrap = 0, (g.Width - g.TextWidth(s)) + x / 2, (wrap - x) - g.TextWidth(s) + x)
      g.DrawText(s, tx, ty)
      ty = ty + g.TextHeight
      
      If ty &gt; g.Height Then Exit
      
    Next
    
  End Select
  
End Select
</pre>



<p>As you can see, this code looks into the value of the Alignment parameter to see the approach to apply. If the Alignment equals to Default or Left we simply call the standard DrawText method on the received graphics context represented by the &#8220;g&#8221; variable. If not, we need to do some stuff to the received block of text to create the required chunks (or lines) that do fit the available width plus the received wrapping value. This is done in the PrepareOutput method.</p>



<p>Once we have all the lines with the apropiate widths in the Output array, then we only need to do some basic maths in order to calculate the final TX coordinate for every line, incrementing the TY coordinate on every new line to draw. As you can see, and in order to speed-up things a bit more, we check if the calculated TY coordinate is beyond the visible area of the graphic context and, if it is the case, we exit the function (it wouldn&#8217;t make much sense drawing text that is not going to be visible and whose processing consumes time).</p>



<p>Of course, the calculation of the TX and TY coordinates depends on the value of the Alignment parameter; that is, if the block of text is going to be drawn right aligned or centered.</p>



<h3 class="wp-block-heading">Calculating Every Line Width</h3>



<p>Now add the PreapareOutput method to the GraphicsExtensions module using the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> PrepareOutput</li><li><strong>Parameters:</strong> g As Graphics, value As string, wrap As Double, x As Double</li><li><strong>Return Type:</strong> String()</li><li><strong>Scope:</strong> Private</li></ul>



<p>And typing the following snippet of code in the associated Code Editor:</p>



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

Var totalWidth As Double = If(wrap = 0, g.Width - x, wrap - x)

Var Input() As String = value.ToArray(EndOfLine)
Var output() As String

For Each s As String In Input
  
  If g.TextWidth(s) &lt;= totalWidth Then
    output.Add(s)
  Else
    AdjustWidth(g, s, totalWidth, output)
  End If
  
Next

Return output
</pre>



<p>Once again, the first lines are some pragmas put in place to speed-up things, then the totalWidth variable will store the required maximum width value for every line. The Input array is going to store every paragraph from the source text, while the Output array will store every processed line and, the one returned to the method calling PrepareOutput.</p>



<p>Then we need to iterate every entry in the Input array and check if its width meets the totalWidth requirement. If it does, then that entry will be added to the Output array; if not, we still need to split the &#8220;paragraph&#8221; into as many chunks of text as needed that meet the expected maximum width. That is something that&#8217;s going to be done by the AdjustWidth method.</p>



<h3 class="wp-block-heading">Splitting Chunks of Text …&nbsp;Recursively</h3>



<p>Add the third, and last required, method to the GraphicExtensions module using the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> AdjustWidth</li><li><strong>Parameters:</strong> g As Graphics, s As String, width As Double, ByRef output() As String</li><li><strong>Scope:</strong> Private</li></ul>



<p>Next, type the following lines of code in the associated Code Editor:</p>



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

Var n As Integer

If g.TextWidth(s) &lt;= width Then
  output.Add(s)
Else
  
  // This can be improved pre-calculating the initial value for "n"…&nbsp;so it's
  // left as an exercise for the reader :-)
  
  While round(g.TextWidth(s.Left(s.Length - n))) &gt; width
    n = n + 1
  Wend
  
  output.Add(s.Left(s.Length - n))
  
  AdjustWidth(g, s.Right(n), width, output)
  
End If
</pre>



<p>As you can see, if the width of the received string is less than or equal to the expected width, then it is added to the Output array. If not, we are using a really less than optimal technique to calculate the appropriate one, saving the resulting string to the Output array and passing the remaining of the string again to the method. You&#8217;ll probably want to change some things here to better pre-calculate the initial value of the <code>n</code> variable.</p>



<h3 class="wp-block-heading">Testing It</h3>



<p>We have everything in place, so let&#8217;s test it! Start by adding a new constant to the Window1 window and name it <code>kSampleText</code>. Use the associated Inspector Panel to assign the block of text you want to use for testing (personally I like to use the <a href="https://www.lipsum.com">https://www.lipsum.com</a> website for getting sample text).</p>



<p>If you prefer, you can <a href="https://www.dropbox.com/s/amt86u9fnbq31xh/GraphicsExtensions.xojo_binary_project.zip?dl=1">download the complete Example project from this link</a>.</p>



<p>Add next the Opening Event Handler to the Window1 window and type following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">Var p As New Picture(612, 792)
Var d As New PDFDocument

Var g As Graphics = p.Graphics
g.FontName = "Helvetica"
Var gPDF As Graphics = d.Graphics

g.DrawText(kSampleText, 40, 10, 570, TextAlignments.Right)
gPDF.DrawText(kSampleText, 40, 10, 570, TextAlignments.Right)

Var tH As Double = g.TextHeight(kSampleText, 570) + g.TextHeight * 4
Var tPH As Double = gPDF.TextHeight(kSampleText, 570) + gPDF.TextHeight * 4

g.DrawText(kSampleText, 40, th, 570, TextAlignments.Center)
gPDF.DrawText(kSampleText, 40, tPh, 570, TextAlignments.Center)

CustomDesktopCanvas1.Image = p
d.Save(SpecialFolder.Desktop.Child("PDFTextAlignment.pdf"))
</pre>



<p>As you can see, I chose the &#8220;Helvetica&#8221; font, but you can change it to any font that is available in your OS. The point here is that we are feeding our &#8220;extended&#8221; DrawText method with the sample text and the alignment we want to use in for drawing it both in the graphic context of a Picture and the one from a PDFDocument instance. Also, CustomDesktopCanvas1 is a simple Canvas subclass with an &#8220;image&#8221; property added to it as a computed property, so when a new value is assigned it will refresh itself and the Paint event will draw the picture centered in the canvas.</p>



<div class="wp-block-image is-style-default"><figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="838" src="https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentMacOS-1024x838.png" alt="" class="wp-image-10352" srcset="https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentMacOS-1024x838.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentMacOS-300x245.png 300w, https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentMacOS-768x628.png 768w, https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentMacOS-1536x1257.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/05/AlignmentMacOS-2048x1675.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>Run the example project and you should see something similar to the result displayed in the screenshots. Of course, there are still some details to take care of, for example when a line is split so the last letter goes over to the next line and things like that but, as mentioned in the beginning of this post, this is just a starting point. Adapt and improve upon it as needed.</p>



<p>Have fun!</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>ImageViewer: Loading Images from a URL in Desktop and iOS Apps</title>
		<link>https://blog.xojo.com/2022/04/18/imageviewer-loading-images-from-a-url-in-desktop-and-ios-apps/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 18 Apr 2022 16:05:36 +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[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10292</guid>

					<description><![CDATA[The WebImageViewer control allow us to load and display any image retrieved from a given URL. Wouldn't be nice to have that same kind of functionality in the Desktop and iOS versions of the ImageViewer? Continue reading and I'll show you how to achieve just that.]]></description>
										<content:encoded><![CDATA[
<p>The <a href="https://documentation.xojo.com/api/user_interface/web/webimageviewer.html#webimageviewer">WebImageViewer</a> control allows you to load and display any image retrieved from a given URL. Wouldn&#8217;t it be nice to have that same kind of functionality in the Desktop and iOS versions of the ImageViewer? Continue reading and I&#8217;ll show you how to achieve just that.</p>



<p>Let&#8217;s start with the Desktop version. Once we&#8217;ve finished this bit, you&#8217;ll only need to repeat the same steps using the <a href="https://documentation.xojo.com/api/user_interface/mobile/mobileimageviewer.html#mobileimageviewer">MobileImageViewer</a> to doo the same in your iOS app- just copy and paste the events, methods and properties to your iOS project!</p>



<p>Begin with a new Desktop project in Xojo, add a new <a href="https://documentation.xojo.com/api/user_interface/desktop/desktopimageviewer.html#desktopimageviewer">DesktopImageViewer</a> by dragging it from the Library and dropping it into the Navigator. This creates a subclass of the DesktopImageViewer.</p>



<p>With the new CustomDesktopImageViewer still selected in the Navigator, use the associated Inspector Panel to change its name to &#8220;URLDesktopImageViewer&#8221; (of course you can use any name you want).</p>



<h3 class="wp-block-heading">Adding Properties</h3>



<p>Because we want to load an image from an URL, let&#8217;s start by adding some properties to our subclass. These will be responsible for storing the URL and the underlying URLConnection instance needed to retrieve the image data from the URL.</p>



<p>Start with the URL property. With URLDesktopImageViewer selected in the Navigator, choose the option &#8220;Add To URLDesktopImageViewer &gt; Property&#8221; from the contextual menu. Once this is added, use the associated Inspector Panel to change the following fields:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> URL</li><li><strong>Type:</strong> String</li><li><strong>Scope:</strong> Public</li></ul>



<p>With that property still selected in the Navigator, choose the option &#8220;Convert to Computed Property&#8221;. This adds a couple of methods under the URL property: Get and Set.</p>



<p>Select the Set method. The code put in that method will be executed every time the user (or the code) assigns a new value to the property. Now, add the following lines of code to the associated code editor for the Set method:</p>



<pre class="wp-block-preformatted">mURL = value
LoadURL</pre>



<p>You&#8217;ll likely want to display that property in the Inspector Panel so that the user can type a URL for that property using the Inspector Panel when a new instance of the class is added to the Layout Editor. In order to do that, select the URLDesktopImageViewer subclass in the Navigator and choose the Inspector Behavior option from the contextual menu. That action will bring up the following dialog:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2022/04/URLProperties-1024x784.png" alt="" class="wp-image-10308" width="768" height="588" srcset="https://blog.xojo.com/wp-content/uploads/2022/04/URLProperties-1024x784.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/04/URLProperties-300x230.png 300w, https://blog.xojo.com/wp-content/uploads/2022/04/URLProperties-768x588.png 768w, https://blog.xojo.com/wp-content/uploads/2022/04/URLProperties.png 1212w" sizes="auto, (max-width: 768px) 100vw, 768px" /></figure>
</div>


<p>You&#8217;ll find the URL property under the Behavior section. Make sure to select the checkbox associated with the property and confirm the change by clicking the &#8220;OK&#8221; button.</p>



<p>Finally, add a second property to the URLDesktopImageViewer subclass. With the new property selected in the Navigator, use the associated Inspector Panel to change the following fields:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> Connection</li><li><strong>Type:</strong> URLConnection</li><li><strong>Scope:</strong> Protected</li></ul>



<h3 class="wp-block-heading">Adding (and Defining) Events</h3>



<p>With the URLDesktopImageViewer still selected in the Navigator, choose the &#8220;Add to URLDesktopImageViewer &gt; Event Handler…&#8221; option from the contextual menu to open the &#8220;Add Event Handler&#8221; window.</p>



<p>Select the Opening and Closing events and click on the &#8220;OK&#8221; button to confirm and close the window. You&#8217;ll see these two events have been added under the subclass.</p>



<p>Select the Opening event handler in the Navigator under the subclass hierarchy (if you don&#8217;t see the event names, then click on the disclosure triangle associated with the &#8220;Event Handlers&#8221; entry). That action will bring up the associated Code<strong> </strong>Editor for the event.</p>



<p>Write these two lines of code:</p>



<pre class="wp-block-preformatted">LoadURL
RaiseEvent Opening</pre>



<p>And because our subclass is &#8220;consuming&#8221; the Opening Event Handler, we need to create a new Event Definition for it, so the consumers of the subclass can handle their own code in that same event. To do that, with the URLDesktopImageViewer still selected in the Navigator, choose the &#8220;Add To URLDesktopImageViewer &gt; Event Definition&#8221; option from the contextual menu.  Xojo&#8217;s IDE will now add a new entry under the Events Definitions section of the class. Select it and use the associated Inspector Panel to change the following value:</p>



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



<p>Now, select the Closing event handler for the URLDesktopImageViewer subclass in the Navigator and type the following lines of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">If connection &lt;&gt; Nil Then
    RemoveHandler connection.contentReceived, WeakAddressOf ContentReceived
End If

RaiseEvent Closing</pre>



<p>And because the subclass is consuming the Closing event handler, you&#8217;ll need to add a new Event Definition for it using the same event handler name (Closing).</p>



<h3 class="wp-block-heading">Adding Methods</h3>



<p>As you see, the code in the Set method for the URL property and the Opening Event Handler are calling the LoadURL method. So we need to add that! With the URLDesktopImageViewer selected in the Navigator, choose the &#8220;Add to URLDesktopImageViewer &gt; Method&#8221; option from the contextual menu using the following value in the associated Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> LoadURL</li></ul>



<p>And type the following lines of code in the associated Code Editor for the method:</p>



<pre class="wp-block-preformatted">If Me.mURL &lt;&gt; "" Then
    Try
      If connection &lt;&gt; Nil Then
        RemoveHandler connection.ContentReceived, WeakAddressOf ContentReceived
      End If

      connection = New URLConnection
      AddHandler connection.ContentReceived, WeakAddressOf ContentReceived
      connection.Send("GET", mURL)
    End Try
End If</pre>



<p>In short, this creates a new URLConnection instance and assigns it to the Connection property. In order to handle the events generated during the URLConnection instance execution, we need to attach its events to some methods in our code. We achieve this with the AddHandler function which provides the name of the name we want to handle, in this case ContentReceived and the address of the method that will do the work. This is done by passing the method name (ContentReceived) to the function WeakAddressOf (or AddressOf, for the case).</p>



<p>Then, we need only to call the Send method of the URLConnection class and provide the &#8220;GET&#8221; verb and the URL that holds the picture we want to retrieve.</p>



<p>The last step is adding the ContentReceived method that will substitute the functionality of the ContentReceived Event Handler for our URLConnection instance.</p>



<p>Add a new method to the URLDesktopImageViewer subclass using the following values in the associated Code Editor:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> ContentReceived</li><li><strong>Parameters:</strong> tCon As URLConnection, URL As String, HTTPStatus As Integer, content As String</li><li><strong>Scope:</strong> Public</li></ul>



<p>As you can see, when we create a method that will substitute the functionality of an Event Handler, we need to provide the same type and number of parameters used by the original Event Handler, plus a first parameter that will hold the instance itself. In this case it is the parameter <code>tCon As URLConnection</code>.</p>



<p>Now type the following lines of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">Try

    If httpStatus = 200 Then Me.Image = Picture.FromData(content)

End Try</pre>



<p>If we receive the &#8220;OK&#8221; status from the connection instance, then we assign the Picture created from the received data to the Image property of the control. And because <em>things can go wrong</em><sup>TM</sup>, and we didn&#8217;t take care of all the possibilities in order to keep this tutorial short, that line of code is wrapped in a <code>Try…Catch</code> block.</p>



<h3 class="wp-block-heading">Testing URLDesktopImageViewer</h3>



<p>In order to test our subclassed control, select the Window1 item in the Navigator so the Layout Editor is open in the main area of the Xojo IDE. Then, drag the URLDesktopImageViewer item from the Navigator and drop it in the Window control displayed in the Layout Editor.</p>



<p>With the new control selected in the Layout Editor, use the Inspector panel to set its width and height values, and any other parameter you wish. The interesting thing here is that you&#8217;ll find the URL field under the Behavior section of the Inspector Panel; so go ahead and type any URL pointing to the image you want to retrieve (for example: https://www.xojo.com/assets/img/logo@2x.png)</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="646" height="568" src="https://blog.xojo.com/wp-content/uploads/2022/04/Assets.png" alt="" class="wp-image-10310" srcset="https://blog.xojo.com/wp-content/uploads/2022/04/Assets.png 646w, https://blog.xojo.com/wp-content/uploads/2022/04/Assets-300x264.png 300w" sizes="auto, (max-width: 646px) 100vw, 646px" /></figure>
</div>


<p>Done! Run the app and if your computer is connected to the Internet you&#8217;ll see how the image is retrieved from the given URL and displayed by the ImageViewer!</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="551" height="1024" src="https://blog.xojo.com/wp-content/uploads/2022/04/Captura-de-pantalla-2022-04-11-a-las-18.38.26-551x1024.png" alt="" class="wp-image-10295" srcset="https://blog.xojo.com/wp-content/uploads/2022/04/Captura-de-pantalla-2022-04-11-a-las-18.38.26-551x1024.png 551w, https://blog.xojo.com/wp-content/uploads/2022/04/Captura-de-pantalla-2022-04-11-a-las-18.38.26-161x300.png 161w, https://blog.xojo.com/wp-content/uploads/2022/04/Captura-de-pantalla-2022-04-11-a-las-18.38.26.png 738w" sizes="auto, (max-width: 551px) 100vw, 551px" /></figure>
</div>


<p>Of course, you can repeat these steps (or copy and paste them) in order to re-create your own URLiOSImageViewer control, as you can see in the above screenshot, with the Xojo iOS app running in the Simulator.</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>Modern, Visual Basic For Your Mac</title>
		<link>https://blog.xojo.com/2021/06/24/modern-visual-basic-for-your-mac/</link>
		
		<dc:creator><![CDATA[Alyssa Foley]]></dc:creator>
		<pubDate>Thu, 24 Jun 2021 16:41:57 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[VB Alternative]]></category>
		<category><![CDATA[VB for Mac]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8638</guid>

					<description><![CDATA[Did you love Visual Basic? A lot of us did, but it's 2021 and technology is ever-changing. As you look at the modern alternatives, consider Xojo. For over 20 years, Xojo has been the spiritual successor to VB, a rapid, cross-platform programming language and integrated development environment (IDE). Often called "VB for the Mac", Xojo is more powerful than VB6 and more approachable than VB.NET. Two factors that are increasingly important because modern coders are everywhere, not just in the technology department. ]]></description>
										<content:encoded><![CDATA[
<p>Did you love Visual Basic? A lot of us did, but technology is ever-changing. As you look at the modern alternatives, consider Xojo. For over 20 years, Xojo has been the true successor to VB, a rapid, cross-platform programming language and integrated development environment (IDE). Often called &#8220;VB for the Mac&#8221;, Xojo is more powerful than VB6 and more approachable than VB.NET &#8211; two factors that are increasingly important because modern coders are everywhere, not just in the technology department.</p>



<p>Unlike VB and VB.NET, Xojo allows you to develop on your platform of choice- Windows, Mac or Linux. But being able to develop wherever you like isn&#8217;t the only reason Xojo is a <a href="https://blog.xojo.com/2013/06/19/a-modern-alternative-to-visual-basic/">great alternative to Visual Basic</a>. Xojo is fully object-oriented, supported and <a href="https://documentation.xojo.com/Resources:Release_Notes">regularly updated</a>. It allows you to cross-compile desktop apps for Windows, Mac and Linux and Raspberry Pi. Currently, a Mac is required to compile projects for macOS and for iOS development and compilation; <a href="https://blog.xojo.com/2020/12/07/why-building-apps-for-macos-requires-a-mac/">learn why</a>. In additional to all this, Xojo allows you to compile apps for mobile and the web with that same powerful language and IDE. </p>



<h2 class="wp-block-heading">Evaluating Xojo as a Visual Basic Alternative</h2>



<p>Xojo is free for learning and development so you can take all the time you need to evaluate. Download Xojo and start learning while you develop, run and debug your projects in Xojo&#8217;s free IDE. Going through the QuickStarts and Tutorials, you&#8217;ll recognize how your knowledge of VB leads you to quickly embrace Xojo. Purchase a license only when you are ready to compile your projects. </p>



<p>To help make your transition from Visual Basic to Xojo easier, download this open-source <a href="https://github.com/xojo/VB">Xojo.VB</a> library that maps many Visual Basic commands to their Xojo equivalents. Watch this <a href="https://youtu.be/9d9PhFWCQC4">Migrating from VB video</a>&nbsp;to see a simple VB app get migrated to Xojo. Visit our <a href="https://documentation.xojo.com/topics/migrating_from_other_development_tools/migrating_from_visual_basic.html">Migrating from Visual Basic</a> page at the Xojo Docs&nbsp;for more details about Data Types, Commands and Controls. </p>



<h2 class="wp-block-heading">Modernize Visual Basic Apps for Web and Mobile</h2>



<p>Xojo it is a great way to modernize legacy Visual Basic desktop apps to web and mobile platforms. </p>



<p><strong>Web Development</strong> &#8211; With Xojo&#8217;s programming language and IDE, web apps are as simple to develop as desktop apps. Instead of HTML, CSS, PHP, JavaScript, and AJAX, you&#8217;ll save tons of development time using the Xojo programming language. <a href="https://www.xojo.com/products/web.php">Xojo web apps</a> are compiled to binary code and can be deployed to any server (Linux, macOS or Windows) as standalone web apps. For simple, secure one-click deployment of web apps plus built-in SSL and database support, use <a href="https://www.xojo.com/cloud/">Xojo Cloud</a>.</p>



<p><strong>Mobile Development</strong> &#8211; With <a href="https://www.xojo.com/products/mobile.php">Xojo iOS</a> you can design your apps using drag and drop in the layout editor, add your code and build. Access the iOS-features you&#8217;d expect, like sharing panel and your photo library, and also the iPhone&#8217;s hardware-based features, like motion, location and camera. Xojo makes iOS development familiar and fast. <a href="https://blog.xojo.com/2021/06/11/android-2021-summer-preview/">Xojo Android</a> is currently in development. </p>



<h2 class="wp-block-heading"><strong>Similarities Between Xojo and V</strong>isual Basic</h2>



<p>As a Visual Basic developer, you will find Xojo very familiar. VB and Visual Basic.NET use a language similar to the Xojo programming language. You will notice that many of the commands are nearly the same. The default UI controls included with VB are, for the most part, also included with Xojo. You&#8217;ll also find that Xojo has several controls that are not included by default with VB like HTMLViewer/WebHTMLViewer, MoviePlayer/WebMoviePlayer and SearchField.&nbsp;</p>



<p><strong>Language</strong> &#8211; The Xojo&nbsp;programming language has commands like If..Then..Else, For..Next, and While..Loop. You will also find the object-oriented capabilities of Xojo are quite similar to VB.NET. </p>



<p><strong>Data Types</strong> &#8211; Xojo shares many of the same data types with VB6 and VB.NET, including: Integer, Double, String/Text, Currency, Boolean, Variant.</p>



<p><strong>Controls</strong> &#8211; Xojo has many common controls including: Buttons, Labels, TextFields, TextAreas, ListBoxes (grids), PopupMenus, ProgressBars, toolbars and more.</p>



<h2 class="wp-block-heading"><strong>Differences Between Xojo and V</strong>isual Basic</h2>



<p>Xojo definitely feels similar to Visual Basic, but you&#8217;ll find there are differences too. Many of these differences stem from Xojo&#8217;s focus on being cross-platform. </p>



<p><strong>Shared Libraries</strong> &#8211;  Xojo cannot create DLLs, ActiveX controls, .NET assemblies or any kind of shared libraries. Since these are all Windows-specific technologies, that is somewhat understandable for a cross-platform tool. If you&#8217;re depending on a DLL and are planning to deploy on Mac or Linux, you&#8217;ll need another solution for those operating systems. Fortunately, Xojo supports conditional compilation which makes it easy for your code to use DLLs only when compiling for Windows. If you find another library that provides a solution for MacOS and/or Linux, you can use conditional compilation there as well.</p>



<p><strong>Compiler and Run-time</strong> &#8211; Xojo apps are<strong> compiled to native code.</strong> They do not contain byte-code that is run by a virtual machine (as with .NET). The run-time library is included with your applications so there is nothing additional that needs to be installed on users&#8217; computers.</p>



<p><strong>Language and Framework</strong> &#8211; Xojo is fully object-oriented. Unlike VB6, you can have classes that use inheritance and other object-oriented features. The Xojo framework is designed to be simple to use and support cross-platform applications; it provides access to many things you&#8217;ve come to expect such as file handling, databases, graphics and more.</p>



<p><strong>File I/O</strong> &#8211; One of the biggest differences between VB6 and Xojo is file I/O. Xojo consolidates all its file processing into a few classes: FolderItem, TextInputStream, TextOutputStream and BinaryStream. VB6 uses hard-coded file paths and less flexible file access methods, primarily because it only needs to work with Windows-specific file paths.</p>



<p><strong>Data Types</strong> &#8211; Xojo is strongly typed, just like VB.NET. VB6 allows you to do some things the old-school, BASIC way, the most significant of which is using variables without declaring them (the type is inferred by a suffix on the name). Xojo does not allow this. Use the OPTION EXPLICIT command in all your Visual Basic code to have VB enforce explicit variable declarations.</p>



<p><strong>Improved Error Handling</strong> &#8211; Xojo has modern exception handling using Try/Catch, Exception and App.UnhandledException.</p>



<h2 class="wp-block-heading">Enjoy Coding Again</h2>



<p>Whether you need VB for Mac, or VB for Linux or just an updated, rapid-application development tool for Windows, Xojo is that alternative! If you find yourself frustrated with VB.NET or you&#8217;re still looking for something to replace VB6, test out Xojo. If saving time and money is a concern, Xojo is a development tool you should consider. Go ahead and download Xojo and see how much you have missed coding like this! </p>



<p>Like all development tools we know Xojo isn&#8217;t a fit for <em>every</em> project, so all Xojo licenses come with a 90 day money-back guarantee. We&#8217;ve been around for more than <a href="https://blog.xojo.com/2021/04/01/suddenly-it-was-25-years-ago/">25 years</a> now, and we&#8217;ll be here when your next project is looking for a quick way to get off the ground and into development! Questions? I&#8217;m here for that, email me, a human being and Xojo fan, anytime at hello@xojo.com.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tip: Temporary FolderItems</title>
		<link>https://blog.xojo.com/2020/09/23/tip-temporary-folderitems/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 23 Sep 2020 20:54:54 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[FolderItem]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7494</guid>

					<description><![CDATA[Sometimes we need to deal with temporary FolderItem instances, and in those cases it would be great to not have to care about when they&#8230;]]></description>
										<content:encoded><![CDATA[<p>Sometimes we need to deal with temporary FolderItem instances, and in those cases it would be great to not have to care about when they get out of scope in order to delete them. Wouldn&#8217;t it be great to automate that task? Continue reading and you&#8217;ll see how easy it is to implement this!<span id="more-7494"></span></p>
<p>In order to instruct a <code>FolderItem</code> to delete itself when it&#8217;s out of scope, we will create a new class that will act as a wrapper for the FolderItem, making use of the <code>Operator_Convert</code> method, so we can assign a FolderItem to it and also get the underlying FolderItem wrapped in it.</p>
<p>So, go ahead and create a new Class. We can name it as <code>TempFolderItem</code> with an empty <code>Super</code> class in the Inspector Panel.</p>
<p>Add a new property to the new TempFolderItem class, using the following values in the Inspector Panel:</p>
<ul>
<li><strong>Name:</strong> mFile</li>
<li><strong>Type:</strong> FolderItem</li>
<li><strong>Scope:</strong> Protected</li>
</ul>
<p>Next, let&#8217;s add a Constructor method to our class with the following signature:</p>
<ul>
<li><strong>Name:</strong> Constructor</li>
<li><strong>Parameters:</strong> f As FolderItem</li>
<li><strong>Scope:</strong> Public</li>
</ul>
<p>And simply put this line of code in the associated Code Editor:</p>
<pre>mFile = f</pre>
<p>Then, we need to add a couple of <strong>Operator_Convert</strong> methods:</p>
<ul>
<li><strong>Name:</strong> Operator_Convert</li>
<li><strong>Parameters:</strong> f As FolderItem</li>
<li><strong>Scope:</strong> Public</li>
<li><strong>Code Editor:</strong> <code>mFile = f</code></li>
</ul>
<ul>
<li><strong>Name:</strong> Operator_Convert</li>
<li><strong>Returned Type:</strong> FolderItem</li>
<li><strong>Scope:</strong> Public</li>
<li><strong>Code Editor:</strong> <code>Return mFile</code></li>
</ul>
<p>Finally, we will add the Destructor method. This one will be in charge of deleting the underlaying FolderItem once the class instance is out of scope:</p>
<ul>
<li><strong>Name:</strong> Destructor</li>
<li><strong>Scope:</strong> Public</li>
<li><strong>Code Editor:</strong></li>
</ul>
<pre>Try

  If mfile &lt;&gt; Nil And mfile.Exists And mfile.IsWriteable Then

    If Not mFile.IsFolder Then

    mfile.Remove

  End

End If

Catch e As IOException
  Raise e
End Try</pre>
<h2>Temporary FolderItems in Practice</h2>
<p>That&#8217;s all &#8211; our class definition is done! In order to test it, create a Desktop project, add the <code>Open</code> Event Handler to the default window and write this snippet of code in the Code Editor:</p>
<pre>Const textContent As String = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
f = New TempFolderItem(specialfolder.desktop.child("Test.txt"))

Try

  Var tos As TextOutputStream = TextOutputStream.Open(f)
  tos.WriteLine textContent
  tos.Close

Catch e As IOException
  MessageBox(e.Message)
End Try</pre>
<p>Next add a new Property to the default window (<code>Window1</code>) using the following values in the Panel Inspector:</p>
<ul>
<li><strong>Property Name:</strong> f</li>
<li><strong>Type:</strong> TempFolderItem</li>
<li><strong>Scope:</strong> Public</li>
</ul>
<p>This way, the TempFolderItem will be in Scope (this is, in memory) while the Window1 window remains opened. Once we close the window, everything will be destroyed from memory, including this property. Also the underlying FolderItem stored on it via the Destructor method of our class will be deleted.</p>
<p>Run the example project and see how it works. While the <code>Window1</code> window remains open, our file will be available in the Desktop; but as soon we close the <code>Window1</code> window… the file will be deleted automatically!</p>


<p>Questions? Ask me about Xojo programming 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>Hour of Code: Xojo Dojo</title>
		<link>https://blog.xojo.com/2018/11/29/hour-of-code-xojo-dojo/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 29 Nov 2018 08:00:41 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Hour of Code]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[Xojo Dojo]]></category>
		<category><![CDATA[Xojo IDE]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5198</guid>

					<description><![CDATA[Today kicks off Computer Science Education Week 2018! Alongside this is the Hour of Code promotion where schools throughout the world get students to try at least 1 hour of programming at some point during the week. This year I plan to demonstrate Xojo Dojo with a Raspberry Pi and show the kids how much fun coding can be.]]></description>
										<content:encoded><![CDATA[<p>December 3rd kicks off <a href="https://csedweek.org">Computer Science Education Week 2018</a>! Computer Science Education Week is held in early December every year in recognition of the birthday of computing pioneer <a href="https://en.wikipedia.org/wiki/Grace_Hopper">Admiral Grace Hopper</a>. Alongside this is the <a href="https://hourofcode.com/us">Hour of Code promotion</a> where schools throughout the world get students to try at least 1 hour of programming at some point during the week.</p>
<p>Each year for Hour of Code, I volunteer at the local Middle School to talk to the students about what it is like to be a programmer and do a little bit of programming. This year I plan to demonstrate <a href="https://gitlab.com/xojo/XojoDojo">Xojo Dojo</a> with a Raspberry Pi and show the kids how much fun coding and Xojo programming can be.</p>
<p><span id="more-5198"></span></p>
<p><img loading="lazy" decoding="async" class="alignnone size-medium" src="https://documentation.xojo.com/images/b/b2/Xojo_Dojo.png" width="1195" height="758" /></p>
<p>My wife teaches 7th grade math so I have a somewhat receptive audience, at least when it comes to middle school students. Of course, I&#8217;ll be sure to show off a few games made with Xojo. <a href="https://blog.xojo.com/2017/12/05/hour-of-code-2017/">Asteroid Run</a> was popular last year.</p>
<p>As Xojo developers you have a great perspective on coding, which would be wonderful to share with the youth of today. Most schools would absolutely welcome a guest speaker for a day so if you have a child in school or know someone that works at a school, I encourage you to see if you can help out by volunteering.</p>
<p>Looking for ideas? Here&#8217;s what we&#8217;ve done for the Hour of Code in past years:</p>
<ul>
<li><a href="https://blog.xojo.com/2013/12/12/hour-of-code-math-facts/">Hour of Code 2013: Math Facts</a></li>
<li><a href="https://blog.xojo.com/2013/12/11/hour-of-code-spelling-test/">Hour of Code 2013: Spelling Test</a></li>
<li><a href="https://blog.xojo.com/2013/12/19/hour-of-code-recap/">Hour of Code 2013: Recap</a></li>
<li><a href="https://youtu.be/Y3HYu_QN614">Hour of Code 2014: iOS Doodle</a></li>
<li><a href="https://blog.xojo.com/2014/12/19/hour-of-code-2014/">Hour of Code 2014 Recap</a></li>
<li><a href="https://blog.xojo.com/2015/12/07/hour-of-code-cat-pictures/">Hour of Code 2015: Cat Pictures</a></li>
<li><a href="https://blog.xojo.com/2017/12/05/hour-of-code-2017/">Hour of Code 2017: Asteroid Run</a></li>
</ul>
<p><strong>Update (Dec 5, 2018)</strong>:</p>
<p>Finished hour of code with 7th Grade students. They were very excited to learn a bit about coding and see some Xojo-made games.</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-5219" src="https://blog.xojo.com/wp-content/uploads/2018/11/Paul1.png" alt="" width="600" height="450" /></p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-5220" src="https://blog.xojo.com/wp-content/uploads/2018/11/Paul2.png" alt="" width="600" height="450" /></p>
<p>Also, Xojo Dojo is now available for Mac and Windows. Download either of these from the <a href="http://documentation.xojo.com/getting_started/creating_more_apps/raspberry_pi/xojo_dojo.html">main Xojo Dojo page</a>.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>#JustCode Challenge Week 11 &#8211; Xojo Dojo for Pi</title>
		<link>https://blog.xojo.com/2018/08/31/justcode-challenge-week-11-xojo-dojo-for-pi/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Fri, 31 Aug 2018 10:00:15 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[#JustCode]]></category>
		<category><![CDATA[GPIO]]></category>
		<category><![CDATA[RPi]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Xojo Dojo]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=4872</guid>

					<description><![CDATA[For #JustCode week 11, I've finished a project I've been working on for several months. This project is a simple app that you can use to write and run your own scripts using Xojo code on the Raspberry Pi. I call it Xojo Dojo.]]></description>
										<content:encoded><![CDATA[<p>For #JustCode week 11, I&#8217;ve finished a project I&#8217;ve been working on for several months. This project is a simple app that you can use to write and run your own scripts using Xojo code on the Raspberry Pi. I call it Xojo Dojo.</p>
<p><span id="more-4872"></span></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-4873" src="https://blog.xojo.com/wp-content/uploads/2018/08/2018-08-28_15-11-34.png" alt="" width="1195" height="758" /></p>
<p>With Xojo Dojo you get a simple code editor where you can write code using the Xojo programming language and a small set of additional commands for graphics, GPIO and some other things. It&#8217;s a great way to learn programming basics. Xojo Dojo includes several sample scripts to get you started.</p>
<p>For more information, check out the <a href="http://developer.xojo.com/xojo-dojo">Xojo Dojo doc page</a>.</p>
<p><a href="https://gitlab.com/xojo/XojoDojo">Download the source from GitLab</a>.</p>
<p>Add your #JustCode project to the <a href="https://forum.xojo.com/49692-just-code-challenge-week-11-projects">week 11 forum conversation</a>.</p>
<p>Download and check out earlier projects:</p>
<ul>
<li>Week 10: <a href="https://blog.xojo.com/2018/08/24/justcode-challenge-week-10-nettank/">NetTank</a></li>
<li>Week 9: <a href="https://blog.xojo.com/2018/08/17/justcode-challenge-week-9-quote-web-service/">Quote Web Service</a></li>
<li>Week 8: <a href="https://blog.xojo.com/2018/08/10/justcode-challenge-week-8-jumpstart-app-launcher/">JumpStart App Launcher</a></li>
<li>Week 7: <a href="https://blog.xojo.com/2018/08/03/justcode-challenge-week-7-pitch-tracker/">Pitch Tracker</a></li>
<li>Week 6: <a href="https://blog.xojo.com/2018/07/27/justcode-challenge-week-6-bubble-popper/">Bubble Popper</a></li>
<li>Week 5: <a href="https://blog.xojo.com/2018/07/20/justcode-challenge-week-5-math-quiz/">Math Quiz</a></li>
<li>Week 4: <a href="https://blog.xojo.com/2018/07/13/justcode-challenge-week-4-mini-golf-scorekeeper/">Mini-Golf ScoreKeeper</a></li>
<li>Week 3: <a href="https://blog.xojo.com/2018/07/06/just-code-challenge-week3/">Dogs Up!</a></li>
<li>Week 2: <a href="https://blog.xojo.com/2018/06/29/just-code-challenge-week2/">Password Generator</a></li>
<li>Week 1: <a href="https://blog.xojo.com/2018/06/22/just-code-challenge-week1/">Color Picker</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Raspberry Pi Library Requirement for 2018r1</title>
		<link>https://blog.xojo.com/2018/04/19/raspberry-pi-library-requirement-for-2018r1/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 19 Apr 2018 08:00:29 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[Raspbian]]></category>
		<category><![CDATA[RPi]]></category>
		<category><![CDATA[Single Board Computer]]></category>
		<category><![CDATA[Terminal]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=4144</guid>

					<description><![CDATA[Starting with Xojo 2018r1, your Xojo apps require the libunwind8 library to be installed on your Raspberry Pi.  Here's how to update your Pi.]]></description>
										<content:encoded><![CDATA[<p>Starting with Xojo 2018r1, your Xojo apps require the libunwind8 library to be installed on your Raspberry Pi. You can easily do that from Terminal on the Pi with this command:</p>
<pre>sudo apt-get install libunwind8</pre>
<p>The Raspberry Pi OS (Raspbian) does not automatically update itself. Since it is always a good idea to keep your Pi up to date, you can do it easily from Terminal using these commands:</p>
<pre>sudo apt-get update
sudo apt-get upgrade</pre>
<p>To learn more about Raspberry Pi and Xojo:</p>
<ul>
<li><a href="http://developer.xojo.com/raspberry-pi">Getting Started with Raspberry Pi</a></li>
<li><a href="http://developer.xojo.com/pibook">Programming the Raspberry Pi with Xojo</a> book</li>
</ul>
<p>And don&#8217;t forget, you can build Console and Desktop apps for Raspberry Pi with your <a href="https://blog.xojo.com/2018/03/14/have-you-pie-build-with-it-too/">free Xojo license</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Have Your Pi &#038; Build For It Too</title>
		<link>https://blog.xojo.com/2018/03/14/have-you-pie-build-with-it-too/</link>
		
		<dc:creator><![CDATA[Alyssa Foley]]></dc:creator>
		<pubDate>Wed, 14 Mar 2018 12:00:03 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[RPi]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<category><![CDATA[Xojo Resources]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=4007</guid>

					<description><![CDATA[In honor of Pi Day 2018, Xojo Pi licenses will be free! Xojo Pi licenses allow you to build console apps for Linux ARM for use with Raspberry Pi 2 and Raspberry Pi 3.]]></description>
										<content:encoded><![CDATA[<p>In honor of Pi Day 2018, we will be giving away Xojo Pi licenses for free!</p>
<p><strong>UPDATE:</strong> Now with Xojo 2019r1, you can develop and build console and desktop apps for the Raspberry Pi for free! <a href="https://www.xojo.com/download/">Download</a> today and get started! Xojo Pi supports Raspberry Pi 2, 3 &amp; 4.</p>
<p>Back at XDC 2015 when we announced Xojo would be adding support for the Raspberry Pi, we thought it was a fun extra for Xojo users. We were not expecting the overwhelming excitement and interest from the Xojo community and makers around the world! To celebrate Pi Day like the true geeks we are, we&#8217;re making <strong>Xojo Pi licenses free from Pi Day &amp; forever!</strong></p>
<p>Email hello@xojo.com for your free Xojo Pi license activation code.</p>
<p>Share the new with you friends, we&#8217;re on <a href="https://twitter.com/xojo">Twitter</a>, <a href="https://www.facebook.com/goxojo/">Facebook</a>, <a href="https://www.instagram.com/goxojo/">Instagram</a> and <a href="https://www.linkedin.com/company/xojo/">LinkedIn</a>.</p>
<p>UPDATED: 4/8/2019</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>New Raspbian Stretch and Xojo</title>
		<link>https://blog.xojo.com/2017/09/18/new-raspbian-stretch-and-xojo/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Mon, 18 Sep 2017 06:00:23 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[IoT]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=3362</guid>

					<description><![CDATA[The latest version of Raspbian, the operating system for the Raspberry Pi, was released in August. It's called Raspbian Stretch  and of course, Xojo apps work just fine on Raspbian Stretch.]]></description>
										<content:encoded><![CDATA[<p>The latest version of Raspbian, the operating system for the Raspberry Pi, was released in August. It&#8217;s called Raspbian Stretch and you can read more about it from the official launch blog post, <a href="https://www.raspberrypi.org/blog/raspbian-stretch/">Raspbian Stretch has arrived</a>.</p>
<p><span id="more-3362"></span>Of course, Xojo apps work just fine on Raspbian Stretch.</p>
<p>The blog post does have this caveat about the upgrade:</p>
<blockquote><p>Upgrading an existing Jessie image is possible, but is not guaranteed to work in every circumstance.</p></blockquote>
<p>This scared me a bit, so I decided I would rebuild my SD card with Stretch so I could have a clean install. Here is how you can set up a new SD card and tweak some settings to make it easier to access the Pi remotely:</p>
<ol>
<li>Download the Raspbian image from the official download page: <a href="https://www.raspberrypi.org/downloads/">Raspberry Pi Downloads</a></li>
<li>Download <a href="https://etcher.io">Etcher</a>, which is a tool that can set up the SD card with the image.</li>
<li>Shut down your Raspberry Pi and removed its SD card. <strong>Be sure to first copy off any data you want to retain as this process will wipe the card and any data on it.</strong></li>
<li>Plug the SD card into your computer. I used a USB micro SD card adapter for my Mac.</li>
<li>Run Etcher and select the Raspbian image you downloaded earlier.</li>
<li>Select the SD card in Etcher and click Flash. This wipes the card and installs Raspbian on it.</li>
<li>When it finishes, put the SD card back into the Raspberry Pi and power it up. You&#8217;ll also want to connect the Pi to a keyboard, mouse and display so you can do some initial configuration.</li>
<li>After the Pi boots and you are at the desktop, connect to your WiFi network.</li>
<li>Click the Pi icon in the menu and select Preferences-&gt;Raspberry Pi Configuration.</li>
<li>On the Interfaces tab, enable SSH and enable VNC.<img loading="lazy" decoding="async" class="size-full wp-image-3365 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2017/09/2017-09-07_16-44-39-1.png" alt="" width="495" height="422" /></li>
<li>You may also want to go to the Localisation tab and set the timezone.</li>
<li>Click OK.</li>
<li>Make a note of the Pi&#8217;s IP address if you do not know it. You can see the IP address by hovering the mouse over the WiFi icon in the menu.</li>
<li>Back on your computer, download <a href="https://www.realvnc.com/en/connect/download/viewer/">RealVNC Viewer</a>.</li>
<li>Install and run RealVNC Viewer.</li>
<li>Add a new connection and enter the IP address of your Raspberry Pi. You&#8217;ll be prompted for the username/password with is pi/raspberry unless you changed it.</li>
<li>You&#8217;ll now be remotely connected to the Pi and can use it without it being connected to a keyboard, mouse and display. This means you can also disconnect the keyboard, mouse and display if you want.</li>
<li>With this setup you can also use an FTP app to transfer files to the Pi. Just use the IP address and username/password for the Pi.</li>
<li>Lastly, <a href="http://developer.xojo.com/rpi-remote-debugging">refer to these steps to set up the Remote Debugger</a> on the Pi so you can easily run and test your Xojo apps directly on the Pi.</li>
</ol>
<p>To learn more about using the Raspberry Pi and Xojo together, refer to our free <a href="http://developer.xojo.com/pibook">Programming the Raspberry Pi with Xojo</a> book and the <a href="http://developer.xojo.com/raspberry-pi">Raspberry Pi section of the User Guide</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Goodbye GTK+ 2, Hello GTK+ 3</title>
		<link>https://blog.xojo.com/2017/08/15/goodbye-gtk-2-hello-gtk-3/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 15 Aug 2017 10:34:33 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[GTK+ 2]]></category>
		<category><![CDATA[GTK+ 3]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=3238</guid>

					<description><![CDATA[With the release of Xojo 2017 Release 2 we have updated our Linux Desktop framework to use GTK+ 3 instead of GTK+ 2.]]></description>
										<content:encoded><![CDATA[<p>With the release of Xojo 2017 Release 2 we have updated our Linux Desktop framework to use GTK+ 3 instead of GTK+ 2. For those not familiar with Linux, GTK+ is a User Interface (i.e. UI) toolkit, much like Cocoa is for macOS and Win32 controls (or WinForms.NET or WPF) is for Windows. GTK+ 2 has been supplying the user interface for Xojo Desktop apps for Linux since we first targeted Linux over a decade ago. It has since been deprecated in favor of GTK+ 3 for quite some time now and GTK+ 2 is typically not installed by default on most Linux distros these days, which makes deploying Xojo Desktop apps on Linux more painful. Unfortunately GTK+ 3 is not ABI compatible with GTK+ 2 so we could not migrate to using GTK+ 3 without completely ditching GTK+ 2.</p>
<p>Let&#8217;s take a closer look at what this means for your Linux apps:</p>
<p><span id="more-3238"></span></p>
<table cellpadding="5">
<tbody>
<tr>
<th>Target</th>
<th>2017r1.1 (and prior) requirements</th>
<th>2017r2 requirements</th>
</tr>
<tr>
<td>Linux console/web apps</td>
<td>Ubuntu 10.04, CentOS 6.0, etc.</td>
<td><b>No change</b></td>
</tr>
<tr>
<td>Linux (x86, x86-64) Desktop apps</td>
<td>Ubuntu 10.04, CentOS 6.0, etc.</p>
<ul>
<li>GTK+ 2.20</li>
<li>libwebkitgtk-1.0.0 (for HTMLViewer)</li>
</ul>
</td>
<td>Ubuntu 12.04, CentOS 7.0, etc.</p>
<ul>
<li>GTK+ 3.4.1</li>
<li>libwebkitgtk-3.0.0 (for HTMLViewer)</li>
</ul>
</td>
</tr>
<tr>
<td>Linux Pi (ARM) Desktop apps</td>
<td>Raspian Wheezy</p>
<ul>
<li>GTK+ 2.20</li>
</ul>
</td>
<td>Raspian Wheezy (<b>no change</b>)</p>
<ul>
<li>GTK+ 3.4.1</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p>Besides the benefit of not having to tell your end users to install GTK+ 2 on their particular Linux distro, here are some other notable items affected by the GTK+ 3 transition:</p>
<table cellpadding="5">
<tbody>
<tr>
<th>Feature</th>
<th>GTK+ 2</th>
<th>GTK+ 3</th>
</tr>
<tr>
<td>HiDPI</td>
<td>
<ul>
<li>No inherent scaling</li>
</ul>
</td>
<td>
<ul>
<li>Scales automatically on integral scale factors (i.e. 1x, 2x, 3x, etc.)</li>
</ul>
</td>
</tr>
<tr>
<td>Controls</td>
<td>
<ul>
<li>Child controls do not clip on a transparent parent control (like a Canvas)</li>
</ul>
</td>
<td>
<ul>
<li>Child controls properly clip on all parent controls</li>
<li>Default control sizes have generally increased, depending on theme/distro</li>
<li>Ability to style controls using CSS, for example:<br />
In ~/config/gtk-3.0/gtk.cssGtkButton {<br />
padding: 1px;<br />
}</li>
</ul>
</td>
</tr>
<tr>
<td>TextField</td>
<td>
<ul>
<li>Border can be removed</li>
</ul>
</td>
<td>
<ul>
<li>Depending on GTK+ 3 version the border cannot be removed (i.e. Ubuntu 12.04 yes, Ubuntu 15.10 no)</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p>While there&#8217;s a short list of actual differences, there have been numerous changes underneath made during this transition. For example, features that we had to custom code because GTK+ 2 did not offer them but GTK+ 3 did. Updating to GTK+ 3 is the final piece to our cross-platform HiDPI support for Desktop apps. Until the day comes when we have to say goodbye to GTK+ 3 (GTK+ 4 is already in the works), we welcome its inclusion in Xojo with a long overdue &#8220;Hello&#8221;!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Auto-Launch Raspberry Pi Apps</title>
		<link>https://blog.xojo.com/2017/05/15/auto-launch-raspberry-pi-apps/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Mon, 15 May 2017 07:25:14 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[XDC]]></category>
		<category><![CDATA[GPIO]]></category>
		<category><![CDATA[RPi]]></category>
		<category><![CDATA[Single Board Computer]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=2712</guid>

					<description><![CDATA[There are several ways that a Pi can automatically start an app. After doing a bit of Google research I decided on this approach. You can develop and build console and desktop apps for the Raspberry Pi using Xojo 2019r1 or later for free.]]></description>
										<content:encoded><![CDATA[<p>For XDC 2016 I needed a way to demonstrate a Raspberry Pi app that used the GPIO and updated an LCD character display. But I didn&#8217;t really have access to a screen that I could use to show the desktop so that I could run the app. And I could not remotely connect to the Pi because I did not have a good way to get it on the wifi network in the first place.</p>
<p><span id="more-2712"></span></p>
<p>I decided what would work for me is to have demo app automatically launch when the Pi boots. This would allow me to demo the app and project anywhere just by plugging in the Pi. There are several ways that a Pi can automatically start an app. After doing a bit of Google research I decided on this approach:</p>
<ol>
<li>Open the /etc/rc.local file (you&#8217;ll want to use sudo):
<pre>sudo nano /etc/rc.local</pre>
</li>
<li>Add lines to automatically start the app you want. My app was a console app that used GPIO, so I added these two lines:
<pre>export WIRINGPI_GPIOMEM=1
/home/pi/Documents/Xojo/LCDPanel &amp;</pre>
</li>
</ol>
<p>For reference, this is my rc.local file contents:</p>
<pre>#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
 printf "My IP address is %s\n" "$_IP"
fi

export WIRINGPI_GPIOMEM=1
/home/pi/Documents/Xojo/LCDPanel/LCDPanel &amp;

exit 0
</pre>
<p>You can develop and build console and desktop apps for the Raspberry Pi using Xojo 2019r1 or later for free.</p>
<p><a href="https://www.xojo.com/download/">Download Xojo</a> today and get started!</p>
<p>Fun times at XDC:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2718" src="https://blog.xojo.com/wp-content/uploads/2017/05/XDC2016Pi.jpg" alt="" width="3434" height="1884" /></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
