<?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>Graphics &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/graphics/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Mon, 10 Nov 2025 22:32:25 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Year of Code 2025: November Project – PDF Postcard Generator</title>
		<link>https://blog.xojo.com/2025/11/10/year-of-code-2025-november-project-pdf-postcard-generator/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Mon, 10 Nov 2025 22:32:24 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Year of Code]]></category>
		<category><![CDATA[#YearofCode]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[PDFDocument]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15499</guid>

					<description><![CDATA[For November&#8217;s Xojo Year of Code 2025, I’ve created a fun and practical project: a PDF Postcard Generator. This desktop application allows you to easily&#8230;]]></description>
										<content:encoded><![CDATA[
<p>For November&#8217;s Xojo Year of Code 2025, I’ve created a fun and practical project: a PDF Postcard Generator. This desktop application allows you to easily design personalized holiday postcards by combining a chosen image with a custom message, then exporting it as a ready-to-share PDF. It&#8217;s a fantastic way to see Xojo’s capabilities in handling graphics, file operations, and PDF creation, all within a simple, intuitive interface.</p>



<h2 class="wp-block-heading">What this project includes</h2>



<ul class="wp-block-list">
<li>A&nbsp;<code>DesktopWindow</code>&nbsp;(<code>wMain</code>) that provides a clean user interface for selecting an image, inputting your message, and generating the final PDF postcard.</li>



<li>Intelligent image handling that supports common formats like JPG, PNG, and GIF. The application automatically crops your selected image to a perfect 4:6 aspect ratio, ensuring it fits the postcard layout beautifully.</li>



<li>Robust PDF generation, leveraging Xojo&#8217;s&nbsp;<code>PDFDocument</code>&nbsp;and&nbsp;<code>Graphics</code>&nbsp;classes to embed images and render styled text effectively onto the document.</li>



<li>Customizable message rendering, which includes a subtle drop shadow effect for improved readability and a polished look against your background image.</li>



<li>Automated saving of the generated PDF postcard to your desktop, complete with a unique, timestamped filename, and immediate opening of the file in your system&#8217;s default viewer for quick review.</li>
</ul>



<h2 class="wp-block-heading">Download</h2>



<p>You can download the entire Xojo project from <a href="https://github.com/xolabsro/Holiday-Postcard-Generator" target="_blank" rel="noreferrer noopener">GitHub</a>.</p>



<p>This project illustrates Xojo&#8217;s robust capabilities for handling graphics and generating PDFs, demonstrating how straightforward it is to create functional and creative desktop applications. We encourage you to use this postcard generator as a springboard for your own ideas. Perhaps you could expand it by adding features like custom fonts, multiple message fields, or even integration with a data source for personalized bulk postcards. Or, consider how Xojo&#8217;s PDF features could power entirely new applications for reporting, invoicing, or custom document creation. We&#8217;d love to see what you build!</p>



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



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

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

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

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

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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



<p>Monthly winners get $100 at the Xojo store. Every month you submit a project is another chance to win the grand prize. The grand prize is $250 cash plus a Xojo Pro license and a year of GraffitiSuite and will be announce in December. Learn more about the <a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/#prizes">prizes</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Implementing a Non-Blocking Image Processor with Xojo Threads</title>
		<link>https://blog.xojo.com/2025/08/28/implementing-a-non-blocking-image-processor-with-xojo-threads/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Thu, 28 Aug 2025 14:56:33 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Dictionary]]></category>
		<category><![CDATA[FolderItem]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Picture]]></category>
		<category><![CDATA[Threads]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15302</guid>

					<description><![CDATA[Have you ever written an app that needs to do some heavy lifting, like processing a big batch of files? Maybe you click a button,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Have you ever written an app that needs to do some heavy lifting, like processing a big batch of files? Maybe you click a button, and suddenly your entire app just … stops. The cursor turns into a spinning wheel, the windows won’t respond, and your users are left wondering if it crashed. It’s a frustrating experience, but don’t worry, there’s a solution:&nbsp;<a href="https://documentation.xojo.com/api/language/threading/thread.html" target="_blank" rel="noreferrer noopener">Threads</a>!</p>



<p>Let&#8217;s build a simple but incredibly powerful Desktop app: a threaded image resizer. This tool will let you pick a folder of images and resize them all without ever locking up the app. It’s a perfect showcase of how easy and effective <a href="https://documentation.xojo.com/topics/threading/index.html" data-type="link" data-id="https://documentation.xojo.com/topics/threading/index.html" target="_blank" rel="noreferrer noopener">threading</a> can be in Xojo.</p>



<p>Let’s get started!</p>



<h4 class="wp-block-heading" id="step-1-designing-the-user-interface">Step 1: Designing the User Interface</h4>



<p>First things first, let’s lay out our app’s window. We’re going for a clean and simple design. All you need to do is create a new Xojo Desktop project and add the following controls from the Library onto your main window:</p>



<ol class="wp-block-list">
<li><strong>DesktopButton</strong>: This will be our “start” button. The user will click this to select a folder and begin the resizing process. Let’s set its&nbsp;<code>Caption</code>&nbsp;to “Select folder &amp;&amp; Start”.</li>



<li><strong>DesktopProgressBar</strong>: This will give the user visual feedback on the progress of the resizing operation.</li>



<li><strong>DesktopLabel</strong>: We’ll use this label to display status updates, like which file is currently being processed or when the job is complete. Let’s call it&nbsp;<code>StatusLabel</code>.</li>
</ol>



<p>Your app layout should look something like this:</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="692" src="https://blog.xojo.com/wp-content/uploads/2025/08/thread_image_resizer_1-1024x692.jpg" alt="" class="wp-image-15303" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/thread_image_resizer_1-1024x692.jpg 1024w, https://blog.xojo.com/wp-content/uploads/2025/08/thread_image_resizer_1-300x203.jpg 300w, https://blog.xojo.com/wp-content/uploads/2025/08/thread_image_resizer_1-768x519.jpg 768w, https://blog.xojo.com/wp-content/uploads/2025/08/thread_image_resizer_1.jpg 1525w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading" id="step-2-adding-the-magic-ingredient-the-thread">Step 2: Adding the Magic Ingredient: The Thread</h4>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-ad2f72ca wp-block-group-is-layout-flex">
<p>Now for the star of the show! Go to the Library and find the&nbsp;<code>Thread</code>&nbsp;object. Drag and drop one onto your window. By default, it might be named&nbsp;<code>Thread1</code>, but I’ve renamed mine to&nbsp;<code>ResizeThread</code>&nbsp;to make its purpose crystal clear. This object is where our background work will happen.</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="298" height="287" src="https://blog.xojo.com/wp-content/uploads/2025/08/thread_image_resizer_2.jpg" alt="" class="wp-image-15304" style="width:500px"/></figure>
</div>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Quick note on thread types: Cooperative threads (the default) share a single CPU core with the main/UI thread and other cooperative threads. Preemptive threads can run on separate CPU cores and deliver true parallelism for CPU-bound work. More info on this subject: <a href="https://blog.xojo.com/2024/10/01/cooperative-to-preemptive-weaving-new-threads-into-your-apps/" target="_blank" rel="noreferrer noopener">Cooperative to Preemptive: Weaving New Threads into your Apps</a></p>
</blockquote>



<p>Why this project uses Preemptive threads: resizing many images is CPU-bound and benefits from parallel cores without blocking the UI.</p>



<h4 class="wp-block-heading" id="step-3-kicking-off-the-process">Step 3: Kicking Off the Process</h4>



<p>With the UI and thread in place, let’s add the code to get things moving. Double-click the “Select folder &amp; Start” button to add its&nbsp;<code>Pressed</code>&nbsp;event. This is what will run when the user clicks it.</p>



<p>Here’s the code for the&nbsp;<code>Pressed</code>&nbsp;event:</p>



<pre class="wp-block-code"><code>' Ask the user for a source folder (contains images)
Var f As FolderItem = FolderItem.ShowSelectFolderDialog
If f = Nil Then Return ' user cancelled

mSourceFolder = f

' Reset UI
ProgressBar1.Value = 0
StatusLabel.Text = "Starting…"

' Kick off background work!
ResizeThread.Start</code></pre>



<p>Let’s break this down. First, we ask the user to select a folder. If they don’t pick one, we simply exit. If they do, we store the selected folder in a window property called&nbsp;<code>mSourceFolder</code>&nbsp;(<code>Public Property mSourceFolder As FolderItem</code>). We then reset our progress bar and status label and, most importantly, we call&nbsp;<code>ResizeThread.Start</code>. That one simple line tells our thread to wake up and get to work by running its&nbsp;<code>Run</code>&nbsp;event.</p>



<h4 class="wp-block-heading" id="step-4-the-heavy-lifting-in-the-background">Step 4: The Heavy Lifting (in the Background)</h4>



<p>The&nbsp;<code>Run</code>&nbsp;event of the&nbsp;<code>ResizeThread</code>&nbsp;is where the core logic lives. This is where we’ll find, load, resize, and save the images. Remember, the golden rule of threads is:&nbsp;never touch the UI directly from the Run event. Doing so can cause crashes and unpredictable behavior.</p>



<p>Instead, we perform our task and then&nbsp;<em>send a message</em>&nbsp;back to the main thread with an update. We do this using a method called&nbsp;<code>AddUserInterfaceUpdate</code>.</p>



<p>Here’s the&nbsp;<code>Run</code>&nbsp;event code:</p>



<pre class="wp-block-code"><code>' Quick validation up-front
If mSourceFolder = Nil Or Not mSourceFolder.Exists Or Not mSourceFolder.IsFolder Then
  Me.AddUserInterfaceUpdate(New Dictionary("progress":0, "msg":"No folder selected"))
  Return
End If

Try
  ' Ensure output subfolder "&lt;selected&gt;/resized" exists
  Var outFolder As FolderItem = mSourceFolder.Child("resized")
  If Not outFolder.Exists Then outFolder.CreateFolder
  
  ' Build a list of candidate image files.
  ' Note: Using Picture.Open to validate images is simple and robust.
  '       (For very large folders, you could pre-filter by extension first.)
  Var images() As FolderItem
  For Each it As FolderItem In mSourceFolder.Children
    If it = Nil Or it.IsFolder Then Continue ' Ignore subfolders
    Try
      Var p As Picture = Picture.Open(it)
      If p &lt;&gt; Nil Then images.Add(it)
    Catch e As RuntimeException
      ' Non-image or unreadable; skip
    End Try
  Next
  
  Var total As Integer = images.Count
  If total = 0 Then
    Me.AddUserInterfaceUpdate(New Dictionary("progress":0, "msg":"No images found"))
    Return
  End If
  
  ' Resize settings (simple “fit within 800x800” bounding box)
  Const kMaxW As Double = 800.0
  Const kMaxH As Double = 800.0
  
  ' Short delay after each file so the main thread can repaint the UI
  Const kDelayMS As Integer = 50
  
  For i As Integer = 0 To total - 1
    Var src As FolderItem = images(i)
    Try
      ' Load source (immutable)
      Var pic As Picture = Picture.Open(src)
      If pic = Nil Or pic.Width &lt;= 0 Or pic.Height &lt;= 0 Then Continue
      
      ' Compute proportional scale (never upscale)
      Var sW As Double = kMaxW / pic.Width
      Var sH As Double = kMaxH / pic.Height
      Var scale As Double = Min(Min(sW, sH), 1.0)
      
      Var newW As Integer = Max(1, pic.Width * scale)
      Var newH As Integer = Max(1, pic.Height * scale)
      
      ' Render into a new mutable bitmap of the target size
      Var outPic As New Picture(newW, newH)
      outPic.Graphics.DrawPicture(pic, 0, 0, newW, newH, 0, 0, pic.Width, pic.Height)
      
      ' Build a safe base name (strip the last extension; handle dotfiles)
      Var name As String = src.Name
      Var ext As String = name.LastField(".")
      Var baseName As String
      If ext = name Then
        ' No dot in the name
        baseName = name
      Else
        baseName = name.Left(name.Length - ext.Length - 1)
      End If
      If baseName.Trim = "" Then baseName = "image"
      
      ' Save JPEG (fallback PNG if JPEG export not supported)
      Var outFile As FolderItem = outFolder.Child(baseName + "_resized.jpg")
      If Picture.IsExportFormatSupported(Picture.Formats.JPEG) Then
        outPic.Save(outFile, Picture.Formats.JPEG, Picture.QualityHigh) ' adjust the quality of the jpeg here
      Else
        outPic.Save(outFolder.Child(baseName + "_resized.png"), Picture.Formats.PNG)
      End If
      
    Catch io As IOException
      ' Likely a write/permission/disk issue; skip this file
    Catch u As UnsupportedOperationException
      ' Unsupported format/operation on this platform; skip
    End Try
    
    ' Progress + message to the UI (safe handoff)
    Var pct As Integer = ((i + 1) * 100) / total
    Me.AddUserInterfaceUpdate(New Dictionary("progress":pct, _
    "msg":"Resized " + src.Name + " (" + pct.ToString + "%)"))
    
    ' Let the main thread paint the update
    Me.Sleep(kDelayMS, True) ' wakeEarly=True allows early resume when idle
  Next
  
  ' Final UI message
  Me.AddUserInterfaceUpdate(New Dictionary("progress":100, "msg":"Done"))
  
Catch e As RuntimeException
  ' Any unexpected failure: report a friendly error
  Me.AddUserInterfaceUpdate(New Dictionary("progress":0, "msg":"Error: " + e.Message))
End Try</code></pre>



<h4 class="wp-block-heading" id="step-5-receiving-updates-and-safely-changing-the-ui">Step 5: Receiving Updates and Safely Changing the UI</h4>



<p>So, how does the main thread “hear” these updates? Through the&nbsp;<code>UserInterfaceUpdate</code>&nbsp;event on the&nbsp;<code>ResizeThread</code>&nbsp;itself! This event fires on the main thread, making it the one and only safe place to update our controls.</p>



<p>Here’s the code for the&nbsp;<code>UserInterfaceUpdate</code>&nbsp;event:</p>



<pre class="wp-block-code"><code>' This event runs on the main thread – SAFE to update controls here.
If data.Count = 0 Then Return

Var latest As Dictionary = data(data.LastIndex)

If latest.HasKey("progress") Then ProgressBar1.Value = latest.Value("progress")
If latest.HasKey("msg") Then StatusLabel.Text = latest.Value("msg")

' A little bonus: when we are done, open the output folder!
If latest.HasKey("msg") And latest.Value("msg") = "Done" Then
  Var outFolder As FolderItem = mSourceFolder.Child("resized")
  If outFolder &lt;&gt; Nil And outFolder.Exists Then
    outFolder.Open
  End If
End If</code></pre>



<p>In this event, we receive an array of Dictionaries (all the updates that have queued up). We usually only care about the very latest one, so we grab&nbsp;<code>data(data.LastIndex)</code>. Then, we safely access the values from the dictionary and assign them to&nbsp;<code>ProgressBar1.Value</code>&nbsp;and&nbsp;<code>StatusLabel.Text</code>. That’s it!</p>



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



<p>And there you have it! A fully functional, non-blocking image resizer. By moving the heavy work to a&nbsp;<code>Thread</code>, we’ve created an application that provides a smooth, professional user experience.</p>



<p>The pattern is simple:</p>



<ol class="wp-block-list">
<li><strong>Start</strong>&nbsp;the task from the main thread (<code>ResizeThread.Start</code>).</li>



<li><strong>Work</strong>&nbsp;inside the thread’s&nbsp;<code>Run</code>&nbsp;event.</li>



<li><strong>Communicate</strong>&nbsp;back to the UI with&nbsp;<code>AddUserInterfaceUpdate</code>.</li>



<li><strong>Update</strong>&nbsp;the UI safely in the&nbsp;<code>UserInterfaceUpdate</code>&nbsp;event.</li>
</ol>



<p>That’s pretty much it! Go ahead, <a href="https://github.com/xolabsro/Thread-Image-Resizer" data-type="link" data-id="https://github.com/xolabsro/Thread-Image-Resizer" target="_blank" rel="noreferrer noopener">download this project’s source code</a> from GitHub, play around with it, and think about how you can use threads in your own applications!</p>



<p>Happy coding!</p>



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



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

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

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

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

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Writing Drawing Code for Android, Desktop, iOS and Web</title>
		<link>https://blog.xojo.com/2025/04/21/writing-drawing-code-for-android-desktop-ios-and-web/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Mon, 21 Apr 2025 19:28:10 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Variants]]></category>
		<category><![CDATA[WebGraphics]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14826</guid>

					<description><![CDATA[When writing code it&#8217;s always a good idea to be thinking about the future. Today you are creating a desktop project but tomorrow you might&#8230;]]></description>
										<content:encoded><![CDATA[
<p>When writing code it&#8217;s always a good idea to be thinking about the future. Today you are creating a desktop project but tomorrow you might need to create an Android or iOS project. That code you&#8217;re writing might be code you could use for another project for another platform. </p>



<p>For the most part, writing drawing code will <em>just work</em> because you use Xojo&#8217;s <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics" target="_blank" rel="noreferrer noopener">Graphics</a> class for Android, Desktop and iOS projects. Web projects, however, don&#8217;t use the Graphics class. The <a href="https://documentation.xojo.com/api/user_interface/web/webcanvas.html#description" target="_blank" rel="noreferrer noopener">WebCanvas</a> control&#8217;s <a href="https://documentation.xojo.com/api/user_interface/web/webcanvas.html#webcanvas-paint" target="_blank" rel="noreferrer noopener">Paint</a> event is passed a <a href="https://documentation.xojo.com/api/graphics/webgraphics.html" target="_blank" rel="noreferrer noopener">WebGraphics</a> object. While the Graphics and WebGraphics classes have a lot in common, sharing many of the same methods with the same parameters, they are two distinctly different classes from the perspective of the Xojo compiler. That means that while the code you write will look almost identical, you still have to use a Graphics object for Android, Desktop and iOS projects and a WebGraphics object for Web projects. </p>



<p>Your instinct might be to simply write the code for one and then copy it to the other projects, changing Graphics to WebGraphics for Web projects. This will of course work, but then you have to remember to do this copy/paste/change operation every time you update your code. That&#8217;s not ideal.</p>



<h2 class="wp-block-heading">Graphics vs. WebGraphics</h2>



<p>With Xojo, the code can be written in such a way as to automatically handle the difference between Graphics/WebGraphics. Most often your graphics methods will be called from something that provides a Graphics or WebGraphics object for you to draw into such as a Canvas control&#8217;s Paint event. From there your code will call your methods that do the drawing. The problem is that your methods can&#8217;t use a Graphics or a WebGraphics type as a parameter because Graphics is not going to work for your Web projects and WebGraphics doesn&#8217;t exist in any framework except the Web framework. Thus using it anywhere else will result in a compiler error.</p>



<h3 class="wp-block-heading">Using a Variant</h3>



<p>Getting around this limitation is, fortunately, quite easy. Instead of using Graphics or WebGraphics as a parameter type, you use <a href="https://documentation.xojo.com/api/data_types/variant.html" target="_blank" rel="noreferrer noopener">Variant</a>. A Variant can hold any type of data from Strings to Integers, to Graphics to WebGraphics and more.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="560" height="466" src="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-14.46.40@2x.png" alt="" class="wp-image-14827" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-14.46.40@2x.png 560w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-14.46.40@2x-300x250.png 300w" sizes="(max-width: 560px) 100vw, 560px" /></figure>



<p>Once your drawing method gets the Variant though, it can&#8217;t use it to draw. It can only use a Graphics or WebGraphics objects. The trick is to then copy it into a Graphics or WebGraphics class variable:</p>



<pre class="wp-block-code"><code><code>Var g As Graphics = context</code></code></pre>



<p>or</p>



<pre class="wp-block-code"><code><code>Var g As WebGraphics = context</code></code></pre>



<p>The problem you now face, as mentioned earlier, is that WebGraphics only exists in Web projects. That means you have to write your code in such a way that you will declare the variable g as a Graphics object in Android, Desktop and iOS projects and as a WebGraphics object in Web projects. This can be achieved via conditional compilation. This is a simple technique that tells the Xojo compiler to only compile code into your app if conditions you specify are met. In this case, if you&#8217;re targeting Desktop or Mobile, it should compile in the line that uses the Graphics type, and if you are targeting a Web app, the line that uses WebGraphics. To conditionally compile, you just need to add that conditional code around these two lines:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="wp-block-code"><code>#If TargetDesktop Or TargetMobile Then
   Var g As Graphics = context
#EndIf

#If TargetWeb Then
   Var g As WebGraphics = context
#EndIf</code></pre>
</div></div>
</div></div>



<p>Since a project must be only one of the above types, when you run or build your project, the appropriate line of code will be compiled in. From there, you now have a variable (g) of the right type can use this to draw whatever you like. For example, there are four identical example projects (one for each project type) that show off this technique. They can be found in the Xojo IDE by choosing File > New Project, clicking on Examples, choosing the Graphics folder in the list and then the Cross-Platform Drawing folder. The examples all draw a checkerboard that looks like this:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="912" height="916" src="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x.png" alt="" class="wp-image-14828" style="width:315px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x.png 912w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x-300x300.png 300w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x-150x150.png 150w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x-768x771.png 768w" sizes="auto, (max-width: 912px) 100vw, 912px" /></figure>
</div>


<p>They all contain the an identical Checkerboard class that handles the drawing. This class has DrawBorder and DrawCheckers methods that both take a Variant as a parameter. In each project is a Canvas control whose Paint event calls these methods:</p>



<pre class="wp-block-code"><code>Var cb As New Checkerboard
cb.DrawBoard(g)
cb.DrawCheckers(g)</code></pre>



<p>The full DrawBoard method looks like this:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="wp-block-code"><code>#If TargetDesktop Or TargetMobile Then
  Var g As Graphics = context
#EndIf

#If TargetWeb Then
  Var g As WebGraphics = context
#EndIf 

Var boxSize As Integer = Min(g.Width/8, g.Height/8) 'The size of the box
'Draw the rows
For y As Integer = 0 To 7
  For x As Integer = 0 To 7
    'Switch colors for each box in the row
    If g.DrawingColor = Color.Black Then
      g.DrawingColor = Color.White
    Else
      g.DrawingColor = Color.Black
    End If
    'Draw a box
    g.FillRectangle(x * boxSize, y * boxSize, boxSize, boxSize)
  Next
  'Switch colors again for the beginning of the next row
  If g.DrawingColor = Color.Black Then
    g.DrawingColor = Color.White
  Else
    g.DrawingColor = Color.Black
  End If
Next</code></pre>
</div></div>



<p>In the example projects, check out the DrawCheckers method as well. It uses the same technique. What is great about this is that this class can be copied into any Android, Desktop, iOS or Web project and it will indeed <em>just work</em>.</p>



<h3 class="wp-block-heading">Checking Out the Examples</h3>



<p>There are four example projects (one for each project type &#8211; Android, Desktop, iOS and Web) that demonstrate the technique explained here. You can find them in the Xojo IDE by choosing File > New Project, clicking on Examples, choosing the Graphics folder in the list and then the Cross-Platform Drawing folder.</p>



<p><em>Geoff Perlman is the Founder and CEO of Xojo. When he’s not leading the Xojo team he can be found playing drums in Austin, Texas and spending time with his family.</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>Beyond Static UI: Create Dynamic Loading Animations with Xojo Graphics</title>
		<link>https://blog.xojo.com/2024/11/05/beyond-static-ui-create-dynamic-loading-animations-with-xojo-graphics/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Tue, 05 Nov 2024 15:10:24 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Custom Controls]]></category>
		<category><![CDATA[DesktopCanvas]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Phase-Animation]]></category>
		<category><![CDATA[UI-Design]]></category>
		<category><![CDATA[Visual Feedback]]></category>
		<category><![CDATA[Xojo-Graphics]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13975</guid>

					<description><![CDATA[Ever wondered how to create those sleek, professional-looking loading animations you see in modern apps? In this blog post, we&#8217;re going to unlock the power&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Ever wondered how to create those sleek, professional-looking loading animations you see in modern apps?</p>



<p>In this blog post, we&#8217;re going to unlock the power of Xojo&#8217;s DesktopCanvas and its Graphics capabilities to recreate one of the popular <a href="https://tobiasahlin.com/spinkit/">SpinKit loading animations originally created by Tobias Ahlin</a>. We&#8217;ll be implementing the &#8220;Three Bounce&#8221; animation, transforming this beloved CSS animation into native Xojo code!</p>



<p>Not only will you learn how to create this specific animation, but you&#8217;ll also gain valuable insights into animation principles in Xojo that you can use to create your own custom animations. By the end of this tutorial, you&#8217;ll understand how to:</p>



<ul class="wp-block-list">
<li>Harness the power of DesktopCanvas for custom graphics</li>



<li>Create smooth animations using Timers</li>



<li>Implement phase-based animations</li>



<li>Use Graphics methods to draw dynamic shapes</li>



<li>Manage animation lifecycles properly</li>
</ul>



<h3 class="wp-block-heading">Why This Matters</h3>



<p>Loading animations are more than just eye candy – they&#8217;re essential UI elements that keep users engaged while your app processes data. Instead of using static images or third-party libraries, creating your own animations gives you complete control over the look and feel of your application while keeping your dependencies minimal.</p>



<h3 class="wp-block-heading">What We&#8217;re Building</h3>



<p>We&#8217;ll create a smooth, professional-looking three-dot loading animation where dots gracefully scale up and down in sequence. The result is a lightweight, customizable loading indicator that you can drop into any Xojo project. Here&#8217;s what makes this implementation special:</p>



<ul class="wp-block-list">
<li>Pure Xojo code &#8211; no external dependencies</li>



<li>Smooth, fluid animation</li>



<li>Easily customizable colors and timing</li>



<li>Efficient resource usage</li>



<li>Clean, object-oriented design</li>
</ul>



<figure class="wp-block-video"><video height="184" style="aspect-ratio: 360 / 184;" width="360" controls loop preload="auto" src="https://blog.xojo.com/wp-content/uploads/2024/10/spinkit_animation.mp4" playsinline></video></figure>



<p>Ok, let&#8217;s start building our awesome animation class.</p>



<h2 class="wp-block-heading">Step 1: Setting Up the Base Class</h2>



<p>First, create a new class (Insert &gt; Class) that inherits from DesktopCanvas:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://storage.googleapis.com/co-writer/images/HRIwK4xjWLXvNRyAbzXbq5t8wJF3/-1730379923862.webp" alt="IMAGE"/></figure>
</div>


<pre class="wp-block-code"><code>Protected Class SpinKitClass Inherits DesktopCanvas</code></pre>



<h2 class="wp-block-heading">Step 2: Defining Core Properties</h2>



<p>Add these essential properties to control the animation:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://storage.googleapis.com/co-writer/images/HRIwK4xjWLXvNRyAbzXbq5t8wJF3/-1730380034310.webp" alt="IMAGE"/></figure>
</div>


<pre class="wp-block-code"><code>Private animationPhases() As Double      // Stores phase offsets for each dot
Private animationSpeed As Integer = 60   // Animation refresh rate in milliseconds
Private animationTimer As Timer         // Timer to drive the animation
Private currentPhase As Double = 0.0    // Current animation phase
Private dotSize As Integer = 20         // Size of each dot
Private dotSpacing As Integer = 20      // Space between dots</code></pre>



<h2 class="wp-block-heading">Step 3: Setting Up Constants</h2>



<p>Define the constants that control the animation behavior:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://storage.googleapis.com/co-writer/images/HRIwK4xjWLXvNRyAbzXbq5t8wJF3/-1730380079168.webp" alt="IMAGE"/></figure>
</div>


<pre class="wp-block-code"><code>Private Const kDefaultColor As Color = &amp;c333333    // Dot color
Private Const kPhaseIncrement As Double = 0.05    // Animation speed</code></pre>



<h2 class="wp-block-heading">Step 4: Implementing Animation Control Methods</h2>



<p>Add methods to start and stop the animation:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<pre class="wp-block-code"><code>Public Sub StartAnimation()
  /// Initializes and starts the animation
  /// Sets up initial phase offsets for the dots
  /// Creates and configures the animation timer
  
  If animationTimer = Nil Then
    animationPhases = Array(0.0, 0.16, 0.32)
    
    animationTimer = New Timer
    AddHandler animationTimer.Action, AddressOf UpdateAnimation
    animationTimer.Period = animationSpeed
    animationTimer.RunMode = Timer.RunModes.Multiple
  End If
End Sub</code></pre>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<pre class="wp-block-code"><code>Public Sub StopAnimation()
  /// Stops the running animation
  /// Removes the timer handler and cleans up
  /// Refreshes the canvas to clear the animation
  
  If animationTimer &lt;&gt; Nil Then
    RemoveHandler animationTimer.Action, AddressOf UpdateAnimation
    animationTimer = Nil
    Refresh
  End If
End Sub</code></pre>
</div>
</div>



<h2 class="wp-block-heading">Step 5: Creating the Animation Update Logic</h2>



<p>Implement the timer callback that drives the animation:</p>



<pre class="wp-block-code"><code>Private Sub updateAnimation(sender As Timer)
  /// Timer callback that updates the animation state
  /// Increments the phase and triggers a redraw
  /// @param sender The Timer that triggered this callback
  
  #Pragma Unused sender
  
  // Increment the current phase (spin08)
  currentPhase = currentPhase + kPhaseIncrement
  // Reset currentPhase if it exceeds 1.0
  If currentPhase &gt; 1.0 Then currentPhase = 0
  
  // Invalidate the canvas to trigger a repaint
  Refresh()
End Sub</code></pre>



<h2 class="wp-block-heading">Step 6: Implementing the Drawing Logic</h2>



<p>Add the core animation rendering code:</p>



<pre class="wp-block-code"><code>Private Sub animation08(g As Graphics)
  /// Renders a single frame of the three-dot loading animation
  /// Draws 3 dots that scale up and down in sequence
  /// @param g The graphics context to draw into
  
  Var centerX As Integer = Me.Width / 2
  Var centerY As Integer = Me.Height / 2
  
  For i As Integer = 0 To 2
    Var phase As Double = currentPhase + animationPhases(i)
    
    // Ensure phase is within 0 to 1
    If phase &gt; 1.0 Then phase = phase - 1.0
    
    Var scale As Double
    If phase &lt; 0.4 Then
      scale = phase / 0.4
    Else
      scale = (1.0 - phase) / 0.6
    End If
    
    Var size As Integer = dotSize * scale
    Var x As Integer = centerX + (i - 1) * dotSpacing - size / 2
    Var y As Integer = centerY - size / 2
    
    g.DrawingColor = kDefaultColor
    g.FillOval(x, y, size, size)
  Next
End Sub</code></pre>



<h2 class="wp-block-heading">Step 7: Handling the Paint Event</h2>



<p>Implement the Paint event to trigger the animation rendering:</p>



<pre class="wp-block-code"><code>Sub Paint(g As Graphics, areas() As Rect) Handles Paint
  /// Paint event handler that renders the animation
  /// Called automatically when the canvas needs to be redrawn
  /// If animation is running, calls animation08, otherwise clears the canvas
  
  If animationTimer &lt;&gt; Nil Then
    animation08(g)
  Else
    g.ClearRectangle(0, 0, Width, Height)
  End If
End Sub
</code></pre>



<h2 class="wp-block-heading">How It Works</h2>



<ol class="wp-block-list">
<li>The animation uses a phase-based system where each dot is offset in its animation cycle.</li>



<li>The dots scale up and down based on their current phase.</li>



<li>A timer drives the animation by incrementing the phase and triggering redraws.</li>



<li>The dots are positioned horizontally with equal spacing around the center.</li>



<li>Each dot&#8217;s size is calculated based on its current phase in the animation.</li>
</ol>



<h2 class="wp-block-heading">Using the Animation</h2>



<p>To use this animation in your project, all you have to do is simply drag and drop the class on a DesktopWindow and then start or stop the animation when needed.</p>



<pre class="wp-block-code"><code>// Start the animation
SpinKit1.StartAnimation()

// Stop the animation when done
SpinKit1.StopAnimation()</code></pre>



<h2 class="wp-block-heading">Customization</h2>



<p>You can customize the animation by adjusting:</p>



<ul class="wp-block-list">
<li><code>dotSize</code> for larger or smaller dots</li>



<li><code>dotSpacing</code> to change the spread of the dots</li>



<li><code>animationSpeed</code> to make it faster or slower</li>



<li><code>kDefaultColor</code> to change the dot color</li>



<li><code>kPhaseIncrement</code> to adjust the animation speed</li>
</ul>



<h2 class="wp-block-heading">Taking It Further</h2>



<p>The &#8220;Three Bounce&#8221; animation we&#8217;ve created is just one of many amazing animations in the <a href="https://tobiasahlin.com/spinkit/">SpinKit collection</a>. Now that you understand the fundamentals, why not try recreating other SpinKit animations? Here are some exciting challenges to tackle:</p>



<ul class="wp-block-list">
<li>Modify the current animation to use different shapes (squares, rectangles).</li>



<li>Experiment with different timing functions for varied animation effects.</li>



<li>Try implementing the &#8220;Rotating Plane&#8221; or &#8220;Chasing Dots&#8221; animations from SpinKit.</li>



<li>Create your own unique variations by combining what you&#8217;ve learned.</li>



<li>Optimize the class further.</li>
</ul>



<h2 class="wp-block-heading">Share Your Creations!</h2>



<p>Have you created an awesome variation or implemented another SpinKit animation in Xojo? Share it with the community! The <a target="_blank" rel="noreferrer noopener" href="https://forum.xojo.com/">Xojo Forums</a> and social media are great places to showcase your work and inspire others.</p>



<h2 class="wp-block-heading">Resources for Further Exploration</h2>



<ul class="wp-block-list">
<li>Original SpinKit animations by Tobias Ahlin: <a href="https://tobiasahlin.com/spinkit/" target="_blank" rel="noreferrer noopener">https://tobiasahlin.com/spinkit/</a></li>



<li>Xojo Graphics documentation: <a href="https://documentation.xojo.com/api/graphics/graphics.html" target="_blank" rel="noreferrer noopener">https://documentation.xojo.com/api/graphics/graphics.html</a></li>



<li>Xojo DesktopCanvas documentation: <a href="https://documentation.xojo.com/api/user_interface/desktop/desktopcanvas.html" target="_blank" rel="noreferrer noopener">https://documentation.xojo.com/api/user_interface/desktop/desktopcanvas.html</a></li>
</ul>



<p><strong>Remember</strong>: Every great application deserves great animations and now you have the tools to create them! Keep experimenting, keep creating, and most importantly, keep animating!</p>



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



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

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

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

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

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

			</item>
		<item>
		<title>Enhanced Emoji Support: A Look into Graphics and String.Character Improvements</title>
		<link>https://blog.xojo.com/2024/06/26/enhanced-emoji-support-a-look-into-graphics-and-string-character-improvements/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Wed, 26 Jun 2024 15:00:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[20242r2]]></category>
		<category><![CDATA[Emoji]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[String]]></category>
		<category><![CDATA[Unicode]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13136</guid>

					<description><![CDATA[Now in Xojo 2024r2, we've enhanced emojis with vivid colors!]]></description>
										<content:encoded><![CDATA[
<p>In the past, people used a two-character symbol : ) to add a smiley to their messages. Nowadays, we have full-color emojis for that purpose, so it&#8217;s time for Xojo to catch up unless we want to be seen as old <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f995.png" alt="🦕" class="wp-smiley" style="height: 1em; max-height: 1em;" />.</p>



<h2 class="wp-block-heading">Enhanced Emoji Rendering</h2>



<p>While Xojo&#8217;s Graphics class supported rendering emojis on Windows and Linux, their appearance was less appealing.</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex"><div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="454" height="377" data-id="13137" src="https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r1.png" alt="" class="wp-image-13137" srcset="https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r1.png 454w, https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r1-300x249.png 300w" sizes="auto, (max-width: 454px) 100vw, 454px" /></figure>
</div>

<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="303" height="263" data-id="13143" src="https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r1Linux-1.png" alt="" class="wp-image-13143" srcset="https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r1Linux-1.png 303w, https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r1Linux-1-300x260.png 300w" sizes="auto, (max-width: 303px) 100vw, 303px" /></figure>
</div></figure>



<p>Now in Xojo 2024r2, we&#8217;ve enhanced emojis with vivid colors!</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex"><div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="454" height="377" data-id="13138" src="https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r2.png" alt="" class="wp-image-13138" srcset="https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r2.png 454w, https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r2-300x249.png 300w" sizes="auto, (max-width: 454px) 100vw, 454px" /></figure>
</div>

<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="303" height="263" data-id="13142" src="https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r2Linux-1.png" alt="" class="wp-image-13142" srcset="https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r2Linux-1.png 303w, https://blog.xojo.com/wp-content/uploads/2024/06/Emoji2024r2Linux-1-300x260.png 300w" sizes="auto, (max-width: 303px) 100vw, 303px" /></figure>
</div></figure>



<p>You’ll notice that other parts of the Xojo framework that utilize the Graphics class, such as the ListBox, have also benefited from this update.</p>



<h2 class="wp-block-heading">Understanding Emojis at a Deeper Level</h2>



<p>Understanding how emojis are encoded is crucial for grasping how Xojo&#8217;s String type works and how we interpret them. Any text or emoji displayed on the screen can be considered a Unicode sequence or a series of Unicode sequences. At a deeper level, a single Unicode sequence can be constructed from multiple Unicode code points (i.e., bytes of data). For clarity, we&#8217;ll describe one character<strong> </strong>(whether simple text or an emoji) as being composed of Unicode sequence(s).</p>



<p>To demonstrate, let&#8217;s try to understand the woman <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f469.png" alt="👩" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="913" height="628" src="https://blog.xojo.com/wp-content/uploads/2024/06/Woman1.png" alt="" class="wp-image-13149 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2024/06/Woman1.png 913w, https://blog.xojo.com/wp-content/uploads/2024/06/Woman1-300x206.png 300w, https://blog.xojo.com/wp-content/uploads/2024/06/Woman1-768x528.png 768w" sizes="auto, (max-width: 913px) 100vw, 913px" /></figure><div class="wp-block-media-text__content">
<p>This particular woman is not very complex, it is made up of one single Unicode sequence (with corresponding code points).  Our String type can easily handle this one Unicode sequence and reports correctly that the Length of the String is 1 (even though the entire emoji is made up of 4 bytes of code points).</p>
</div></div>



<p>Now let&#8217;s take a look at a more complicated woman <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f469-200d-1f9b0.png" alt="👩‍🦰" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="916" height="631" src="https://blog.xojo.com/wp-content/uploads/2024/06/Woman2-1.png" alt="" class="wp-image-13148 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2024/06/Woman2-1.png 916w, https://blog.xojo.com/wp-content/uploads/2024/06/Woman2-1-300x207.png 300w, https://blog.xojo.com/wp-content/uploads/2024/06/Woman2-1-768x529.png 768w" sizes="auto, (max-width: 916px) 100vw, 916px" /></figure><div class="wp-block-media-text__content">
<p>The only difference visually is that this woman has fiery red hair.  This subtle change in appearance means that to construct this emoji requires not 1, not 2, but 3 distinct Unicode sequences (with a grand total of 11 bytes of code points).</p>
</div></div>



<p>Note that the reported length of the String is 3 Unicode sequences, even though we visually see only one character. This distinction is very important in understanding how String functions work. Xojo&#8217;s String functions inherently deal with Unicode sequences, not individual characters. When you do need to work with complex emojis like these, you will want to utilize our String.Characters API which effectively manages this complexity.</p>



<h2 class="wp-block-heading">An Optimized String.Characters</h2>



<p>Given the prevalence of emojis in everyday text and messages, properly handling them within Xojo&#8217;s String type is crucial. While we initially introduced this feature as String.Characters, it functioned as an iterator until Xojo 2024r2. Now, String.Characters returns a String array, which can still be iterated, ensuring existing code continues to work as before. Additionally, this update offers the added advantage of significantly improved speed, especially on Windows and Linux. Along with this update, we introduced String.CharacterCount, which is useful when you need to know the number of characters in a string without storing them all in an array.</p>



<p>To further understand emojis and their corresponding Unicode sequences, check out this <a href="https://www.unicode.org/emoji/charts/full-emoji-list.html">Full Emoji List</a>.</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>Rotate that Picture!</title>
		<link>https://blog.xojo.com/2022/08/29/rotate-that-picture/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 29 Aug 2022 19:33:16 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Graphics]]></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 Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10696</guid>

					<description><![CDATA[Sometimes we need to rotate a Picture from portrait to landscape and vice versa. Since the introduction of the Graphics methods Translate and Rotate this is pretty simple to do! Continue reading and I will show you how to create a Method Extension for the Picture class that will be able to do that. This will work on Desktop and iOS projects by only copying and pasting the code, but you will need to make some changes to the example project for the Web version because of  the need to convert Picture to WebPicture and back.]]></description>
										<content:encoded><![CDATA[
<p>Sometimes we need to rotate a <a href="https://documentation.xojo.com/api/graphics/picture.html#picture">Picture</a> from portrait to landscape and vice versa. Since the introduction of the <a href="https://documentation.xojo.com/api/graphics/graphics.html">Graphics</a> methods <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-translate">Translate</a> and <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-rotate">Rotate</a> this is pretty simple to do! Continue reading and I will show you how to create a Method Extension for the Picture class that will be able to do that.</p>



<p>This will work on Desktop and iOS projects by only copying and pasting the code, but you will need to make some changes to the example project for the Web version because of  the need to convert Picture to WebPicture and back.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Download the <a href="https://drive.google.com/file/d/1-ctdr_ha_3mrToOvG5jrNHRdhQVEEeRM/view?usp=sharing">Example Project from this link</a>.</p></blockquote>



<p>As you probably know, Method Extensions need to be created in a <a href="https://documentation.xojo.com/api/language/module.html#module">Module</a>, so once you have created your new project, add a new Module to it (name it PictureExtensions) and, then, add a new method to the Module using the following signature:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> Rotate</li><li><strong>Parameters:</strong> Extends SourcePicture As Picture, Optional ClockWise As Boolean = True</li><li><strong>Return Type:</strong> Picture</li><li><strong>Scope:</strong> Global</li></ul>



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



<pre class="wp-block-preformatted"><code>Var p As New Picture(SourcePicture.Height, SourcePicture.Width)
Var g As Graphics = p.Graphics

Var tRotation As Double = (90 * 3.14159 / 180) // 90º in radians
If Not ClockWise Then
  tRotation = -tRotation
  g.Translate(0, g.Height)
Else
  g.Translate(g.Width,0)
End If
g.Rotate(tRotation)

g.DrawPicture(SourcePicture,0,0)

Return p</code></pre>



<p>And that is all!</p>



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



<p>Now, let&#8217;s create the user interface (UI) to test it (in this case, a Desktop Project), but you can follow the same steps for an iOS project.</p>



<p>First, drop into the Navigator any image you want to use as the source. In this example it is named &#8220;Test&#8221;.</p>



<p>Now, select the Window1 window to access the Layout Editor and drag to it an ImageViewer control from the Library. Use the resizing handles of the ImageViewer added to the Layout Editor so it looks like the one shown in the following screenshot:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="725" src="https://blog.xojo.com/wp-content/uploads/2022/08/ImageViewerSize-1024x725.png" alt="" class="wp-image-10697" srcset="https://blog.xojo.com/wp-content/uploads/2022/08/ImageViewerSize-1024x725.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/08/ImageViewerSize-300x213.png 300w, https://blog.xojo.com/wp-content/uploads/2022/08/ImageViewerSize-768x544.png 768w, https://blog.xojo.com/wp-content/uploads/2022/08/ImageViewerSize.png 1372w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>With the ImageViewer still selected in the Layout Editor, change its Name to &#8220;PreviewImageViewer&#8221; in the associated Inspector Panel, and make sure that the four locks under the Locking section are locked. Also, select the image &#8220;Test&#8221; as the image to be shown in the Image option found under the Appearance section.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="790" height="318" src="https://blog.xojo.com/wp-content/uploads/2022/08/ImageViewerLocks.png" alt="" class="wp-image-10698" srcset="https://blog.xojo.com/wp-content/uploads/2022/08/ImageViewerLocks.png 790w, https://blog.xojo.com/wp-content/uploads/2022/08/ImageViewerLocks-300x121.png 300w, https://blog.xojo.com/wp-content/uploads/2022/08/ImageViewerLocks-768x309.png 768w" sizes="auto, (max-width: 790px) 100vw, 790px" /></figure>
</div>


<p>Next, drag two buttons from the Library and drop them below the PreviewImageViewer control. The finished UI should look like the one in the following screenshot:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="867" src="https://blog.xojo.com/wp-content/uploads/2022/08/FinalUI-1024x867.png" alt="" class="wp-image-10699" srcset="https://blog.xojo.com/wp-content/uploads/2022/08/FinalUI-1024x867.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/08/FinalUI-300x254.png 300w, https://blog.xojo.com/wp-content/uploads/2022/08/FinalUI-768x650.png 768w, https://blog.xojo.com/wp-content/uploads/2022/08/FinalUI.png 1294w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>As you can see in the previous image, label the rightmost button as &#8220;Clockwise&#8221; and the leftmost one as &#8220;Counter Clockwise&#8221;.</p>



<p>Double click the &#8220;Clockwise&#8221; button and add the &#8220;Pressed&#8221; Event Handler to it. Next, add the following line of code to the associated Code Editor:</p>



<pre class="wp-block-preformatted"><code>PreviewImageViewer.Image = PreviewImageViewer.Image.Rotate</code></pre>



<p>Double click the &#8220;Counter Clockwise&#8221; button to add the &#8220;Pressed&#8221; Event Handler to it. Next, add the following line of code to it in the associated Code Editor:</p>



<pre class="wp-block-preformatted"><code>PreviewImageViewer.Image = PreviewImageViewer.Image.Rotate(False)</code></pre>



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



<p>Run the example project and click (or tap) the buttons, you will see how the image rotates 90º clockwise or counter clockwise depending on the button clicked!</p>



<figure class="wp-block-video"><video autoplay controls loop src="https://blog.xojo.com/wp-content/uploads/2022/08/RotatePicture.mp4"></video></figure>



<p>As you can see, we only needed a few lines of Xojo code to achieve this and this same code will work both on Desktop and iOS projects!</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>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2022/08/RotatePicture.mp4" length="607698" type="video/mp4" />

			</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>PDFDocument: More PDFGraphics Enhancements</title>
		<link>https://blog.xojo.com/2022/04/05/pdfdocument-more-pdfgraphics-enhancements/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 05 Apr 2022 13:30:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=9959</guid>

					<description><![CDATA[With the added functionality of the Brush property and the ClipToPath, Clip and DrawObject methods, Xojo 2022r1 completes the practical PDFGraphics class support for all the methods and properties that makes sense (or are applicable) from Xojo's Graphics class. ]]></description>
										<content:encoded><![CDATA[
<p>With the added functionality of the <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-brush">Brush</a> property and the <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-clipToPath">ClipToPath</a>, <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-clip">Clip</a> and <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-drawobject">DrawObject</a> methods, Xojo 2022r1 completes the practical <a href="https://documentation.xojo.com/api/pdf/pdfgraphics.html">PDFGraphics</a> class support for all the methods and properties that makes sense (or are applicable) from Xojo&#8217;s <a href="https://documentation.xojo.com/api/graphics/graphics.html">Graphics</a> class. </p>



<h3 class="wp-block-heading">Fillings and Drawing with Brush</h3>



<p>The Brush property allows you to assign, well, a brush to the current Graphics context in order to use it as the drawing color or filling for any of the available shapes when drawing text and also in drawing vectorial paths into the PDF document. When the Brush property is set to Nil, then the color set via DrawingColor will be applied.</p>



<p>What makes the Brush property especially interesting is that you can assign to it any instance created from the <a href="https://documentation.xojo.com/api/graphics/picture.htmlBrush">PictureBrush</a>, <a href="https://documentation.xojo.com/api/graphics/lineargradientbrush.html">LinearGradientBrush</a> or <a href="https://documentation.xojo.com/api/graphics/radialgradientbrush.html">RadialGradientBrush</a> classes.</p>



<ul class="wp-block-list"><li><strong>PictureBrush.</strong> PDFGraphics only supports the Tile, so the picture will be repeated until completing the filling area.</li><li><strong>LinearGradientBrush.</strong> PDFGraphics offers the same support you expect when it is used in combination with the regular Graphics class.</li><li><strong>RadialGradientBrush.</strong> PDFGraphics offers the same support you expect when it is used in combination with the regular Graphics class.</li></ul>



<p>The following image shows a PDF with PictureBrush applied as the color for the text, RadialGradientBrush set to fill the lower rectangle, and also as the outline color for drawing the &#8220;The Golden&#8221; text. Additionally, a LinearGradientBrush is used to fill the upper rectangle. The graphic context has been set to use a transparency value when drawing the text, so it also affect the transparency of the filling brush on these.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="462" src="https://blog.xojo.com/wp-content/uploads/2022/02/PDFGradient-1024x462.png" alt="" class="wp-image-9960" srcset="https://blog.xojo.com/wp-content/uploads/2022/02/PDFGradient-1024x462.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/02/PDFGradient-300x135.png 300w, https://blog.xojo.com/wp-content/uploads/2022/02/PDFGradient-768x347.png 768w, https://blog.xojo.com/wp-content/uploads/2022/02/PDFGradient-1536x693.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/02/PDFGradient-2048x924.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


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



<p>In opposition to ClipToRectangle or Clip, the ClipToPath method allows the definition of a irregular area that will act as the cropping area for any later drawing in the PDF, while ClipToRectangle and Clip provide regular areas: rectangles or squares.</p>



<p>When used in combination with PDFGraphics , expect the same behavior as when used in combination with a regular context from the Graphics class. For example, while the following snippet of code will draw a circle, only the portion contained in the ClipToPath set will be visible (a triangle), as you can see in the picture below from the generated PDF.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="281" height="300" src="https://blog.xojo.com/wp-content/uploads/2022/02/PDFClipToPath-281x300.png" alt="" class="wp-image-9961" srcset="https://blog.xojo.com/wp-content/uploads/2022/02/PDFClipToPath-281x300.png 281w, https://blog.xojo.com/wp-content/uploads/2022/02/PDFClipToPath.png 726w" sizes="auto, (max-width: 281px) 100vw, 281px" /></figure>
</div>


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

// Clip to a GraphicsPath
// Path is a triangle
Var p As New GraphicsPath
p.MoveToPoint(0, 0) // Start location
p.AddLineToPoint(20, 44)
p.AddLineToPoint(40, 0)
p.AddLineToPoint(0, 0)

g.SaveState
g.DrawingColor = Color.Red
g.ClipToPath(p)
g.FillOval(0, 0, 50, 50)
g.RestoreState

Var f As FolderItem = SpecialFolder.Desktop.Child("Cliptopath.pdf")
d.Save(f)</pre>



<h3 class="wp-block-heading">Clip: New Graphic Contexts</h3>



<p>In opposition to ClipToRectangle and ClipToPath, the Clip method is more powerful because it not only provides a cropping area but a fully new Graphic context. That is, you&#8217;ll be able to set any of the properties on the returned Graphics.Clip context and also call any of the PDFGraphics supported methods on it.</p>



<p>In this regard, all the coordinates provided for the drawing are relative to the top/left of the new Clip, and not on the main Graphics context it is based on. So, if we run the following snippet of code:</p>



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

g.FontSize = 40
g.DrawText("Hello…", 40, 100)

// Getting a new graphics context via Clip
// We change the Font and the 
// drawing color

Var g1 As Graphics = g.Clip(40, 130, 170, 50)
g1.FontName = "Times"
g1.DrawingColor = Color.Red
g1.DrawText("…World!", 0, 0)

// Back To drawing on the main Graphics context. 
// It Is Not affected by the changes made in the graphics subcontext from Clip.

g.DrawText("(Back to Main Graphics context)", 40, 240)
</pre>



<p>We can see how the line of code <code>g1.DrawTex "…World!", 0, 0</code> provides 0,0 as the X and Y coordinates for drawing the text. That is, the top/left origin of the created clip, while these values would be 40,130 as absolute coordinates if we had used the main graphics context.</p>



<p>The PDF generated as result of the previous code is the one shown in the following picture:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="300" height="112" src="https://blog.xojo.com/wp-content/uploads/2022/02/PDFClip-300x112.png" alt="" class="wp-image-9962" srcset="https://blog.xojo.com/wp-content/uploads/2022/02/PDFClip-300x112.png 300w, https://blog.xojo.com/wp-content/uploads/2022/02/PDFClip-1024x381.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/02/PDFClip-768x285.png 768w, https://blog.xojo.com/wp-content/uploads/2022/02/PDFClip-1536x571.png 1536w, https://blog.xojo.com/wp-content/uploads/2022/02/PDFClip.png 2034w" sizes="auto, (max-width: 300px) 100vw, 300px" /></figure>
</div>


<p>Of course, you can nest as many Clips as you need. For example you can create a new Clip from a previous clip created in a previous step.</p>



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



<p>PDFGraphics also allows you to draw any of the objects created as instances from any of the Object2D class, and also those under the hierarchy of a Group2D object:</p>



<ul class="wp-block-list"><li><strong><a href="https://documentation.xojo.com/api/graphics/arcshape.html">ArchShape</a></strong></li><li><strong><a href="https://documentation.xojo.com/api/graphics/curveshape.html">CurveShape</a></strong></li><li><strong><a href="https://documentation.xojo.com/api/graphics/figureshape.html">FigureShape</a></strong></li><li><strong><a href="https://documentation.xojo.com/api/graphics/ovalshape.html">OvalShape</a></strong></li><li><strong><a href="https://documentation.xojo.com/api/graphics/pixmapshape.html">PixmapShape</a></strong></li><li><strong><a href="https://documentation.xojo.com/api/graphics/rect.htmlShape">RectShape</a></strong></li><li><strong><a href="https://documentation.xojo.com/api/graphics/roundrectshape.html">RoundRectShape</a></strong></li><li><strong><a href="https://documentation.xojo.com/api/graphics/textshape.html">TextShape</a></strong></li></ul>



<p>For example, the following snippet of code will create the PDF document you can see in the picture.:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="300" height="241" src="https://blog.xojo.com/wp-content/uploads/2022/02/CurveShape-300x241.png" alt="" class="wp-image-9963" srcset="https://blog.xojo.com/wp-content/uploads/2022/02/CurveShape-300x241.png 300w, https://blog.xojo.com/wp-content/uploads/2022/02/CurveShape-1024x822.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/02/CurveShape-768x616.png 768w, https://blog.xojo.com/wp-content/uploads/2022/02/CurveShape.png 1154w" sizes="auto, (max-width: 300px) 100vw, 300px" /></figure>
</div>


<pre class="wp-block-preformatted">Var c As New CurveShape
c.ControlX(0) = 120
c.ControlY(0) = -40
c.Order = 1
c.X = 10
c.Y = 100
c.X2 = 250
c.Y2 = 100

Var fx As New FigureShape
fx.AddLine(0, 100, 50, 0)
fx.AddLine(50, 0, -50, 0)
fx.Border = 100  // opaque border
fx.BorderColor = &amp;cFF0000  // red border
fx.FillColor = &amp;cFFFF00   // yellow interior

Var d As New PDFDocument

Var g As Graphics = d.Graphics
g.DrawObject(c, c.x, c.y)
g.DrawObject(fx, 100, 100)

d.Save(SpecialFolder.Desktop.Child("CurveShape.PDF"))
</pre>



<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>PDFDocument: Transparency Support</title>
		<link>https://blog.xojo.com/2021/11/18/pdfdocument-transparency-support/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 18 Nov 2021 14:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=9491</guid>

					<description><![CDATA[Among the many improvements added to PDFDocument in Xojo 2021r3 is support for Graphics.Transparency as well as support for the alpha value in the color&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Among the many improvements added to PDFDocument in Xojo 2021r3 is support for <code>Graphics.Transparency</code> as well as support for the alpha value in the color assigned to the <code>Graphics.DrawingColor</code> property. Continue reading to learn more!</p>



<p>With 2021r3 you&#8217;ll be able to effectively set and use both <code>Transparency</code> and also the <code>Color</code> alpha component in any item you add to PDF documents: text, shapes and images! Moreover, the support of the <code>Pictures</code> has been improved so <code>PDFDocument</code> will work with the alpha channel of the image, instead of considering the alpha channel of the image as a fixed white background as in previous releases. That means more flexibility in the layout of the PDFs!</p>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="1024" height="403" src="https://blog.xojo.com/wp-content/uploads/2021/10/Captura-de-pantalla-2021-10-20-a-las-9.39.00-1024x403.png" alt="" class="wp-image-9492" srcset="https://blog.xojo.com/wp-content/uploads/2021/10/Captura-de-pantalla-2021-10-20-a-las-9.39.00-1024x403.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/10/Captura-de-pantalla-2021-10-20-a-las-9.39.00-300x118.png 300w, https://blog.xojo.com/wp-content/uploads/2021/10/Captura-de-pantalla-2021-10-20-a-las-9.39.00-768x302.png 768w, https://blog.xojo.com/wp-content/uploads/2021/10/Captura-de-pantalla-2021-10-20-a-las-9.39.00-1536x604.png 1536w, https://blog.xojo.com/wp-content/uploads/2021/10/Captura-de-pantalla-2021-10-20-a-las-9.39.00.png 1672w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>And because <code>Transparency</code> support is added to PDF using the <code>Graphic</code> class you, the way to use it is very straightforward. For example, put this following snippet of code in the <code>Open</code> Event Handler for a Desktop project (in this case, the referenced &#8220;GrassBG&#8221; picture has been added to the project):</p>



<pre class="wp-block-preformatted">// Creating a new PDFDocument instance
Var d As New PDFDocument

// Getting the graphic context from the PDF Document
Var g As Graphics = d.Graphics

// How many rectangles fits in the page width?
Var iter As Integer = g.Width/10

Var x As Integer

// Let's calculate the Y coordinate for center the
// GrassBG in the height of the PDF page
Var imageY As Integer = g.Height/2 - grassBG.Height/2

// And calculate the Y coordinate for drawing the rectangles
Var y As Integer = (imagey + grassbg.Height) - 40

// Transparency value = 0
Var tLevel As Integer

// Value to increase the Transparency on every rectangle
// drawing step
Var offset As Integer = 10

Var txt As String = "Transparency"

g.FontSize = 90
g.Bold = True

// X and Y coordinates to center the "Transparency" text
// on the page width / height
Var txtX As Integer =  g.Width/2 - g.TextWidth(txt) / 2
Var txtY As Integer = ImageY + GrassBG.Height - g.FontAscent

// Drawing the "Transparency" text -&gt; Background layer!
g.DrawText txt, txtX, txty

// Drawing the GrassBG picture over the text
// that's the second layer, and preserving
// the PNG alpha channel
g.DrawPicture grassBG,0,ImageY

// Setting the initial random color for drawing
// the first rectangle
Var rd As New Random
g.DrawingColor = Color.RGB(rd.InRange(0,255), rd.InRange(0,255), rd.InRange(0,255))

Var tmpLevel, y1 As Integer

// Drawing the horizontal strip of rectangles.
// This is the third layer
For n As Integer = 0 To iter

  // Setting the Transparency value
  g.Transparency = tLevel

  // Drawing the rectangle
  g.FillRectangle x,y,20,40

  // Assign the current Transparency value to
  // tmpLevel variable in order to draw the color drops

  tmpLevel = tLevel

  // Y coordinate for the color drop
  y1 = y + 40

  // Drawing the color drops for the current Rect
  For i As Integer = 0 To 10
    tmpLevel = tmpLevel - 10
    If tmpLevel &gt;= 0 Then
      g.Transparency = tmpLevel
      g.FillRectangle x,y1,2, 2
      y1 = y1 + 2
    End If
  Next i

  // We increase the X coordinate for drawing the
  // next rectangle
  x = x + 20

  //…and increase the Transparency value by ten
  tLevel = tLevel + offset

  // we reached the maximum allowable value for
  // the transparency, so let's invert the sign
  // for the offset and set a new
  // drawing color.
  If tLevel = 100 Or tLevel = 0 Then
    offset = -offset
    g.DrawingColor = Color.RGB(rd.InRange(0,255), rd.InRange(0,255), rd.InRange(0,255))
  End If

Next n

// Let's draw the fourth layer over the strip of rectangles
// with the "Comes to PDFDocument" text.
txt = "COMES TO PDFDOCUMENT"
g.FontSize = 30

// Notice that we are setting here the alpha value for
// the color, instead of relying on the Transparency property
g.DrawingColor = Color.RGB(255,255,255,127)

g.CharacterSpacing = 20
txtX = g.Width/2 - g.TextWidth(txt) /2
txty = y + 20 + g.FontAscent/2
g.DrawText txt,txtx, txty

// Getting a FolderItem reference pointing to the
// "Transparency.PDF" file on the desktop.
Var f As FolderItem = SpecialFolder.Desktop.Child("Transparency.pdf")

// Saving the PDFDocument file
d.Save(f)
f.Open</pre>



<p>Once you run this code, it will produce the PDF with the image as it is shown at the top of this post.</p>



<p>As you can see, there are four layers to  this document with the &#8220;Transparency&#8221; text drawn in the first layer (the farthest back), followed by a PNG image whose alpha channel lets us see the non-covered portions of the text behind it.</p>



<p>Next, the image is followed by a strip of horizontal rectangles in a new layer over it, that is drawn using a variable amount of transparency.</p>



<p>Finally, in the frontmost layer, we are drawing the &#8220;Comes to PDFDocument&#8221; text making use of the alpha value in the White color set as the DrawingColor.</p>



<p>You can see how the two upper layers mixed their color / level of transparency against the ones behind them and, of course, the text drawn in the PDF document continues to be vectorial and editable.</p>



<div class="wp-block-image is-style-default"><figure class="aligncenter"><img loading="lazy" decoding="async" width="640" height="480" src="https://blog.xojo.com/wp-content/uploads/2021/10/TransparencyPDF.gif" alt="" class="wp-image-9493"/></figure></div>



<h2 class="wp-block-heading">Transparency vs. Color&#8217;s Alpha Value</h2>



<p>As you probably already know, the <code>Transparency</code> value can range from 0.0 (opaque) to 100.0 (fully transparent), while the alpha component of a Color instance can range from 0.0 (opaque) to 255.0 (fully transparent).</p>



<p>What happen when you use both kind of values in the drawings of your PDF document? Let&#8217;s suppose you did set a Transparency value of 40 while setting the alpha value of the current drawing color to 127. In that case, the alpha value of the drawing color offers a higher transparency, so that will be the value applied in the drawing (because all kind of drawings, except Pictures, are affected by the current drawing color).</p>



<p>Otherwise, if the <code>Transparency</code> value is higher than the alpha value of the current drawing color, then that will be the level of transparency applied to the drawings and, in this case, also affecting to the Pictures in the PDF document.</p>



<p>Learn more about <a href="https://documentation.xojo.com/api/pdf/pdfdocument.html">PDFDocument</a> in the Xojo Documentation. And watch this 7 minute <a href="https://youtu.be/mp9Ylu3wY4g">video tutorial</a> that demonstrates this handy new feature!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PDFDocument: No More Blurry Images</title>
		<link>https://blog.xojo.com/2021/11/18/pdfdocument-no-more-blurry-images/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 18 Nov 2021 12:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PDF]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=9561</guid>

					<description><![CDATA[Among the major enhancements made to the images support in PDFDocument in Xojo 2021r3 release, in addition to transparency support, alpha channel support, and the new way the data is codified in the resulting PDF stream (no more DCTEncoding), we've also tackled an issue with images not being as sharp as they should have been. ]]></description>
										<content:encoded><![CDATA[
<p>Among the major enhancements made to the images support in <code>PDFDocument</code> in Xojo 2021r3 release, in addition to <a href="https://blog.xojo.com/2021/11/16/pdfdocument-transparency-support">transparency support</a>, alpha channel support, and the new way the data is codified in the resulting PDF stream (no more DCTEncoding), we&#8217;ve also tackled an issue with images not being as sharp as they should have been. </p>



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



<p>With Xojo 2021r3 we are handling the images added to <code>PDFDocument</code> in a different way. When images are added to the page using a smaller size than the original size, which is probably more common, using something like:</p>



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

g.DrawPicture myImage, 10, 10, 100, 100, 0, 0, myImage.Width, myImage.Height</pre>



<p>or</p>



<pre class="wp-block-preformatted">g.DrawPicture myImage, 10, 10, myImage.Width/3, myImage.Width/3, 0, 0, myImage.Width, myImage.Height</pre>



<p>&#8220;myImage&#8221; being an image added to the Xojo project, loaded from disk or from a database query.</p>



<p>You can appreciate how the quality has improved from left to right, below.</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="576" src="https://blog.xojo.com/wp-content/uploads/2021/11/Untitled-design-1024x576.png" alt="" class="wp-image-9577" srcset="https://blog.xojo.com/wp-content/uploads/2021/11/Untitled-design-1024x576.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/11/Untitled-design-300x169.png 300w, https://blog.xojo.com/wp-content/uploads/2021/11/Untitled-design-768x432.png 768w, https://blog.xojo.com/wp-content/uploads/2021/11/Untitled-design-1536x864.png 1536w, https://blog.xojo.com/wp-content/uploads/2021/11/Untitled-design.png 1600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Also, the new way the image PDF streams are created in order to get this sharpness means that all the data of the source image is added to the PDF document. In other words, it will increase its size. Comparing the same document, the one created with Xojo 2021r2.1 is 521 KB, and the one created with Xojo 2021r3 is 3.1 MB. This is because adding the full size of the the image takes a total of 950 KB, plus support for alpha and masks&#8230;</p>



<p>But the good side of the extra document size is that, because images are embedded at their full resolution, they will keep looking sharp even when the PDF document is displayed beyond 100% its original scale.  You can see in the PDF document below created with Xojo 2021r2.1:</p>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="1024" height="704" src="https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r2_1-1024x704.png" alt="" class="wp-image-9566" srcset="https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r2_1-1024x704.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r2_1-300x206.png 300w, https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r2_1-768x528.png 768w, https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r2_1-1536x1056.png 1536w, https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r2_1-2048x1408.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>And the PDF document created with Xojo 2021r3:</p>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="1024" height="704" src="https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r3-1024x704.png" alt="" class="wp-image-9567" srcset="https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r3-1024x704.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r3-300x206.png 300w, https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r3-768x528.png 768w, https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r3-1536x1056.png 1536w, https://blog.xojo.com/wp-content/uploads/2021/11/Zoom_Farm_r3-2048x1408.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">Document Size vs Image Quality</h3>



<p>The  winner of this battle depends what do you want to offer to your users. Using our example document we have the following figures:</p>



<ul class="wp-block-list"><li>PDF document resolution (w x h): 612 x 792 pixels</li><li>The apple image resolution (w x h): 607 x 576 pixels</li></ul>



<p>As you can see, the apple image has nearly the same resolution that the full page of the PDF Document! But it is rendered at a final size of 100 x 100 pixels. That means that the image will keep sharper even if we use a zoom value of 800% in the viewer app, but that has a cost in the size of the generated PDF document.</p>



<p>You&#8217;ll probably want to keep the images added to the <code>PDFDocument</code> pages at a maximum of twice the final width and height. That will produce good looking images in your PDF documents while keeping the document to a reasonable size. Learn more about PDFDocument and what&#8217;s new in the <a href="https://documentation.xojo.com/api/pdf/pdfdocument.html">Xojo Documentation</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>More New Features in Xojo PDF Support</title>
		<link>https://blog.xojo.com/2021/03/31/more-new-features-in-xojo-pdf-support/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 31 Mar 2021 13:50:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8368</guid>

					<description><![CDATA[The popular PDF support and features introduced last year in Xojo 2020r1, have gained several improvements and bug fixes in today's release. Now, with Xojo 2021r1, Xojo's PDF support include a set of new Graphics features that will continue to be expanded more in future releases.]]></description>
										<content:encoded><![CDATA[<p>The popular PDF support and features introduced last year in Xojo 2020r1, have gained several improvements and bug fixes in today&#8217;s release. Now, with Xojo 2021r1, Xojo&#8217;s PDF support include a set of new Graphics features that will continue to be expanded more in future releases.<span id="more-8368"></span></p>
<p>First off, you can now use the <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-characterspacing"><strong>CharacterSpacing</strong></a> property to adjust the text tracking:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8369 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/03/CharacterSpacing.png" alt="" width="444" height="286" srcset="https://blog.xojo.com/wp-content/uploads/2021/03/CharacterSpacing.png 444w, https://blog.xojo.com/wp-content/uploads/2021/03/CharacterSpacing-300x193.png 300w" sizes="auto, (max-width: 444px) 100vw, 444px" /></p>
<p>Next, you can create outlined text in your PDF documents by setting the <a href="https://documentation.xojo.com/api/graphics/graphics.html.Outline"><strong>Outline</strong></a> property to True:</p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8370 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/03/OutlinedText-1024x147.png" alt="" width="1024" height="147" srcset="https://blog.xojo.com/wp-content/uploads/2021/03/OutlinedText-1024x147.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/03/OutlinedText-300x43.png 300w, https://blog.xojo.com/wp-content/uploads/2021/03/OutlinedText-768x111.png 768w, https://blog.xojo.com/wp-content/uploads/2021/03/OutlinedText.png 1486w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>It is now possible to use the <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-linedash"><strong>LineDash</strong></a> method and the <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-linedashOffset"><strong>LineDashOffset</strong></a> property on the rendered text in combination with lines, paths and other shapes likes ovals and rectangles. You can also use these in combination with the <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-linecap"><strong>LineCap</strong></a> and <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-linejoin"><strong>LineJoin</strong></a> properties, like you can do with the regular Graphics class:</p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8371 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/03/DashedText-1024x151.png" alt="" width="1024" height="151" srcset="https://blog.xojo.com/wp-content/uploads/2021/03/DashedText-1024x151.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedText-300x44.png 300w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedText-768x113.png 768w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedText-1536x226.png 1536w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedText-2048x301.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8372 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/03/DashedLines-1024x285.png" alt="" width="1024" height="285" srcset="https://blog.xojo.com/wp-content/uploads/2021/03/DashedLines-1024x285.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedLines-300x84.png 300w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedLines-768x214.png 768w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedLines-1536x428.png 1536w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedLines.png 1680w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8373 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/03/DashedPath.png" alt="" width="788" height="484" srcset="https://blog.xojo.com/wp-content/uploads/2021/03/DashedPath.png 788w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedPath-300x184.png 300w, https://blog.xojo.com/wp-content/uploads/2021/03/DashedPath-768x472.png 768w" sizes="auto, (max-width: 788px) 100vw, 788px" /></p>
<p>It&#8217;s even possible to use the <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-savestate"><strong>SaveState</strong></a> and <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-restorestate"><strong>RestoreState</strong></a> methods in order to save and retrieve the graphics state values.</p>
<p>Check out the useful <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-clipToRectangle"><strong>ClipToRectangle</strong></a> method in your PDF documents. With it, all the drawing (rasterization of text, paths and shapes) will be restricted to the inside of the rectangle designated as the clipping area:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8374 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/03/ClipToRectangle.png" alt="" width="856" height="490" srcset="https://blog.xojo.com/wp-content/uploads/2021/03/ClipToRectangle.png 856w, https://blog.xojo.com/wp-content/uploads/2021/03/ClipToRectangle-300x172.png 300w, https://blog.xojo.com/wp-content/uploads/2021/03/ClipToRectangle-768x440.png 768w" sizes="auto, (max-width: 856px) 100vw, 856px" /></p>
<p>And if you need symbolic glyphs, you&#8217;ll find that using the ZapfDingbats and Symbol fonts will be very helpful in order to keep full vectorial resolution at any size you may need:</p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8375 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/03/ZapfDingbats-1024x212.png" alt="" width="1024" height="212" srcset="https://blog.xojo.com/wp-content/uploads/2021/03/ZapfDingbats-1024x212.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/03/ZapfDingbats-300x62.png 300w, https://blog.xojo.com/wp-content/uploads/2021/03/ZapfDingbats-768x159.png 768w, https://blog.xojo.com/wp-content/uploads/2021/03/ZapfDingbats.png 1302w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8376 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/03/Symbol-1024x265.png" alt="" width="1024" height="265" srcset="https://blog.xojo.com/wp-content/uploads/2021/03/Symbol-1024x265.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/03/Symbol-300x78.png 300w, https://blog.xojo.com/wp-content/uploads/2021/03/Symbol-768x199.png 768w, https://blog.xojo.com/wp-content/uploads/2021/03/Symbol.png 1190w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>Also important, is the new addition that lets you to create a PDF document composed of multiple page sizes, using NextPage (width As Integer, height As Integer):</p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8377 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/03/PageSizes-598x1024.png" alt="" width="598" height="1024" srcset="https://blog.xojo.com/wp-content/uploads/2021/03/PageSizes-598x1024.png 598w, https://blog.xojo.com/wp-content/uploads/2021/03/PageSizes-175x300.png 175w, https://blog.xojo.com/wp-content/uploads/2021/03/PageSizes-768x1315.png 768w, https://blog.xojo.com/wp-content/uploads/2021/03/PageSizes-897x1536.png 897w, https://blog.xojo.com/wp-content/uploads/2021/03/PageSizes.png 1156w" sizes="auto, (max-width: 598px) 100vw, 598px" /></p>
<p>Lastly, now it is possible to retrieve the full PDF data from the document as a <strong>MemoryBlock </strong>using the <a href="https://documentation.xojo.com/api/pdf/pdfdocument.html#pdfdocument-todata"><strong>ToData</strong></a> method. This is very useful in cases where you don&#8217;t need to save the PDF document to a file in first place, like when you are displaying the PDF document in a web app.</p>
<p>Questions? Ask me on Twitter <a href="https://twitter.com/xojoes">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary">Xojo Forum</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>New Graphics Methods for Desktop Projects</title>
		<link>https://blog.xojo.com/2021/03/31/new-graphics-methods-for-desktop-projects/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Wed, 31 Mar 2021 12:05:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8272</guid>

					<description><![CDATA[First available on iOS, staring with 2021 Release 1 you can now also use the Rotate, Translate, SaveState and RestoreState methods with Desktop projects.]]></description>
										<content:encoded><![CDATA[
<p>First available on iOS, staring with 2021 Release 1 you can now also use the <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-rotate">Rotate</a>, <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-translate">Translate</a>, <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-savestate">SaveState</a> and <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics-restorestate">RestoreState</a> methods with Desktop projects.</p>



<p>The Rotate method rotates drawing by the specified angle (in radians). The code below rotates the drawing area 45 degrees and draws a square so it will look like a diamond:</p>



<pre class="wp-block-preformatted">// Rotate the entire drawing area around its center
// and draw a rectangle
Const Pi = 3.14159
g.Rotate(Pi / 4, g.Width / 2, g.Height / 2) // 45 degrees or 1/8 of a circle
g.DrawingColor = Color.Blue
g.FillRectangle(g.Width / 2 - 20, g.Height / 2 - 20, 20, 20)</pre>



<p>You can use Translate to change the origin point for drawing. Used in combination with Rotate, this code rotates a square around a center point:</p>



<pre class="wp-block-preformatted">// Rotate square in center of graphics area
Const Pi = 3.14159
g.Translate(g.Width / 2, g.Height / 2)
g.Rotate(Pi / 4) // 45 degrees or 1/8 of a circle
g.DrawingColor = Color.Blue
g.FillRectangle(10, 10, 50, 50)</pre>



<p>With a few tweaks and a Timer, you can animate this (<a href="http://files.xojo.com/BlogExamples/Rotation.xojo_binary_project">download project</a>):</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="443" src="https://blog.xojo.com/wp-content/uploads/2021/03/CleanShot-2021-03-25-at-12.19.45.gif" alt="" class="wp-image-8280"/></figure>



<p>SaveState and RestoreState do what their names imply. They let you save the state of the graphics area so it can be restored later. SaveState can save this information:</p>



<ul class="wp-block-list"><li>Translate</li><li>Clip region</li><li>PenSize</li><li>AntiAliased</li><li>DrawingColor</li><li>Font</li><li>Underline</li><li>Rotate (rotation)</li></ul>



<p>This code draws a blue rectangle, saves the state and then draws a red rectangle. It then calls RestoreState which puts the color back to blue and draws another blue rectangle:</p>



<pre class="wp-block-preformatted">g.DrawingColor = Color.Blue
g.FillRectangle(10, 10, 20, 20)
g.SaveState
g.DrawingColor = Color.Red
g.FillRectangle(50, 50, 20, 20)
// Restore to state where FillColor is Blue
g.RestoreState
g.FillRectangle(10, 50, 20, 20)</pre>



<p>You might find that these new methods can serve as an alternative to <a href="https://documentation.xojo.com/api/graphics/object2d.html">Object2D</a> for certain types of graphics drawing.</p>



<p>There are also other new Graphics features in 2021r1, such as <a href="https://documentation.xojo.com/api/graphics/graphics.html.Scale">Scale</a> and <a href="https://documentation.xojo.com/api/graphics/graphics.html.Outline">Outline</a>, which you can read about on the <a href="https://documentation.xojo.com/api/graphics/graphics.html">Graphics</a> doc page.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>New Graphics Enhancements in Xojo</title>
		<link>https://blog.xojo.com/2020/11/24/new-graphics-enhancements-in-xojo/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 24 Nov 2020 14:15:14 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7717</guid>

					<description><![CDATA[Let's talk about the new properties and methods added to the Graphics class that will make all your Paint drawings more flexible and powerful! The enhancements include: LineDash, LineCap, LineJoin, the new Brush property with LinearGradientBrush, RadialGradientBrush, ShadowBrush and PictureBrush, and the new PictureBrush class.]]></description>
										<content:encoded><![CDATA[
<p>Let&#8217;s talk about the new properties and methods added to the Graphics class that will make all your Paint drawings more flexible and powerful! The enhancements include: LineDash, LineCap, LineJoin, the new Brush property with LinearGradientBrush, RadialGradientBrush, ShadowBrush and PictureBrush, and the new PictureBrush class.</p>



<p>You aren&#8217;t restricted to using solid lines anymore as the outline in the drawing of lines, rectangles, circles, ovals or paths anymore. From now on you can set the LineDash property of your choice, you can even set the LineDashOffset property and the LineCap and LineJoin from the supported types.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="712" height="540" src="https://blog.xojo.com/wp-content/uploads/2020/11/GraphicsGradients.png" alt="" class="wp-image-7718" srcset="https://blog.xojo.com/wp-content/uploads/2020/11/GraphicsGradients.png 712w, https://blog.xojo.com/wp-content/uploads/2020/11/GraphicsGradients-300x228.png 300w" sizes="auto, (max-width: 712px) 100vw, 712px" /></figure></div>



<p>Moreover, the drawing fill is no longer limited to a solid color! The Graphic class includes now the Brush property, so you can create any of the supported brushes and assign any of them to it. For example, you can create color gradients really easy creating new instances from the LinearGradientBrush, RadialGradientBrush and assigning these to the Brush property. Of course, you can set as many GradientStops on these with the desired color to create the transition from one color to other in your gradient at given points during the filling process.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="690" height="388" src="https://blog.xojo.com/wp-content/uploads/2020/11/BrushDemo.gif" alt="" class="wp-image-7719"/></figure></div>



<p>And, even better, you&#8217;re not restricted to using solid colors or gradient colors when you fill an object. Use the new <strong>PictureBrush</strong> class to assign the Picture you want to use for the fill and even the fill mode: Pad, Tile or Mirror.</p>



<p>Further, you can now give your text or shapes a shadow using the ShadowBrush property in the Graphics class, and the ability to create new instances from the ShadowBrush class.</p>



<p>In fact, when you use the default constructor of the ShadowBrush class, you&#8217;ll get an object right to use with a default color, offset for the X and Y coordinates and by default blur amount. Of course you can set any of these properties as you need for your ShadowBrush instances!</p>



<p>Questions? Ask me on Twitter <a href="https://twitter.com/xojoes">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary">Xojo Forum</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WebChart, Easy as Pie</title>
		<link>https://blog.xojo.com/2020/09/11/web-2-0-webchart-easy-as-pie/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Fri, 11 Sep 2020 15:00:00 +0000</pubDate>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></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[Web 2.0]]></category>
		<category><![CDATA[Xojo Code]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7473</guid>

					<description><![CDATA[Learn to use the new WebChart class in Xojo's Web 2.0. Based on Chart.js, this class offers eight chart types you can create and use including the Line, Bar, Pie or Doughnut chart types.]]></description>
										<content:encoded><![CDATA[<p>Among the many new features introduced by the <a href="https://blog.xojo.com/2020/08/27/converting-web-projects-to-web-framework-2-0/"><strong>Web Framework 2.0</strong></a>, one of my favourites is the new <strong>WebChart</strong> class. Based on <a href="https://www.chartjs.org">Chart.js</a>, this class offers a total of eight chart types you can create and use really easily in your projects; including the Line, Bar, Pie or Doughnut chart types among others.<span id="more-7473"></span></p>
<p>The best thing is that implementing this feature in your Xojo Web projects is really easy to do, and extremely flexible to set-up! Just drag and drop the <a href="https://documentation.xojo.com/api/user_interface/web/webchart.html">WebChart</a> control from the Library to your page (or <a href="https://documentation.xojo.com/api/user_interface/web/webcontainer.html"><strong>ContainerControl</strong></a>) layout, set the Mode (type) of the chart you want to use and other properties in the Inspector Panel and you&#8217;re almost done.</p>
<figure id="attachment_7476" aria-describedby="caption-attachment-7476" style="width: 500px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-7476" src="https://blog.xojo.com/wp-content/uploads/2020/09/WebChartInAction.gif" alt="" width="500" height="345"><figcaption id="caption-attachment-7476" class="wp-caption-text">WebChart in Action</figcaption></figure>
<p>Then, add your&nbsp;<a href="https://documentation.xojo.com/api/user_interface/web/webchart.htmlDataset"><strong>DataSet</strong></a> instances for your chart to display. Every one of these DataSets just needs to receive the Label to use, the data to display and the colors associated with each value or datapoint. For example, the following snippet of code creates a new <a href="https://documentation.xojo.com/api/user_interface/web/webchart.htmlCircularDataset">WebChartCircularDataSet</a> (<a href="https://documentation.xojo.com/api/user_interface/web/webchart.htmlLinearDataset">WebChartLinearDataset</a> and <a href="https://documentation.xojo.com/api/user_interface/web/webchart.htmlScatterDataset">WebChartScatterDataset</a> are other DataSet classes available, each of these use their own set of parameters in the Constructor):</p>
<pre>Var sales() As Double = Array(12500.0, 30200, 25600, 15800)
Var colors() As Color = Array(Color.Orange, Color.Brown, Color.Purple, Color.DarkGray)
Var ds As New WebChartCircularDataset("Test", sales, Colors)</pre>
<p>Every DataSet can be configured so it can fill or not fill the graphical object in the chart representing the value, and also associate another object with it via the usual <code>Tag</code> property.</p>
<p>Once we have a DataSet in place, we can add it to the chart simply calling the AddDataSet method on the WebChart instance. You can also add it to a specific position index or even remove a DataSet from the currently available ones in the WebChart instance. In this case <code>T</code> is the variable pointing to a WebChart:</p>
<pre>T.AddDataset(ds)</pre>
<p>Of course it is also possible to add labels to the WebChart itself. For example, if our DataSet has a total of four values, then we probably would want to add the same amount of labels to the chart instance:</p>
<pre>T.AddLabels("Q1", "Q2", "Q3", "Q4")</pre>
<p>In addition, one visually appealing thing is that the WebChart instance will animate the presentation of the dataset values; something it will do again every time we add a new DataSet to it. It is also possible to disable this behavior for the WebChart both via code and using the Inspector Panel.</p>
<p>Of course, you can add new DataSets to the WebChart once it is already shown in the webpage if you need to. But what you can&#8217;t do at runtime is changing the Mode (or type) of the WebChart itself. That is, if you did set a WebChart instance with the Mode set to Line, then you can&#8217;t change the mode via code to Bar.</p>
<p>All in all, I really think this is one of the (many) exceptional features introduced with Web 2.0 that will make your web apps shine even more and without much effort! Definitively, the icing on the Pie.</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>Top-Rounded Rectangle</title>
		<link>https://blog.xojo.com/2020/08/17/top-rounded-rectangle/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Mon, 17 Aug 2020 19:44:45 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7235</guid>

					<description><![CDATA[On the forum a user asked if there was a way to create a rectangle with only the top left and top right corners being rounded. Xojo's built-in RoundRectangle control draws with all four corners rounded, so that was not an option. One solution is to use a GraphicsPath to draw exactly what you want. With a GraphicsPath you can use the AddArc() method to add rounded corners and then draw the lines for the rest of the rectangle.]]></description>
										<content:encoded><![CDATA[
<p>On <a href="https://forum.xojo.com/t/rounded-corners/54587">the forum</a> a user asked if there was a way to create a rectangle with only the top left and top right corners being rounded. Xojo&#8217;s built-in RoundRectangle control draws with all four corners rounded, so that was not an option.</p>



<p>One solution is to use a <a href="https://documentation.xojo.com/api/graphics/graphics.htmlPath">GraphicsPath</a> to draw exactly what you want. With a GraphicsPath you can use the AddArc() method to add rounded corners and then draw the lines for the rest of the rectangle.</p>



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



<p>This is the code for desktop:</p>



<pre class="wp-block-preformatted">Const Pi = 3.14159<br>Const x = 50<br>Const y = 00<br>Const rectHeight = 100<br>Const rectWidth = 100<br>Const arcRadius = 20<br><br>Var topRoundRect As New GraphicsPath<br>topRoundRect.AddArc(x, y, arcRadius, Pi, 1.5 * Pi, False)<br>topRoundRect.AddArc(x + rectWidth, y, arcRadius, 1.5 * Pi, 0, False)<br>topRoundRect.AddLineToPoint(x + rectWidth + arcRadius, rectHeight)<br>topRoundRect.AddLineToPoint(x - arcRadius, rectHeight)<br>topRoundRect.AddLineToPoint(x - arcRadius, y)<br><br>g.DrawPath(topRoundRect)</pre>



<p>You&#8217;ll want to tweak the numbers to fit your situation, but this should give you the idea.</p>



<p>With a couple minor tweaks<sup>1</sup>, the same code also works on iOS. Change <strong>GraphicsPath</strong> to <strong><a href="https://documentation.xojo.com/api/deprecated/iospath.html">iOSPath</a></strong> and change the <strong>AddLineToPoint()</strong> method calls to <strong>LineToPoint()</strong>. This is the result:</p>



<div class="wp-block-image"><figure class="aligncenter size-medium"><img loading="lazy" decoding="async" width="262" height="300" src="https://blog.xojo.com/wp-content/uploads/2020/08/2020-08-11_09-05-04-262x300.png" alt="" class="wp-image-7236" srcset="https://blog.xojo.com/wp-content/uploads/2020/08/2020-08-11_09-05-04-262x300.png 262w, https://blog.xojo.com/wp-content/uploads/2020/08/2020-08-11_09-05-04.png 472w" sizes="auto, (max-width: 262px) 100vw, 262px" /></figure></div>



<p>GraphicsPath maps very closely to HTML5 Canvas Path so you can often find code samples online that are easily adapted to Xojo. For example, take a look at this JavaScript code from <a href="https://www.html5canvastutorials.com/tutorials/html5-canvas-paths/">HTML5 Canvas Tutorial</a> which draws a squiggle:</p>



<pre class="wp-block-preformatted">var context = canvas.getContext('2d');<br><br>context.beginPath();<br>context.moveTo(100, 20);<br><br>// line 1<br>context.lineTo(200, 160);<br><br>// quadratic curve<br>context.quadraticCurveTo(230, 200, 250, 120);<br><br>// bezier curve<br>context.bezierCurveTo(290, -40, 300, 200, 400, 150);<br><br>// line 2<br>context.lineTo(500, 90);<br><br>context.lineWidth = 5;<br>context.strokeStyle = 'blue';<br>context.stroke();</pre>



<div class="wp-block-image"><figure class="aligncenter size-medium"><img loading="lazy" decoding="async" width="300" height="129" src="https://blog.xojo.com/wp-content/uploads/2020/08/2020-08-11_10-04-41-300x129.png" alt="" class="wp-image-7237" srcset="https://blog.xojo.com/wp-content/uploads/2020/08/2020-08-11_10-04-41-300x129.png 300w, https://blog.xojo.com/wp-content/uploads/2020/08/2020-08-11_10-04-41-768x331.png 768w, https://blog.xojo.com/wp-content/uploads/2020/08/2020-08-11_10-04-41.png 938w" sizes="auto, (max-width: 300px) 100vw, 300px" /></figure></div>



<p>Notice how similar the JavaScript looks to the equivalent Xojo code that draws the same squiggle:</p>



<pre class="wp-block-preformatted">Var path As New GraphicsPath<br>path.MoveToPoint(100, 20)<br><br>// line 1<br>path.AddLineToPoint(200, 160)<br><br>// quadratic curve<br>path.AddQuadraticCurveToPoint(230, 200, 250, 120)<br><br>// bezier curve<br>path.AddCurveToPoint(290, -40, 300, 200, 400, 150)<br><br>// line 2<br>path.AddLineToPoint(500, 90)<br><br>g.DrawingColor = Color.Blue<br>g.DrawPath(path)</pre>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<div class="wp-block-group is-layout-flow wp-block-group-is-layout-flow"><div class="wp-block-group__inner-container"></div></div>
</div></div>



<p><sup>1</sup> As we mentioned in the <a href="https://youtu.be/oi5MCrDlpsg">Xojo 2020 Update video</a> and in our <a href="https://documentation.xojo.com/resources/roadmap.html">Roadmap</a>, the iOS API is planned to match the API used by other platforms so you won&#8217;t need slightly different code here in the future.</p>



<p></p>



<p> </p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Quick Tip: Centering a Picture on any Graphic Context</title>
		<link>https://blog.xojo.com/2020/06/17/quick-tip-centering-a-picture-on-any-graphic-context/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 17 Jun 2020 10:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7115</guid>

					<description><![CDATA[Taking the class extension approach means that you can reuse the same code for any of these (or any additional class) offering a Graphic context, so you can pass along the Picture you want to center and re-scale (if needed) in its area.]]></description>
										<content:encoded><![CDATA[<p>Sure you can create a Subclass of any Picture, Canvas or class and write code to center another Picture in its respective Graphics contexts. But taking the class extension approach means that you can reuse the same code for any of these (or any additional class) offering a Graphic context, so you can pass along the Picture you want to center and re-scale (if needed) in its area.<span id="more-7115"></span></p>
<p>You may already know that in order to create a Method Class Extension, you need to add a new method to a Module. For example, you can create a new Module and name it &#8220;Graphic Extensions&#8221;.</p>
<p>Then add a new Method to it using the following signature:</p>
<ul>
<li><strong>Name:</strong> CenterPicture</li>
<li><strong>Parameters:</strong> Extends g As Graphics, Image As Picture</li>
<li><strong>Scope:</strong> Global</li>
</ul>
<p><img loading="lazy" decoding="async" class="size-full wp-image-7116 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2020/06/GraphicsExtension.gif" alt="" width="616" height="442" /></p>
<p>Add the code that will position and scale the received picture on the Graphic area:</p>
<pre>// Let's check first that the referenced Picture is not nil
If Not (image Is Nil) Then
  
  Var Height, Width As Integer
  Var SourceY, SourceX As Integer = 0
  
  //If the Image width and Height just fit inside the Graphic area
  //then there is not need to scale it.
  If image.Width &lt;= g.Width And image.Height &lt;= g.Height Then
    
    Width = image.Width
    Height = image.Height
    
  Else
    
    // Else, let's scale the image when its width is greater
    // than its height
    If g.Width &gt;= g.Height And image.Width &gt;= image.Height Then
      
      Width = g.Width
      Height = (Image.Height * Width) / image.Width
      
      
      //…recalculating its width if the new height is greater
      // than the height of the current Graphics context
      If Height &gt; g.Height Then
        
        Height = g.Height
        Width = (image.Width*Height)/image.Height
        
      End If
    
    // let's scale the image when its width is less than its height
    // but the width of the graphics context is greater than its height
    Elseif g.Width &gt;= g.Height And image.Width &lt;= image.Height Then
      
      Height = g.Height
      Width = (image.Width * Height) / image.Height
    
    // scale the imagen when the width is greater than its height
    // and the width from the Graphics context is less than its height  
    Elseif g.Width &lt;= g.Height And image.Width &gt;= image.Height Then
      
      Width = g.Width
      Height = (image.Height * Width) / image.Width
    
    // lastly, this is the case when both the image and Graphics width 
    // is less than its respective heights.  
    Elseif g.Width &lt;= g.Height And image.Width &lt;= image.Height Then
      
      Height = g.Height
      Width = (image.Width*Height)/image.Height
      
      // It may be the case that the new calculated width is greater
      // than the available width in the Graphics context,
      // so we adjust the scale on the max width for the image.
      If Width &gt; g.Width Then
        
        Width = g.Width
        Height = (image.Height*Width)/image.Width
        
      End If
      
    End If
    
  End If
  
  // Let's calculate the X and Y coordinates in order to
  // display the image centered on the Graphics context
  sourcex = (g.Width/2) - (Width/2)
  sourcey = (g.Height/2) - (Height/2)
  
  // and we draw finally the picture in the Graphic context
  // using the new calculated values
  g.DrawPicture(image,sourcex,sourcey,Width,Height,0,0,image.Width,Image.Height)
  
End If</pre>
<p>And that&#8217;s all.</p>
<p>From now on, you can call this method from the Paint Event Handler of a Canvas subclass, or the Graphics context of another Picture using:</p>
<pre>g.CenterPicture(mImage) // mImage is a valid instance of a Picture</pre>
<p>Of course, you can go ahead and add other useful method extensions to your own Graphics Extensions module.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Starting Graphics with GraphicsPath</title>
		<link>https://blog.xojo.com/2020/03/26/starting-graphics-with-graphicspath/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 26 Mar 2020 10:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=6877</guid>

					<description><![CDATA[In Xojo there is a new class, GraphicsPath, that you can use to create graphics as a mathematical description of shapes and lines; ranging from simple lines to Bèzier curves, arcs, rectangles, there are many advantages to using these!]]></description>
										<content:encoded><![CDATA[<p>In Xojo there is a new class, GraphicsPath, that you can use to create graphics as a mathematical description of shapes and lines; ranging from simple lines to Bézier curves, arcs, rectangles, there are many advantages to using these! For example, as a class on its own, it doesn&#8217;t even needs a graphical context (Graphics) in order to describe the shapes you want to use, and the mathematical representation means more control and precision. Simply put, you only need to join the points!<span id="more-6877"></span></p>
<p>The available methods in the class give you the ability to create any shape you need in an easier way when compared with the <a href="https://documentation.xojo.com/api/graphics/object2d.html">Object2D</a> class (and other classes you may use in combination), from simple rectangles (including the &#8220;rounded&#8221; variation), to arcs, curves or quadratic curves (Bézier curves) where we model them through a control point.</p>
<p>The interesting thing in <a href="https://documentation.xojo.com/api/graphics/graphics.htmlPath">GraphicsPath</a> is that every call to any of these methods have the starting coordinate the ending point of the previous shape in the path, while you can use the MoveToPoint method in order to, well, move the virtual &#8220;cursor&#8221; to any point of your election without painting anything in the process. Thus, this one would act as the starting (or initial) point for the next method drawing in the path.</p>
<p>As for the available properties, you can use these:</p>
<ul>
<li><strong>CurrentPoint</strong>. Check this value in order to know the current coordinate, so you can make the proper decision about what to do next in your code.</li>
<li><strong>IsEmpty</strong>. This one allows us to know if the path is empty; this is, it doesn&#8217;t contain any shape definition in it.</li>
<li><strong>IsRectangle</strong>. This property is really useful to know if we are dealing with a rectangle shape in our GraphicsPath instance.</li>
</ul>
<h2>Starting your Path&#8230;</h2>
<p>Let&#8217;s see how simply it is to apply these principles during the creation of a graphic making use of a Bézier curve, and the best part is that this example project lets us move that control point, so you can make a better idea about how it goes. This is the final look of our example application:</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-6878 size-full" src="https://blog.xojo.com/wp-content/uploads/2020/03/FinalProject.png" alt="" width="878" height="736" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/FinalProject.png 878w, https://blog.xojo.com/wp-content/uploads/2020/03/FinalProject-300x251.png 300w, https://blog.xojo.com/wp-content/uploads/2020/03/FinalProject-768x644.png 768w" sizes="auto, (max-width: 878px) 100vw, 878px" /></p>
<h2>1. Designing the User Interface</h2>
<p>The user interface for our example app is quite simple, with a few controls in it:</p>
<ul>
<li>2 Labels</li>
<li>2 Sliders. Use the Inspector Panel on them to activate the &#8220;Allow Live Scrolling&#8221;, under the Behavior section.</li>
<li>1 Canvas control.</li>
</ul>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-6879 size-large" src="https://blog.xojo.com/wp-content/uploads/2020/03/Layout-1024x572.png" alt="" width="1024" height="572" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/Layout-1024x572.png 1024w, https://blog.xojo.com/wp-content/uploads/2020/03/Layout-300x167.png 300w, https://blog.xojo.com/wp-content/uploads/2020/03/Layout-768x429.png 768w, https://blog.xojo.com/wp-content/uploads/2020/03/Layout.png 1064w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>Set the Locking properties in the Inspector Panel for the Sliders and the Canvas, as shown in the picture. This will allow the controls to properly resize when the Window size is changed by the user.</p>
<h2>2. Creating your own Graphic Canvas (Canvas subclass)</h2>
<p>We need the Canvas to be specialized, so that means that we need to subclass the Canvas class and put in all the specific stuff we may need.</p>
<p>Add a new Class to the project (Insert &gt; Class), and access the Inspector Panel to change the values of the following properties:</p>
<ul>
<li><strong>Name:</strong> CuadraticCanvas</li>
<li><strong>Super:</strong> Canvas</li>
</ul>
<p>Next, add two Computed Properties. For that, make sure you selected the just added class in the Navigator, and access the contextual menu to choose the Add to &#8220;CuadraticCanvas&#8221; &gt; Computed Property option.</p>
<p>Change the following fields in the associated Inspector Panel:</p>
<ul>
<li><strong>Name:</strong> PC1X</li>
<li><strong>Type:</strong> Double</li>
</ul>
<p>Next, choose the &#8220;Set&#8221; method on the Computed Property and add this single line of code after the existing one:</p>
<pre>invalidate</pre>
<p>This will force our canvas to redraw itself every time we change the value of the X point in the coordinate of our Bézier curve.</p>
<p>Repeat the operation in order to add a second Computer Property, using the following values this time:</p>
<ul>
<li><strong>Name:</strong> PC1Y</li>
<li><strong>Type:</strong> Double.</li>
</ul>
<p>Remember to add the &#8220;Invalidate&#8221; line of code to the &#8220;Set&#8221; method on this property too.</p>
<p>Now is time to add the Paint Event Handler to our class. For that, and with our class item still selected on the Navigator, access the contextual menu and choose the Add to &#8220;CuadraticCanvas&#8221; &gt; Event Handler option.</p>
<p>In the resulting panel, select the Paint entry from the left list and confirm the selection. The last action will add the new event to the class, bringing the associated Code Editor. Write the following code snippet:</p>
<pre>g.AntiAlias = True

g.DrawingColor = &amp;cffffff
g.FillRectangle(0,0,g.Width,g.Height)
g.DrawingColor = &amp;c000000
g.DrawLine(g.Width/2,0,g.Width/2,g.Height)
g.DrawLine(0,g.Height/2,g.Width,g.Height/2)

g.DrawingColor = &amp;ccc1233

Var gp As New GraphicsPath
gp.MoveToPoint(0,g.Height/2)
gp.AddQuadraticCurveToPoint(Me.pc1x,Me.pc1y,g.Width,g.Height/2)

g.DrawPath gp</pre>
<p>As you can see, here is where we create our GraphicsPath instance (the &#8220;gp&#8221; variable) so we can use it to add the quadratic curve using as the control point the values of our &#8220;PC1X&#8221; and &#8220;PC1Y&#8221; properties.</p>
<p>In order for our GraphicsPath instance to be drawn in the graphical context (the &#8220;g&#8221; parameter), we need to use the DrawPath method passing along our &#8220;gp&#8221; object as argument.</p>
<h2>3. Joining the Points</h2>
<p>Choose the &#8220;Canvas1&#8221; item in the project Navigator and access the Inspector Panel so you can change the &#8220;Super&#8221; value to &#8220;CuadraticCanvas&#8221;.</p>
<p>Next, select the &#8220;Slider1&#8221; item and add the &#8220;ValueChanged&#8221; Event Handler to it. Write this line of code in the associated Code Editor:</p>
<pre>canvas1.pc1x = me.Value</pre>
<p>Repeat the operation with the &#8220;Slider2&#8221; item, except that this time you need to change the line of code slightly:</p>
<pre>canvas1.pc1y = me.Value</pre>
<p>We are almost done! Select now the &#8220;Window1&#8221; item in the project Navigator and add these two events to it: Open and Resizing. Write this line of code in both event handlers:</p>
<pre>SetSliders</pre>
<p>Finally, we will add a new method to the Window1 item. For that, select the Window1 item in the project Navigator (if it is not yet selected), and access the contextual menu in order to choose the Add to &#8220;Window1&#8221; &gt; Method option. Make use of the Inspector Panel to reflect this method signature:</p>
<ul>
<li><strong>Method Name:</strong> SetSliders</li>
</ul>
<p>And write the following code snippet in the associated Code Editor for the method:</p>
<pre>slider1.MaximumValue = canvas1.Width
slider2.MaximumValue = canvas1.Height
canvas1.PC1x = Slider1.Value
canvas1.PC1y = Slider2.Value</pre>
<p>This will be the method in charge of updating the maximum value of the sliders to the width and height of the window, and also to update our canvas control properties forcing it to redraw itself with the new values.</p>
<h2>In Good Shape!</h2>
<p>We have everything set now. Run the app and use the sliders to move the Bézier curve control point. As you change the sliders values, you&#8217;ll see how the curve smoothly updates its shape in the canvas.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-6880" src="https://blog.xojo.com/wp-content/uploads/2020/03/Bezier-1024x576.gif" alt="" width="1024" height="576" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/Bezier-1024x576.gif 1024w, https://blog.xojo.com/wp-content/uploads/2020/03/Bezier-300x169.gif 300w, https://blog.xojo.com/wp-content/uploads/2020/03/Bezier-768x432.gif 768w, https://blog.xojo.com/wp-content/uploads/2020/03/Bezier-1536x864.gif 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>You have a starting point now! Try to use the other methods available in the GraphicsPath class in order to make more complex drawings in your own apps!</p>
<p><a href="https://www.dropbox.com/s/7gxy6f1rlhgpx8d/GraphicsPathExample.zip?dl=1">Download the example Xojo Project</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Programming your own Solar System with Xojo + MBS SceneKit</title>
		<link>https://blog.xojo.com/2020/02/17/a-solar-system-with-xojo/</link>
		
		<dc:creator><![CDATA[Stefanie Juchmes]]></dc:creator>
		<pubDate>Mon, 17 Feb 2020 10:00:00 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Monkeybread Software]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=6604</guid>

					<description><![CDATA[Learn to create a solar system in Xojo with the help of the MBS Xojo Plugin component SceneKit. SceneKit is an Apple framework that supplies functions for graphic and animation designs. 
]]></description>
										<content:encoded><![CDATA[
<p>In this post I will show you how to create you own solar system in Xojo with the help of the <a href="https://www.monkeybreadsoftware.de/xojo/">Monkeybread Software</a> plugin component SceneKit. <a href="https://developer.apple.com/scenekit/">SceneKit</a> is an Apple framework that supplies functions for graphic and animation designs.&nbsp;</p>



<p>Please run a current Xojo version with MBS Xojo Mac64bit Plugin installed. Due to our dependencies list, please add Main, MacCloud, MacBase, MacCocoa, MacControls, MacCG and MacCF plugins too. Start with a new project. To the window we add a SCNControlMBS control from the library and rename it MyControl. Drag it across the entire window size and lock all edges. It is very useful because we want fullscreen mode later.&nbsp;</p>



<p>Then we need two properties MyScene and MyView. MyScene has the type SCNSceneMBS and MyView has the type SCNViewMBS. Afterwards, add the open event of the SceneKit control.&nbsp;</p>



<p>We start with the setting of MyView and MyScene like this:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<pre class="wp-block-preformatted">MyView = Me.View 
MyScene = New SCNSceneMBS
MyView.scene = MyScene</pre>
</div></div>



<p>Then we enable the default light and the camera control, because we want to see a 3D effect and want to move the camera using the mouse. We set black as the background color.</p>



<pre class="wp-block-preformatted">myView.autoenablesDefaultLighting = True  
MyView.allowsCameraControl = True&nbsp;  
myView.backgroundColor = NSColorMBS.blackColor&nbsp;</pre>



<p>Next we add our first node to the scene. The center of the scene is the Sun. In basic structure the Sun is a lit up sphere. So we add a sphere geometry with a given size. In this project we can&#8217;t work with the original conditions, because Mercury would be so small that it is impossible to see. Plus, we would have same problem for the distance between the Sun and the planets. Because that, our Sun has a radius of 13. Then we add a node and give it geometric information about the Sun. The position of the node is the origin with the coordinates 0,0,0. Finally, we add the node to our scene.&nbsp;</p>



<pre class="wp-block-preformatted">Dim SunGeometry As New SCNSphereMBS(13)  
Dim Sun As New SCNNodeMBS(SunGeometry)  
Sun.Position = New SCNVector3MBS(0, 0, 0)   
MyScene.rootNode.addChildNode(Sun)</pre>



<p>Then we start our program.&nbsp;</p>



<p>We see a white sphere on the screen. The Sun looks a bit edged because of the segment count. Our Sun sphere is very big and needs more segments then the default segment count. Set the segment count property ahead of adding the node to the scene command.&nbsp;</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="712" height="905" src="https://blog.xojo.com/wp-content/uploads/2020/02/Sun.png" alt="" class="wp-image-6605" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/Sun.png 712w, https://blog.xojo.com/wp-content/uploads/2020/02/Sun-236x300.png 236w" sizes="auto, (max-width: 712px) 100vw, 712px" /></figure></div>



<pre class="wp-block-preformatted">	SunGeometry.segmentCount=100&nbsp;</pre>



<p>Then we set each planet in a similar way. Because the planets look different, we want to change their colors as appropriate or even put a picture as a graphic over each sphere. For the color of an object we have the firstMaterial.diffuse.contents Property. This is how you would set a gray color for Mercury.&nbsp;</p>



<pre class="wp-block-preformatted"> MercuryGeometry.firstMaterial.diffuse.contents = NSColorMBS.grayColor</pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="645" src="https://blog.xojo.com/wp-content/uploads/2020/02/Map-1024x645.png" alt="" class="wp-image-6606" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/Map-1024x645.png 1024w, https://blog.xojo.com/wp-content/uploads/2020/02/Map-300x189.png 300w, https://blog.xojo.com/wp-content/uploads/2020/02/Map-768x484.png 768w, https://blog.xojo.com/wp-content/uploads/2020/02/Map.png 1442w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>If we want to map a picture on a geometry, for example for Earth, we add this picture to our project and set it to the geometry. It&#8217;s a bit like covering it with a blanket with a high percentage of elongation. We can imagine that by covering a sphere, we stretch the blanket on the equator more than on the polar caps. Because that, if you look on a map, the longitudes and latitudes are not parallel, but rather bent. In reality the longitude and latitude are parallel. You can see that on a globe. Fortunately for us a world map is already a perfect UV map for a sphere. Thanks to the website <a href="http://www.ginkgomaps.com">www.ginkgomaps.com</a> which supplies world maps to everyone. I used one of these maps in my example. You can customize the map with a graphic program. Then add it to the project and set it in the property.&nbsp;</p>



<pre class="wp-block-preformatted">Dim EarthGeometry As New SCNSphereMBS(1.47)  
EarthGeometry.segmentCount=100  
Dim Earth As New SCNNodeMBS(EarthGeometry)  
EarthGeometry.firstMaterial.diffuse.contents = EarthPic  
Earth.Position = New SCNVector3MBS(25, 0, 0)&nbsp;  
MyScene.rootNode.addChildNode(Earth)</pre>



<p>All other textures I draw myself in a graphic program.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="768" src="https://blog.xojo.com/wp-content/uploads/2020/02/Earth-1024x768.png" alt="" class="wp-image-6608" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/Earth-1024x768.png 1024w, https://blog.xojo.com/wp-content/uploads/2020/02/Earth-300x225.png 300w, https://blog.xojo.com/wp-content/uploads/2020/02/Earth-768x576.png 768w, https://blog.xojo.com/wp-content/uploads/2020/02/Earth.png 1424w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>For the position of the Planets, we must pay attention to the fact that the origin of the single planets are in the center of the sphere and we set in the constructor of the geometry as the radius and not the diameter. The distance between two planets are: radius of planet 1+radius of planet two+ space between them.&nbsp;</p>



<p>Following this same pattern we add the other planets. Saturn has a planetary ring. The ring is a tube with an inner radius that is bigger than the planet and a small hight. I use the same structure on the ring as on the planet. The tube is a bit rotated. We rotate the ring a bit by x and y. The specification of a rotation looks like this:&nbsp;</p>



<pre class="wp-block-preformatted">saturnRing.orientation = New SCNVector4MBS(-0.4, -0.5, 0, 1)</pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="558" height="386" src="https://blog.xojo.com/wp-content/uploads/2020/02/PicSaturn.png" alt="" class="wp-image-6609" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/PicSaturn.png 558w, https://blog.xojo.com/wp-content/uploads/2020/02/PicSaturn-300x208.png 300w" sizes="auto, (max-width: 558px) 100vw, 558px" /></figure>



<p><strong>Let&#8217;s Move the Solar System</strong></p>



<p>Now we want to move the Scene. We assume that the planets&#8217; orbits are all parallel to the xz plane and that they are exactly circular. To roate around a certain point, we create a geometry for each rotation. It lies in the point and is a parent node of the geometry. If a parent node moves, a child node moves too. The inverse does not apply. In that way, if we rotate the helping node in the origin, the child node moves around the origin too. We cannot use the Sun as the parent node for all planets because the planets are supposed to move at different speeds.&nbsp;</p>



<p>The creation of the geometry looks similar for each planet:</p>



<pre class="wp-block-preformatted">Dim UranusRotationGeometry As New SCNSphereMBS(1)  
Dim UranusRotation As New SCNNodeMBS(UranusRotationGeometry) 
UranusRotation.Position = New SCNVector3MBS(0, 0, 0)&nbsp; 
MyScene.rootNode.addChildNode(UranusRotation) </pre>



<pre class="wp-block-preformatted">UranusRotation.addChildNode(Uranus)&nbsp;</pre>



<p>These geometries are covered by the Sun.&nbsp;</p>



<p>Then we add the movements. We defined a rotation of the helping node and set the information about the rotation. We want to rotate around the y axis in each cycle about 360°. The information is given in the unit rad. Because of this we must convert 360° to 6.283 rad. The last parameter is about the speed of the operation. In this section we can set the proportion of the speed of the planets. The speed of Earth is the basic value. Everything is based on this value. The assumption is: an Earth year lasts 365 days. For each planet we use the number of Earth days a planet takes to rotate once around the Sun. We divide this value by the days of an Earth year. For Neptune we get a value that is approximate to 164.79 rad. That we can multiply with a variable. The variable can be set by the customer to regulate the speed of the solar system. We want to repeat this movement again and again. In this way we set it. In the last step we set this rotation to the scene. &nbsp;</p>



<pre class="wp-block-preformatted">Dim moveNeptune As SCNActionMBS = SCNActionMBS.rotateBy(0, 6.283, 0, 164.79 * speed)
Dim Neptunerepeat As SCNActionMBS = SCNActionMBS.repeatActionForever(moveNeptune)
NeptuneRotation.runAction(Neptunerepeat)</pre>



<p>Finally, we want to talk about lighting. The Sun is the light source. It is a light that comes from a point and shines in all directions. That type of light source is called an omni light. We define a light as a property from a node. Since our Sun is a node in the scene, we add the light property directly. All nodes that spray light don’t get any light and they are normally black. With the emission property we can make the sphere look like it is glowing. We choose yellow as color.&nbsp;</p>



<pre class="wp-block-preformatted">Dim SunGeometry As New SCNSphereMBS(13) 
Dim Sun As New SCNNodeMBS(SunGeometry) 
sun.Light = New SCNLightMBS 
sun.Light.Type = SCNLightMBS.SCNLightTypeOmni 
sun.Light.Intensity = 2000
sun.light.Color = NSColorMBS.whiteColor sun.Light.Intensity = 2000 SunGeometry.firstMaterial.emission.contents = NSColorMBS.yellowColor SunGeometry.segmentCount = 100 
Sun.Position = New SCNVector3MBS(0, 0, 0)&nbsp; 
MyScene.rootNode.addChildNode(Sun)</pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="766" src="https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem-1024x766.png" alt="" class="wp-image-6610" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem-1024x766.png 1024w, https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem-300x224.png 300w, https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem-768x574.png 768w, https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem.png 1514w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The scene seems very dark if the Sun is our only light source, so add weak ambient light that lights up all elements in the same way. The unit of the light intensity is lumen. Now you can run the project and admire your own programmed solar system. Have a lot of fun with that.&nbsp;Link to project.</p>



<p>If you have questions about SceneKit don’t hesitate to contact me. And please join my session about SceneKit at the <a href="https://www.xojo.com/xdc/">XOJO.CONNECT</a> conference in Nashville.</p>



<p>Download the <a href="https://blog.xojo.com/wp-content/uploads/2020/02/SolarSystem.zip">project</a>.</p>



<p><em>Stefanie Juchmes studies computer science at the University of Bonn. She came in touch with Xojo due to the work of her brother-in-law and got a junior developer position in early 2019 at<a rel="noreferrer noopener" href="https://www.monkeybreadsoftware.de/xojo/" target="_blank">&nbsp;Monkeybread Software.</a>&nbsp;You may have also read her articles in<a rel="noreferrer noopener" href="http://www.xdevmag.com/" target="_blank">&nbsp;Xojo Developer Magazine</a>.&nbsp;<br></em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Guest Post: Using the Graphics Class to Create PDF Documents</title>
		<link>https://blog.xojo.com/2019/05/23/using-the-graphics-class-to-create-pdf-documents/</link>
		
		<dc:creator><![CDATA[Christian Schmitz]]></dc:creator>
		<pubDate>Thu, 23 May 2019 16:49:12 +0000</pubDate>
				<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Monkeybread Software]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Plugins]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5769</guid>

					<description><![CDATA[Monkeybread Software started with the DynaPDF plugin for Xojo about twelve years ago. As DynaPDF is a C++ library, the wrapping plugin mimics the original&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Monkeybread Software started with the DynaPDF plugin for Xojo about twelve years ago. As DynaPDF is a C++ library, the wrapping plugin mimics the original C API and offers it for Xojo. Over the years a lot more convenient methods have been added to make the plugin more Xojo-like. For example, newer methods can process pictures directly, take colors as Xojo color values and allow drawing of styled text directly.</p>



<p>Since the early days there has been the feature request to use the graphics class in Xojo to draw to a PDF document. We recently came back to this old feature request and decided to try a new way to implement it and our new code seems to work just fine. With some help from Xojo engineers, we even got the alignment right.</p>



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



<p>At the Xojo Developer Conference 2019 in Miami in the presentation about news in MBS Xojo Plugin, Christian Schmitz presented this new feature. We can draw the normal drawing commands for lines, rectangles, polygons and pictures, but also text and even vector graphics. With the support of vector graphics, you can even use the report engine in Xojo and let it output your reports as PDF documents.</p>



<div class="wp-block-image"><figure class="aligncenter"><img loading="lazy" decoding="async" width="1240" height="1754" src="https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered4.png" alt="" class="wp-image-5789" srcset="https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered4.png 1240w, https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered4-212x300.png 212w, https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered4-768x1086.png 768w, https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered4-724x1024.png 724w" sizes="auto, (max-width: 1240px) 100vw, 1240px" /></figure></div>



<p>In your project, you can have a central draw(g as graphics) method, which handles drawing your content. For a print preview, you can let it draw to a picture and show the picture scaled down in a canvas. The same code can be called for drawing to a graphics object from printer received via OpenPrinterDialog function. And for saving as PDF, you can use the graphics object from DynaPDF. Just query PageGraphics object while you have a PDF page open.</p>



<p>Here is a code example:</p>


<blockquote>
<p>
<font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p><font face="courier new">
<p>Dim pdf As New DynapdfMBS<br>Dim f As FolderItem = SpecialFolder.Desktop.Child(&#8220;DynaPDF Graphics.pdf&#8221;)</p>
<p>// For this example you can use a Starter, Lite, Pro or Enterprise License<br>&#8216;pdf.SetLicenseKey &#8220;Starter&#8221;&nbsp;</p>
<p>// Create new PDF. Use f = nil for in-memory PDF<br>Call pdf.CreateNewPDF(f)</p>
<p>// append a new page, so we have an open page<br>Call pdf.Append&nbsp;</p>
<p>// get graphics object to draw on the page<br>Dim g As Graphics = pdf.PageGraphics</p>
<p>// draw as usual<br>g.DrawString &#8220;Hello World&#8221;, 105, 100<br>g.DrawRect 100, 80, 100, 100</p>
<p>// close page and file<br>Call pdf.EndPage&nbsp;<br>Call pdf.CloseFile</p>
<p>// for in-memory PDF, use GetBuffer here to grab it.<br>&#8216;Dim PDFData As String = pdf.GetBuffer</p>
</font><p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
</blockquote>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p><font face="courier new">
<p><font face="courier new"></font></p>
</font><p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>
<p><font face="courier new"></font></p>


<p>As you see, we use normal drawing commands for adding text to the page. A few lines are needed to setup the PDF environment and after drawing to properly close the file. If you like to customize the new PDF pages, you can implement NextPage event on DynaPDFMBS class and for example import an existing PDF document as letter paper for your background. You should also implement Error event to handle any problem while creating the PDF document.&nbsp;</p>



<div class="wp-block-image"><figure class="aligncenter"><img loading="lazy" decoding="async" width="1240" height="1754" src="https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered2.png" alt="" class="wp-image-5787" srcset="https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered2.png 1240w, https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered2-212x300.png 212w, https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered2-768x1086.png 768w, https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered2-724x1024.png 724w" sizes="auto, (max-width: 1240px) 100vw, 1240px" /></figure></div>



<p>Depending on your DynaPDF license, other features like rendering PDF Pages, importing of other PDF pages or digital signatures may be possible. But even with starter license, you can create new PDF documents and draw into them. If you have questions, please do not hesitate to contact Monkeybread Software. </p>



<div class="wp-block-image"><figure class="aligncenter"><img loading="lazy" decoding="async" width="1240" height="1754" src="https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered3.png" alt="" class="wp-image-5788" srcset="https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered3.png 1240w, https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered3-212x300.png 212w, https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered3-768x1086.png 768w, https://blog.xojo.com/wp-content/uploads/2019/05/DynaPDF-Graphics-Rendered3-724x1024.png 724w" sizes="auto, (max-width: 1240px) 100vw, 1240px" /></figure></div>



<p><em>Christian Schmitz has been active in the Xojo community for over 20 years. As the developer behind the Monkeybread Software Plugins he provides thousands of classes and example projects to help you build better applications with Xojo. In Europe, Christian has organized over 10 conferences, including the upcoming </em><a href="http://monkeybreadsoftware.com/conference"><em>conference</em></a><em> in Cologne this fall. You may have also read his articles in </em><a href="http://www.xdevmag.com"><em>Xojo Developer Magazine</em></a><em>. DynaPDF and other MBS plugins are available in the Xojo Add-Ons </em><a href="https://www.xojo.com/store/#addons"><em>Store</em></a><em> and at </em><a href="http://www.monkeybreadsoftware.de/xojo/"><em>Monkeybread Software</em></a><em>.<br></em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Updating Code That Used The Graphics Property</title>
		<link>https://blog.xojo.com/2018/12/06/updating-code-that-used-the-graphics-property/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 06 Dec 2018 20:54:35 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Canvas]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5224</guid>

					<description><![CDATA[Starting with Xojo 2018r3, this Graphics property was removed from Window and Canvas so if you had code that was still relying on it, that code will no longer compile. Here are some tips on how you can migrate your code to use the Paint event handlers and tell the Canvas to update with a call to Invalidate.]]></description>
										<content:encoded><![CDATA[<p>Prior to Xojo 2018r3 Window and Canvas both had a Graphics property that you could access and draw to. This was <a href="https://documentation.xojo.com/Resources:Deprecations">deprecated</a> in 2011 because it had significant performance issues on all platforms. The preferred way to draw your graphics since 2011 has been to use the <a title="Window.Paint" href="http://documentation.xojo.com/api/deprecated/window.html#window-paint">Window.Paint</a> or <a title="Canvas.Paint" href="http://documentation.xojo.com/topics/user_interface/desktop/desktop_controls/canvas.html#canvas-paint">Canvas.Paint</a> event handlers and the supplied parameter <i>g As Graphics</i>.</p>
<p>Starting with Xojo 2018r3, this Graphics property was removed from Window and Canvas so if you had code that was still relying on it, that code will no longer compile. Here are some tips on how you can migrate your code to use the Paint event handlers and tell the Canvas to update with a call to Invalidate.</p>
<p><span id="more-5224"></span></p>
<p>If your code was simple and just drawing a Picture to the Graphics property, then you would just move the code to the Paint event handler. For example, this code is drawing a picture:</p>
<pre>Canvas1.Graphics.DrawPicture(MyPic, 0, 0)</pre>
<p>Where that code existed, you would tell it to redraw Canvas1:</p>
<pre>Canvas1.Invalidate(False)</pre>
<p>And then in the Canvas.Paint event handler you would draw the picture:</p>
<pre>g.DrawPicture(MyPic, 0, 0)</pre>
<p>Related to this is another thing to keep in mind. Do not use this Graphics object (g) outside the lifetime of the Paint event. You can certainly pass the Graphics parameter from the Paint event to other methods, but you should not keep a reference of it in a property or elsewhere. When the Paint event eventually completes, this Graphics object is no longer valid and the copy you&#8217;ve saved in a property also becomes invalid. Attempting to use a saved Graphics object outside of the Paint event&#8217;s lifetime may raise an exception in future versions of Xojo.</p>
<p>For more information and other strategies to handle more advanced situations, refer to the topic in the documentation: <a href="http://documentation.xojo.com/topics/graphics/updating_code_that_used_the_graphics_property.html">Updating Code That Used the Graphics Property</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Drawing Objects in a Canvas with the Paint Event</title>
		<link>https://blog.xojo.com/2018/11/02/drawing-objects-in-a-canvas-with-the-paint-event/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Fri, 02 Nov 2018 16:28:21 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Canvas]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5102</guid>

					<description><![CDATA[The Canvas control is a great way to draw pretty much anything to a window. With a Canvas, do all your drawing in its Paint event handler for the best quality and performance.]]></description>
										<content:encoded><![CDATA[<p>The Canvas control is a great way to draw pretty much anything to a window. With a Canvas, do all your drawing in its Paint event handler for the best quality and performance.</p>
<p>I&#8217;ve had many people ask for an example for how to create a Canvas that allows you to:</p>
<ul>
<li>Draw pictures within it (as objects)</li>
<li>Move these objects</li>
<li>Remove them</li>
<li>Add labels to them</li>
<li>Programmatically select one</li>
</ul>
<p>This example demonstrates how to do all these things. It has a large Canvas on the window with several buttons that let you add and manage the objects on the Canvas.</p>
<p><span id="more-5102"></span></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5108" src="https://blog.xojo.com/wp-content/uploads/2018/11/2018-11-01_17-22-59.png" alt="" width="800" height="622" /></p>
<p>Use the SegmentControl to select the type of object you want to add to the Canvas and click the Add Object button.  You can optionally specify text to label the object using the field below the button.</p>
<p>Add as many objects as you want. You can click to select an object and it will have a black border drawn around it. You can drag any object within the Canvas.</p>
<p>The other buttons center or remove a selected object.  You can use the Select Object # button to select the object number you specify (objects are numbered starting at 0).</p>
<h2>About the Project</h2>
<p>The concept is pretty simple. Essentially you have a class that represents objects to draw on the Canvas and that knows how to draw itself on a Canvas.</p>
<p>In this project, the <b>CanvasObject</b> class represents an object to draw on the Canvas. It contains everything it needs to know to draw itself, such as its coordinates, label text, the icon to display and other properties.</p>
<p>The <b>ObjectContainerCanvas</b> class is a subclass of Canvas that is responsible for all the drawing, moving and removing of CanvasObjects. This class has an array of CanvasObjects that it knows about. The objects in this array are drawn by the Canvas Paint event handler when appropriate by calling the Draw method on the object itself.</p>
<p>To allow you to drag an object within the Canvas, the MouseDrag event handler is used. It knows what the currently selected CanvasObject is and as you drag the mouse, it updates the coordinates for the CanvasObject.</p>
<p>When the Canvas is told to update itself, usually through a call to Invalidate, the Paint event is called. Here each CanvasObject in the array is drawn on the screen.  This is the Paint event:</p>
<pre>If Background &lt;&gt; Nil Then
  g.DrawPicture(Background, 0, 0)
End If

For Each co As CanvasObject In mCanvasObjects
  co.Draw(g)
Next</pre>
<p>The CanvasObject&#8217;s Draw method draws itself at its coordinates and also draws a selection rectangle around itself if it is selected. This is the Draw method:</p>
<pre>// Draws the object on the canvas.
g.DrawPicture(Image, Left, Top)

If Selected Then
  Const kBorder = 2
  // Draw selection rectangel around the image
  g.PenHeight = kBorder
  g.PenWidth = kBorder
  g.ForeColor = TextColor
  g.DrawRect(Left - kBorder, Top - kBorder, Width + kBorder * 2, Height + kBorder * 2)
End If</pre>
<p>In addition, ObjectContainerCanvas has two events that are called when an object is selected (ObjectSelected) and when an object is moved (ObjectMoved).</p>
<p><a href="http://files.xojo.com/BlogExamples/ObjectsInCanvas.zip">Download the ObjectsInCanvas example</a>.</p>
<p>Check out the other methods on ObjectContainerCanvas that are used to add, move, remove and select objects. I hope you find this technique useful in your projects.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Create Your Own ImageWell Based on Canvas</title>
		<link>https://blog.xojo.com/2018/05/07/create-your-own-imagewell-based-on-canvas/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 07 May 2018 10:00:26 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Canvas]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[Xojo Framework]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=4179</guid>

					<description><![CDATA[Whether you are using Xojo to create your very first application or if you are coming from other languages, like C# or VisualBasic, customized UI controls are probably one of those things you have in your to-do list. For multiplatform Desktop apps, you will find that the Canvas class offers everything you need.]]></description>
										<content:encoded><![CDATA[<p>Whether you are using Xojo to create your very first application or if you are coming from other languages, like <strong>C#</strong> or <strong>VisualBasic</strong>, customized UI controls are probably one of those things you have in your to-do list. For multiplatform Desktop apps, you will find that the <a href="http://developer.xojo.com/canvas"><b>Canvas</b></a> class offers everything you need. In order to show you how easy it can be, follow this tutorial to recreate the <a href="http://developer.xojo.com/imagewell"><b>ImageWell</b></a> UI class control, provided by default in the Xojo framework. Our customized ImageWell will be able to proportionally display any JPEG file dropped by the user on the control, centering it on the available surface.<span id="more-4179"></span></p>
<p>Along the way, we also will see how the Xojo IDE simplifies making subclass properties available from the Inspector Panel, so when using their instances we can set some attributes as the background color, pen size or border color in a more convenient way.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-4182 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2018/04/MyImageWellFinal.png" alt="" width="712" height="534" />As usual, the first step to create a new subclass is adding a new class item to the Desktop project (Insert &gt; Class). With the new class item selected, change its name to something descriptive. For this example we will use <code>MyImageWell</code>. The most important thing here is setting <code>Canvas</code> as its <b>Super</b> attribute. That means that the subclass will be based on the <b>Canvas</b> class, inheriting all its properties, Events and Methods so they will also be available for the subclass.</p>
<p>One of these inherited Events is <b>Open</b>, and we will implement it using the Event Handler option (click the <strong>+</strong> button in the toolbar to access the dropdown menu) in order to inform the class that we want to accept the dropped JPEG files. This is done with the following line of code in the Open Event Handler:</p>
<p><code>Me.AcceptFileDrop("img/jpeg")</code></p>
<p>Obviously, we can extend this support to accept other Xojo compatible graphical formats. For that, we would add a new <a href="http://developer.xojo.com/userguide/using-file-type-sets"><b>File Type Set</b></a> to the project, using it as the filter in the previous line of code.</p>
<p>Once we inform the class that we accept this feature, the next step is implementing the <b>DropObject</b> Event Handler that fires once this action is detected inside the limits of the control. The code we need to write for this Event Handler will test that the <code>obj</code> parameter passed along contains a valid <b>FolderItem</b> and, in that case, we will load such file as a new <b>Picture</b> object, assigning it to a property of the same Type. The code for the event is:</p>
<pre>If obj.FolderItemAvailable Then
  image = Picture.Open(obj.FolderItem)
  Invalidate
End If</pre>
<p>Don&#8217;t forget to add the <code>Image</code> computed property to the Class using Insert &gt; Computed Property while the <code>MyImageWell</code> item is still selected, and using these values:</p>
<ul>
<li><b>Name</b>: Image</li>
<li><b>Type</b>: Picture</li>
<li><b>Scope</b>: Public</li>
</ul>
<p>As you can see, the amount of code we need to load the file as a Picture object and to assign it to the class property is minimal! Why do we use the <b>Invalidate</b> method call afterwards? Well, this is responsible for informing the operating system to redraw the instance when it has a chance. And when this happens it will fire the third and last Event we need to implement: <b>Paint. </b>Here is where we can instruct any Canvas based control how to draw itself through the graphical context represented by the <strong><code>g</code></strong> parameter passed along the Event.</p>
<h2>Painting the control</h2>
<p>Once we&#8217;ve added the <b>Paint</b> Event to the class and before writing the code responible of painting the dropped image inside its limits, we need to add three additional computed properties. We will use them to set some attributes like the color we want to use to paint the control background, the border color and even the width of the border:</p>
<ul>
<li><code>BackGroundColor As Color = &amp;cdddddd</code></li>
<li><code>BorderColor As Color = &amp;c000000</code></li>
<li><code>PenSize as Integer = 2</code></li>
</ul>
<p>Add to the Setter method on every computed property the sentence me.invalidate; so every time we assign a new value to them… the control will be redrawn using the new value (background color, border color, pen size or even a new assigned picture).</p>
<p>The last step is writing the code responsible for drawing the control itself: filling the background with the set color, then drawing proportionally (and centered) the loaded picture pointed by the <code>Image</code> property, and finally drawing the border with the width and color specified. All of this is what we can do using the following snippet of code:</p>
<pre>// We fill the control background using the set color
g.DrawingColor = BackgroundColor
g.FillRectangle(0,0,g.Width,g.Height)

// If we have a valid image object, then we draw it centered and scaled (if necessary)
If image &lt;&gt; Nil Then 
  Var Height, Width As Integer
  Var sourcey, sourcex As Integer = 0 
  If image.Height &gt; image.Width Then
    Height = Me.Height
    Width = (Me.Height * image.Width) / image.Height
    sourcey = (Me.Width - Width) / 2
  Else
    Width = Me.Width
    Height = (Me.Width * image.Height) / image.Width
    sourcex = (Me.Height - Height) / 2
  End If

  // This is the line that actually draws a picture inside the graphic context of our instance
  g.DrawPicture(image,sourcey,sourcex,Width,Height,0,0,image.Width,image.Height)
End If

// We draw the control border
g.PenSize = me.PenSize
g.DrawingColor = BorderColor

g.DrawRectangle(0,0,Me.Width,Me.Height)</pre>
<p>As you can see, the code needed for this is also very simple!</p>
<h2>Make the properties visible from the Inspector Panel</h2>
<p>While we are on it, we can use the <b>Inspector Behavior</b> feature to make our specific properties visible through the Inspector Panel. This way, when we add new instances from the subclass to the layout of any window, we will be able to easily set their values directly from the Inspector Panel. With the <code>MyImageWell</code> item still selected in the Project Browser, use the contextual menu to select the <b>Inspector Behavior</b> option to access the following Window:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-4180 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2018/04/InspectorBehavior.jpg" alt="" width="721" height="459" /></p>
<p>Here you will see all the Class properties, those common to all <b>Canvas</b> derived subclasses and also the ones added for us and that are specific to our class. You can find these properties listed under the <b>Behavior</b> section. To make them visible in the Inspector Panel we just need to check their associated checkboxes; and even modify their default values editing the associated cell if we want to.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-4181 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2018/04/InspectorPanelOwnClass.png" alt="" width="322" height="257" /></p>
<p>Now, we just need to drag and drop the <code>MyImageWell</code> item from the Project Browser into any Window Design Layout in order to add new instances! Once we run the example project, we will see how the controls react to displaying any JPEG picture dropped on it.</p>
<p>If you want, you can investigate deeper into the methods provided by the <a href="http://developer.xojo.com/graphics"><b>Graphics</b></a> class in order to make the control more glittery or more sophisticated.</p>
<p>You can watch <a href="https://www.youtube.com/watch?v=val_Bcgw_4U">this video</a> (en español) to see this in action:</p>
<p><em>Javier Rodri­guez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages <a href="http://www.aprendexojo.com">AprendeXojo.com</a> and is the developer behind the GuancheMOS plug-in for Xojo Developers, Markdown Parser for Xojo, HTMLColorizer for Xojo and the Snippery app, among others</em></p>
<p>*<a href="https://www.aprendexojo.com/2018/04/crea-tu-propio-imagewell-con-canvas/">Read this post in Spanish</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>ContainerControl: Making a Multiplatform Search Field</title>
		<link>https://blog.xojo.com/2017/04/26/containercontrol-making-a-multiplatform-search-field/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 26 Apr 2017 18:16:47 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[AprendeXojo]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=2596</guid>

					<description><![CDATA[Create the basis of a multiplatform search field based on the ContainerControl class for Desktop and Web apps.]]></description>
										<content:encoded><![CDATA[<p>The ContainerControl is one of the most versatile control classes included in the Xojo framework both for Desktop and Web apps. In fact, it paves the way to complex UI controls creation with the same simplicity you are used to while designing your window layouts. Even better, once you create your complex UI controls using the ContainerControl, you will be able to add them to your Window layouts as if they were regular controls. Plus, you will enjoy the fruits of better OOP encapsulation and the fact that you can create and use the controls dynamically at run time. Want to see this in action? Follow this tutorial and video to create the basis of a multiplatform search field based on the ContainerControl class.<span id="more-2596"></span></p>
<p>The following tutorial is based on the Desktop Xojo project that you can <a href="https://www.dropbox.com/s/hwr2ehikiz41vop/Xojo-Search%20Control.zip?dl=1">download from this link</a>. In fact, this project was the foundation to the search filed control implemented in the <a href="http://www.aprendexojo.com/software/snippery/">Snippery</a> app. Thus, you can envision in more detail the kind of functionality you can achieve when used in a real app. Ok, maybe you are thinking &#8220;this is not the native control a user expects when using a true native app under certain OS&#8221;. That&#8217;s true; anyway there are a lot of apps around (some of them from the big players) that use non-native controls in favour of providing a unified UI between all supported platforms. This is the case of the final class exposed here, offering the same aspect and behaviour when running under macOS, Windows and Linux.</p>
<h2>Preparing the Ingredients</h2>
<p>In order to create our multiplatform search control we need to use a series of components (classes) that will cooperate with each other: a <a href="http://blog.xojo.com/2017/02/06/textfield-getting-the-user-input/">TextField</a> that will receive the user keyboard input (that is, where the user inputs the text to search); a Canvas subclass to display the typical magnifying glass icon and other decoration for the control (that also extends further to add more functionality); and a second Canvas subclass that will offer the classic &#8220;search text clean&#8221; widget functionality normally presented at the right of a search field.</p>
<p>Of course, you can create a search field using these classes as individual items on a Window layout, but in that case all the resizing operations and cooperation between the controls will be more messy &#8212; losing the encapsulation that a ContainerControl provides to the other components of the application as if it was a unique, simple control.</p>
<h2>Dealing with the Graphics</h2>
<p>The resulting control uses three pictures for a total of two functions: one for the magnifying glass and two for the &#8220;text cleaning&#8221; widget that will be displayed only when the TextField has text on it. The widget has to change its image when the pointer is on it so the user can see that this is an active &#8220;clickable&#8221; control.</p>
<p>Fortunately Xojo eases the management of multiresolution pictures in our apps, changing on the fly between the existing regular/normal resolution and the <a href="http://developer.xojo.com/hidpi-support">HiDPI/Retina</a> versions for the same given picture. Thus, we only need to use our favourite graphics editor app to draw and export the pictures with the required quality as PNG files (personally I use the <a href="https://www.sketchapp.com/">Sketch</a> on macOS).</p>
<p>In order for Xojo to be able to do its magic, you shouldn&#8217;t import the pictures to the app by dragging them from disk and dropping them on the Project Browser or Xojo will import the pictures as an alias. Instead, use the Insert &gt; Image option to add an Image instance to the project, showing the associated Editor where you&#8217;ll be able to assign every picture file for the supported resolutions of a same graphic. Of course the label you use as the Image name on the Inspector Panel will be the name you use to reference the Image from code or when assigned to other controls properties. If you explore the example project for this tutorial, you can see the three Images used: searchIcon, CloseSelected and Close in regular and HiDPI/Retina resolutions.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-2597 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2017/04/Image-Xojo.png" alt="" width="621" height="716" /></p>
<h2>Creating the Text Cleaning Widget</h2>
<p>We have already seen in a <a href="http://www.aprendexojo.com/2016/10/canvas-crea-tus-propios-controles/">previous tutorial</a> (in Spanish) how easy it is to create custom graphic controls in Xojo based on the Canvas Class. In order to create the widget providing the search text cleaning feature, we will follow that same principle here:</p>
<ul>
<li>Add a Canvas subclass and name it CloseButtonClean.</li>
<li>Add the Open, MouseEnter and MouseExit events to the subclass</li>
<li>Type the following code into the Open event, basically to assign the picture showing its initial state and making it invisible:</li>
</ul>
<pre>me.Backdrop = close
me.Visible = false</pre>
<ul>
<li>We will use the MouseEnter and MouseExit events to change the displayed picture in response to  the pointer cursor being inside or outside the limits of the control; showing that this is an active/clickable control. Put the following line of code in the MouseEnter event:</li>
</ul>
<pre>me.Backdrop = CloseSelected</pre>
<ul>
<li>And the following one in the MouseExit event of the control:</li>
</ul>
<pre>me.Backdrop = close</pre>
<p>We have completed the decoration of our little class, but it is also desirable to provide an external interface so other controls can easily change the state of the widget. We will do that by adding two methods to the class.</p>
<p>With the widget class still selected on the Project Browser, select the Insert &gt; Method option twice to add two Methods and using the Inspector Panel to change the Method names to &#8220;Activate&#8221; and &#8220;Deactivate&#8221;, respectively. Leave the Scope as Public for both methods, so they are reachable by other objects and not only those created from the class.</p>
<p>The select method simply changes the control visibility to True:</p>
<pre>me.Visible = true</pre>
<p>While the Deactivate method will do the opposite action:</p>
<pre>me.Visible = false
me.Backdrop = Close</pre>
<h2>Drawing the Search Control</h2>
<p>The second of the required classes based on the Canvas class is no more complex. In this case we will not assign a picture to the Backdrop property of the Canvas, instead we will use the Paint event to directly draw the decoration, including the magnifying glass picture at the appropriate coordinates of the control.</p>
<p>So, after adding a second Canvas subclass to the project —named cSearchBackground in our Example project—, we just need to add the Paint event to it, writing the following lines of code on the associated Code Editor:</p>
<pre>g.PenWidth = 1
g.PenWidth = 1
g.ForeColor = &amp;caaaaaa
g.DrawRoundRect(0,0,g.Width,g.Height,5,5)
g.ForeColor = &amp;cffffff
g.FillRoundRect(1,1,g.Width-2, g.Height-2,5,5)
dim midY as integer = (g.Height/2) - (searchIcon.Graphics.Height/2)
g.DrawPicture(searchIcon,5,midy)</pre>
<p>In essence, we are drawing the control border using the provided foreground color (&amp;caaaaaa, in hex notation), and filling the control background with the white color. After that, we will paint the magnifying glass icon using the DrawPicture method of the Graphic class provided as the drawing context for the Paint event.</p>
<h2>Container Control: Putting it all Together</h2>
<p>Once we have all the required items for our &#8220;complex&#8221; UI control, it&#8217;s time to add a ContainerControl to the project using the Insert &gt; ContainerControl option. The first thing you probably notice is that the Layout Editor is very similar to the one used for designing the windows of the app. After all, the ContainerControl is about adding, resizing and aligning several UI controls on it, as you do when designing a window.</p>
<p>With the added ContainerControl still selected, change the attribute Name to ContainerSearchField on the associated Inspector Panel.</p>
<p>Now we just need to add an instance of our cSearchBackground class to the ContainerControl, a TextField control from the Xojo Library Panel and our search text cancelation widget class to the right of the just added TextField. The final layout of the control should be something similar to this (after adjusting the own Container Control height and width):</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-2598 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2017/04/ContainerControl.png" alt="" width="475" height="179" /></p>
<p>In order to correctly draw the control background when resizing the ContainerControl, select the cSearchBackground instance and add the Open event with the following line of code:</p>
<pre>me.Width = self.Width</pre>
<p>In addition, we also want that the TextField to show our search text cancellation widget only if the TextField has text on it. Select the TextField instance on the ContainerControl (searchField in the example project), and add the TextChange event with the following code in the associated Code Editor:</p>
<pre>if me.Text &lt;&gt; "" then
  CloseButtonClean1.activate
else
  CloseButtonClean1.deactivate
end if</pre>
<p>With the TextField still selected, set the CueText property under the Initial State section of the Inspector Panel to &#8220;Search&#8221;. This will be the text shown by default when the TextField is empty.</p>
<p>Of course we want to add functionality to the instance of our search text cancelation widget —named CloseButtonClean1 in the example project—. Add the MouseDown event and write the following line of code on the associated Code Editor:</p>
<pre>searchField.Text = ""</pre>
<p>When using a ContainerControl you will want to provide a way to resize every control inside of it in response to the resizing of the ContainerControl itself. We resolve this by adding the doResize method to our Container Control with the following code:</p>
<pre>closeButtonClean1.Left = me.Width - 24

searchField.Width = (Me.Width - 27) - searchField.Left

cSearchBackground1.Width = me.Width

cSearchBackground1.Invalidate</pre>
<p>As you can see this method simply does some calculations to reposition the controls based on their relative coordinates, updating also the width of the background control to reflect the same width of the ContainerControl itself. Finally it calls the invalidate method on the background instance class so the control can update the drawing.</p>
<p>In order to finish our ContainerControl subclass, we just need to add a couple of events: Open and Resizing. The first will be in charge of setting the initial state for the control, while the second will call the doResize method every time the ContainerControl is resized.</p>
<p>Once you&#8217;ve added these events, select them and simply write the call to the doResize method in both cases.</p>
<h2>Using the SearchField ContainerControl</h2>
<p><img loading="lazy" decoding="async" class="size-full wp-image-2599 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2017/04/Control-Container-Search-en-uso-1024x605.png" alt="" width="1024" height="605" /></p>
<p>That&#8217;s all! You can start using the control by dragging it from the project browser to the Window Layout in order to create a new instance. Of course, we have not implemented the search functionality itself in this example project, mainly because it depends of the purpose of the final application itself. In addition, it would be easy for you to add extra functionality as <a href="http://blog.xojo.com/2016/08/10/textfield-with-autocomplete/">text autocompletion</a> as we have seen in a previous tutorial.</p>
<p><em>Javier Rodri­guez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages <a href="http://www.aprendexojo.com">AprendeXojo.com</a> and is the developer behind the GuancheMOS plug-in for Xojo Developers and the Snippery app, among others.</em></p>
<p>*<a href="http://www.aprendexojo.com/2017/04/container-control-en-xojo/">Read this post in Spanish</a></p>
<p>*<a href="https://youtu.be/qC-EFl6xW9A">Watch the video in Spanish</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Windows Graphics: Direct2D/DirectWrite Direction</title>
		<link>https://blog.xojo.com/2017/04/12/windows-graphics-direct2ddirectwrite-direction/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Wed, 12 Apr 2017 17:51:49 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Direct2D]]></category>
		<category><![CDATA[DirectWrite]]></category>
		<category><![CDATA[GDI]]></category>
		<category><![CDATA[Graphics]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=2560</guid>

					<description><![CDATA[Xojo 2016r4 we switched our main graphics rendering engine on Windows from GDI and GDI+ to Direct2D/DirectWrite learn more about why we made this change and how it effects you.]]></description>
										<content:encoded><![CDATA[<p>In Xojo 2016 Release 4 we switched our main graphics rendering engine on Windows from GDI and GDI+ to Direct2D/DirectWrite. Direct2D/DirectWrite was first introduced by Microsoft in Windows 7, with support in Vista via a Platform Update. It is (or was at the time) Microsoft&#8217;s new high-performance 2D vector Graphics API.</p>
<p><span id="more-2560"></span></p>
<h2><strong>The transition GDI to GDI+ to Direct2D</strong></h2>
<p>GDI is another Graphics API that was present in the initial release of Windows and to this day remains an integral part of the OS. However, since GDI is such old technology it lacks basic anti-aliasing support, alpha channel support, and still deals in integer coordinates. GDI+ was introduced in Windows XP and included everything missing from GDI, with one glaring issue, text rendering. While the appearance itself is slightly different (one of the original reasons why even with App.UseGDIPlus enabled Xojo still rendered DrawStrings using GDI text rendering), but also because of the additional text processing and resolution independence capabilities in GDI+, text rendering is performed by the CPU.</p>
<p>Direct2D/DirectWrite solves all those issues, and best of all it can still interoperate with GDI code which is important for Xojo Plugin developers and other parts of Xojo that still rely on a GDI graphics context (i.e. StyledTextPrinter and theme drawing). Without Direct2D/DirectWrite Xojo could not completely support HiDPI effectively. The main issue was text rendering in the code editor and swithing to GDI+ text rendering was deemed too slow. Other benefits of Direct2D/DirectWrite include: hardware acceleration, low CPU usage, improved text rendering and scaling.</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-2566" src="https://blog.xojo.com/wp-content/uploads/2017/04/Direct2D.png" alt="" width="600" height="600" /></p>
<h2><strong>Consequences of the transition</strong></h2>
<p>While new technology solves many immediate and future problems, it can also introduce some growing pains. For example, Microsoft didn&#8217;t introduce a printing API for Direct2D until Windows 8 (which was thankfully backported to Windows 7 via a Platform Update). This printing API has limited Xojo&#8217;s resolution setting among other things. Also, even though Direct2D can interoperate with GDI, this is not without some effort as Plugin developers have come to realize, especially when it comes to printing. For example, StyledTextPrinter is currently using an OS API that still takes a GDI graphics context (good luck getting Microsoft to update this control&#8217;s API) which now renders output as a scaled picture with how interoperating works. Other differences in rendering may be noticeable but these are likely just a difference in the graphics rendering APIs. While some consequences may be solved as time/features permit, some may be here to stay. We&#8217;ve fully embraced Direct2D/DirectWrite as our new graphics rendering engine and hope you will too.</p>
<h2><strong>Additional resources</strong></h2>
<p>While our framework attempts to guard one from having to learn about the underlying technology, it is still beneficial to understand why, at times, we need to make these changes. With that in mind, here&#8217;s some additional resources for those curious to learn more:</p>
<p><a href="https://channel9.msdn.com/blogs/pdc2008/pc18">Windows 7: Introducing Direct2D and DirectWrite</a></p>
<p><a href="https://en.wikipedia.org/wiki/Graphics_Device_Interface">GDI/GDI+</a></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
