<?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>FolderItem &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/folderitem/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Thu, 28 Aug 2025 14:55:07 +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>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>Dragging to More Destinations</title>
		<link>https://blog.xojo.com/2025/03/25/dragging-to-more-destinations/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 15:33:28 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[2025r1]]></category>
		<category><![CDATA[Drag and Drop]]></category>
		<category><![CDATA[DragItem]]></category>
		<category><![CDATA[FolderItem]]></category>
		<category><![CDATA[RawData]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14626</guid>

					<description><![CDATA[It’s been a common complaint that on macOS you could not get the Destination of a FolderItem drag. That was then, but this is 2025r1&#8230;]]></description>
										<content:encoded><![CDATA[
<p>It’s been a common complaint that on macOS you could not get the Destination of a FolderItem drag. That was then, but this is 2025r1 and now dragging finally knows where it’s going, and it&#8217;s happy to reveal its Destination!</p>



<h2 class="wp-block-heading">The History</h2>



<p>While we’ve offered an API to get the Destination of a DragItem, it has been returning Nil on macOS for quite some time. In fact, it likely hasn’t worked since our transition from Carbon to Cocoa way back in the day. Amid all the API changes that came with that transition, DragItem.Destination was unfortunately left behind.</p>



<h2 class="wp-block-heading">A New Way to FolderItem Drag</h2>



<p>To avoid breaking existing code, we chose not to overhaul our entire drag-and-drop system just to support this feature. Instead, we’ve made a few simple additions that are necessary to get FolderItem drags to return a valid DragItem.Destination</p>



<p>Here’s how a FolderItem drag would currently be setup (for example in the DesktopWindow.MouseDown event):</p>



<pre class="wp-block-code"><code>Var fileToCopy As FolderItem = SpecialFolder.Temporary.Child("Test")
Var item As New DragItem(Self, 0, 0, 100, 100)
item.FolderItem = fileToCopy
item.Drag</code></pre>



<p>After dropping the item at its Destination, checking item.Destination would always return Nil:</p>



<pre class="wp-block-code"><code>If item.Destination = Nil Then
    MessageBox "Not a happy destination. &#x1f614;"
End If</code></pre>



<p>By making one simple addition and using the RawData API, we can now initiate FolderItem drags in a way that correctly returns a valid FolderItem.Destination.</p>



<pre class="wp-block-code"><code>Var fileToCopy As FolderItem = SpecialFolder.Temporary.Child("Test")
Var item As New DragItem(Self, 0, 0, 100, 100)
item.FolderItem = fileToCopy
item.RawData("public.file-url") = ""
item.Drag</code></pre>



<p>Now, when you check the Destination after the drag is complete, you&#8217;ll receive something much more meaningful:</p>



<pre class="wp-block-code"><code>If item.Destination &lt;&gt; Nil And item.Destination IsA FolderItem Then
    MessageBox(FolderItem(item.Destination).NativePath)
End If</code></pre>



<h2 class="wp-block-heading">An Added Benefit</h2>



<p>While this change is a big improvement, why stop there? In the past, you could only drag FolderItems to the Destination, and the entire contents of that FolderItem would be copied over. With the addition of this new dragging method, you can now assign content to&nbsp;<code>RawData("public.file-url")</code>. Instead of copying the entire FolderItem to the Destination, we’ll copy the content from the RawData&nbsp;instead.</p>



<p>Here&#8217;s how you could set it up:</p>



<pre class="wp-block-code"><code>// The fileToCopy does not need to exist, we'll simply
// pull the file name from it and create the file at
// the destination with the new content that is assigned
// to the RawData.
Var fileToCopy As FolderItem = SpecialFolder.Temporary.Child("DummyFile.txt")
Var item As New DragItem(Self, 0, 0, 100, 100)
item.FolderItem = fileToCopy
item.RawData("public.file-url") = "Content that will be written to the destination file."
item.Drag</code></pre>



<h2 class="wp-block-heading"><strong>Conclusion</strong></h2>



<p>With these enhancements, dragging FolderItems on macOS has become more flexible and powerful than ever. Not only can you now easily retrieve a valid&nbsp;<code>Destination</code>, but you also have the power to control the content being copied, thanks to the integration with the&nbsp;<code>RawData</code>&nbsp;API. </p>



<p>So, go ahead—drag that FolderItem and show us your destination!</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>Using the Zip &#038; Unzip Feature</title>
		<link>https://blog.xojo.com/2023/10/10/using-the-zip-unzip-feature/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 10 Oct 2023 13:30:08 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[2023r3]]></category>
		<category><![CDATA[Compression]]></category>
		<category><![CDATA[FolderItem]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Unzip]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<category><![CDATA[Zip]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12107</guid>

					<description><![CDATA[FolderItem has been extended with new methods to Zip and Unzip files and folders in Xojo 2023 Release 3. Take a peek as we look at how easy it is to use this new feature.]]></description>
										<content:encoded><![CDATA[
<p>FolderItem has been extended with new methods to Zip and Unzip files and folders in Xojo 2023 Release 3. Take a peek as we look at how easy it is to use this new feature.</p>



<h3 class="wp-block-heading">What is New?</h3>



<p>Xojo 2023r3 adds new FolderItem.Zip and FolderItem.Unzip methods with support for the most widely used DEFLATE compression format.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<ul class="wp-block-list">
<li>Zip(destination As FolderItem, contentsOnly As Boolean = False, compression As ZipCompressions = ZipCompressions.Normal) As FolderItem</li>



<li>Zip(contentsOnly As Boolean = False, compression As ZipCompressions = ZipCompressions.Normal) As FolderItem</li>



<li>Unzip()</li>



<li>Unzip(destinationFolder As FolderItem)</li>
</ul>
</blockquote>



<h3 class="wp-block-heading">How to Zip</h3>



<p>Here&#8217;s an example of zipping SomeFolder on your Desktop:</p>



<pre class="wp-block-code"><code>Var someFolder As FolderItem = SpecialFolder.Desktop.Child("SomeFolder")
Var outputFile As FolderItem = someFolder.Zip</code></pre>



<p>The outputFile will be created on your Desktop with the name &#8220;SomeFolder.zip&#8221;.<br>This zip file will contain a single folder called SomeFolder, along with the contents of that folder.</p>



<pre class="wp-block-code"><code>+- SomeFolder.zip
  +- SomeFolder
    +- File1.ext
    +- File2.ext
    +- etc.</code></pre>



<p>If you&#8217;d rather just zip up the contents of SomeFolder then you can pass True to the contentsOnly parameter.</p>



<pre class="wp-block-code"><code>Var outputFile As FolderItem = myFolder.Zip(True)</code></pre>



<p>Now the zip file only contains the contents of the SomeFolder folder.</p>



<pre class="wp-block-code"><code>+- SomeFolder.zip
  +- File1.ext
  +- File2.ext
  +- etc.
</code></pre>



<p><em>Note: on macOS, when the OS unzips this kind of zip folder hierarchy, it will automatically create a folder with the contents, regardless of what the actual zip hierarchy looks like. However, this does not affect our own FolderItem.Unzip method.</em></p>



<p>With the overloaded Zip method that takes a destination FolderItem, you can use this to specify where the zip file is created.</p>



<pre class="wp-block-code"><code>Var destinationFolder As FolderItem = SpecialFolder.Documents
Var outputFile As FolderItem = myFolder.Zip(destinationFolder)</code></pre>



<p>In this case the outputFile is created in the user&#8217;s Documents folder. If you wanted to rename it to something other than the default name with a &#8220;.zip&#8221; appended to it, you can also use this syntax to pass a destination file instead of a destination folder.</p>



<pre class="wp-block-code"><code>Var destinationFile As FolderItem = SpecialFolder.Desktop.Child("MyZipFile.zext")
Var outputFile As FolderItem = myFolder.Zip(destinationFile)</code></pre>



<p>While we only demonstrated how to zip a folder in these examples, the exact same syntax applies for zipping a single FolderItem file too.</p>



<h3 class="wp-block-heading">How to Unzip</h3>



<p>Conversely, if you wanted to unzip a file, this is a simple call to FolderItem.Unzip</p>



<pre class="wp-block-code"><code>outputFile.Unzip</code></pre>



<p>This unzips the outputFile contents to the same directory that the outputFile resides in.  If you wanted to unzip the contents to a different location, pass in a destination folder instead:</p>



<pre class="wp-block-code"><code>outputFile.Unzip(SpecialFolder.Temporary)</code></pre>



<p>This feature is not yet supported in Android. In conclusion, Zipping/Unzipping has never been easier!  Learn more in the Xojo Programming Documentation &#8211; <a href="https://documentation.xojo.com/api/files/folderitem.html#folderitem-zip">Zip</a> and <a href="https://documentation.xojo.com/api/files/folderitem.html#folderitem-unzip">UnZip</a>. (<em>Thanks in part to zlib</em>)</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>



<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>Auto-Deleting Temporary Files</title>
		<link>https://blog.xojo.com/2021/03/11/auto-deleting-temporary-files/</link>
		
		<dc:creator><![CDATA[Greg O'Lone]]></dc:creator>
		<pubDate>Thu, 11 Mar 2021 10:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[FolderItem]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7212</guid>

					<description><![CDATA[Did you know that you can make temporary FolderItems that automatically delete when they go out of scope? This technique makes it fairly easy. ]]></description>
										<content:encoded><![CDATA[
<p>Did you know that you can make temporary FolderItems that automatically delete when they go out of scope? This technique makes it fairly easy. So let&#8217;s get to it.</p>



<ol class="wp-block-list"><li>Add a class to your project and name it <strong>TempFolderItem</strong>.</li><li>Add a <strong>Private</strong> property to the class named <strong>mFolderItem</strong> with a type of <strong>FolderItem</strong>.</li><li>Add a Method to the class named <strong>Constructor</strong>.</li><li>In the method, add the following code:<br><code>mFolderItem = FolderItem.TemporaryFile()</code></li><li>Add a Method to the class named <strong>Destructor</strong>.</li><li>In the method, add the following code:<br><code>mFolderItem.Delete</code></li><li>Add a new Method to the class named <strong>Operator_Convert</strong> with a return type of <strong>FolderItem</strong>.</li><li>In the method, add the following code:<br><code>Return mFolderItem</code></li></ol>



<p>That&#8217;s it! Now when you need a temporary file, create one of these objects like this:</p>



<p><code>Var myTempFile as New TempFolderItem</code></p>



<p>The Operator_Convert method makes it so you can use this object in any place where a FolderItem is expected and as soon as myTempFile goes out of scope, *POOF* the file disappears (assuming of course that no other process has locked the file).</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tip: Temporary FolderItems</title>
		<link>https://blog.xojo.com/2020/09/23/tip-temporary-folderitems/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 23 Sep 2020 20:54:54 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[FolderItem]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7494</guid>

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

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

    If Not mFile.IsFolder Then

    mfile.Remove

  End

End If

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

Try

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

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


<p>Questions? Ask me about Xojo programming on Twitter <a href="https://twitter.com/xojoes">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary">Xojo Forum</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Recursion: Emptying a Folder</title>
		<link>https://blog.xojo.com/2019/02/04/recursion-emptying-a-folder/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 04 Feb 2019 10:00:38 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[AprendeXojo]]></category>
		<category><![CDATA[FolderItem]]></category>
		<category><![CDATA[Recursiveness]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5363</guid>

					<description><![CDATA[Do you need code to delete the files and folders from the selected folder? In that case, there is a technique I propose to you and that is based on the recursivity. That is, the hability of a function to calling itself until the task is complete; in this case, the function will call itself every time it detects a new folder/directory inside the designated original folder/directory.]]></description>
										<content:encoded><![CDATA[<p>Do you need code to delete the files and folders from the selected folder? In that case, there is a technique I propose to you and that is based on <strong>recursion</strong>. That is, the ability of a function to call itself repeatedly until the task is complete; in this case, the function will call itself every time it detects a new folder/directory inside the designated original folder/directory.<span id="more-5363"></span></p>
<p>But, beware! The following implementation will delete all the files and original containing folder every time it finds an alias… not just the alias. Anyway, it is easy to change this behavior in case you just want to delete the alias and not the original it points to.</p>
<p>As you probably already know, when we work with files or folders in Xojo we are actually using the <a href="http://documentation.xojo.com/api/files/folderitem.html">FolderItem</a> class, so we are able to access to all its properties and the methods acting on every instance: changing the file/folder/directory name, getting the creation date, create a copy, to move the file and/or folder to a new destination … and also for deleting the file or folder.</p>
<p>In addition, <b>recursion</b> is a technique that is not always appropriate because the function adds a new frame of data to the execution stack every time it calls itself, something that can cause a stack overflow error if it calls itself a large amount amount of times. This may occur, for example, if a folder or directory has many nested folders. To alleviate this, we can resort to the mechanism provided by the Xojo language itself and gracefully catch this situation on runtime.</p>
<p>Having said this, what is the best way to implement our recursive function so it is available to all the FolderItem instances? You may create a new FolderItem subclass, but that would mean that the method would only be available from the instances created from the subclass, and not for those created from the parent FolderItem class. The answer in this case is to apply it as a <a href="http://documentation.xojo.com/api/language/extends.html"><strong>Class Extension</strong></a> technique. This technique allows us to add additional functionality to a existing class without needing to subclass it previously.</p>
<p>The way to add a Class Extension in Xojo is through a <a href="http://documentation.xojo.com/api/language/module.html"><b>Module</b></a>, so it gives us the option to set the method as globally available from all the app code. This way, the Xojo compiler will know that we want to extend a particular class because we use the <code>Extends</code> keyword in the method definition, followed by the variable whose data type designates the class we want to extend.</p>
<p>So, our method (or function) signature will be:</p>
<p><code>DeleteAllFilesInside(extends f as FolderItem)</code></p>
<p>Once we&#8217;ve added that method to a Module it&#8217;s important to set the <code>Scope</code> to the value <code>Global</code> in the Inspector. Now we can put the following code inside the associated Code Editor for the method, so this is the responsible of deleting the files and call itself every time it detects a new folder/directory:</p>
<pre>  // We keep the initial (designated) FolderItem
  // So it doesn't get deleted.

  Static originFolder As String = f.NativePath

  // Is the pointed FolderItem a Directory?
  // then proceed to iterate the containing
  // files and (probably) folders.

  If f.Directory Then

    For n As Integer = f.Count DownTo 1

      If f.Item(n) &lt;&gt; Nil Then

        // Are we detecting a new folder
        // while iterating the current one?
        // then we call the function again!

        If f.item(n).Directory And f.Count &lt;&gt; 0 Then

          Dim f1 As FolderItem = f.item(n)

          f1.deleteAllFilesInside

        End If

        // Otherwhise, we proceed to delete the file/folder
        // always it is not the initial FolderItem
        // that is, the initial folder/directory

        If f.item(n) &lt;&gt; Nil And f.item(n).NativePath &lt;&gt; originfolder Then f.item(n).Delete

      End If
      
    Next
  End
  
  // we are outside a folder, so let's check
  // that the pointing FolderItem is not the initial one
  // if it doens't, then we can delete the file/folder

  If f &lt;&gt; Nil And f.NativePath &lt;&gt; originFolder Then f.Delete

</pre>
<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>*Watch a <a href="https://www.youtube.com/watch?v=1TNxnYs91xY">video of this Tutorial in Spanish</a></p>
<p>*<a href="https://www.aprendexojo.com/2019/01/recursividad-vaciar-contenido-de-una-carpeta/">Read this post in Spanish</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Working with Files: FolderItem</title>
		<link>https://blog.xojo.com/2017/02/20/working-with-files-folderitem/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 20 Feb 2017 06:30:45 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[FolderItem]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=2325</guid>

					<description><![CDATA[Sooner or later your app will need to work with files, maybe to save the data generated with the app itself, to open the files created with&#8230;]]></description>
										<content:encoded><![CDATA[<p>Sooner or later your app will need to work with files, maybe to save the data generated with the app itself, to open the files created with other apps or because is the main purpose of the utility you are working on. <b>Xojo</b> gives you the class <a href="http://developer.xojo.com/xojo-io-folderitem"><b>FolderItem</b></a> fully loaded with a useful bunch of properties that allow you to examine the attributes of any file; for example, the creation or modification of dates, the file path (in several formats), if the file is an alias, etc. The FolderItem class also gives you the methods to do a lot of file operations without effort.<span id="more-2325"></span></p>
<p>Of course, as <b>Xojo</b> is a native multi-platform development environment, the FolderItem class is available for all the supported deployment platforms: desktop (macOS, Windows, Linux, Raspberry Pi), console, web or iOS. Of course, under iOS and other sandboxed deployments, you will have to consider the limitations imposed by the OS when dealing with files, as for example not writing to the app bundle (under OS X and iOS), accessing only the allowed folders/directories, etc.</p>
<p>As it goes when using any class, the first thing you will have to do is get a new class instance (an object) pointing to the file item you want to work with, whether it is one already available or one you want to create from scratch (i.e: giving the path, name and extension). In both scenarios, the most basic way to go is the same:</p>
<pre>Dim f as new FolderItem("\users\myusuario\documents\test.txt")</pre>
<p>With the previous line of code we will be using the FolderItem class <b>Constructor</b>, passing along as the argument the native path to the file we want to get the reference to, if it already exists; or to the file our app expects to create. It is important to point out the fact that the path format, as <b>String</b>, is the native one to the platform over which we are going to deploy the app, something you have to consider if you want to create a multiplatform app. For these cases, you can turn to the use of the conditional compilation clause <b>#If…#Then…#Endif</b>, providing the native path variation expected by the OS under which your app is running.</p>
<p>In addition, when we use the FolderItem constructor in combination with absolute paths as arguments, we have not guarantees that the resulting reference assigned to the FolderItem variable is a valid one (in our example, pointed by the &#8216;f&#8217; variable). For example, if we were trying to open a file, it could be the case that the file was no longer in the referenced path anymore (moved, deleted…); or maybe we have included a typo in the path composition. It is for things like these that we should always check the correctness of the variable <b>before</b> using any of the provided methods or accessing the properties, because it is possible that we were dealing with a <b>Nil</b> reference.</p>
<p>For example, we can check our FolderItem variables using the conditional form like this:</p>
<pre>if f &lt;&gt; Nil then
  // this is a valid reference
  // so we can work with it
end if</pre>
<p>Or, preferably, catching the exceptions as in the following example. This way we avoid the use of multiple <code>if…then…else</code> in the same code fragment:</p>
<pre>Exception e as NilObjectException
  MsgBox "The file is not valid"</pre>
<p>How can we get a reference to a file for those cases were we don&#8217;t know the file path in advance? I mean, this is what happens, for example, when using most of the apps that allows us to choose the file via a <b>File Dialog Box</b>; a Window that brings access to the OS file system showing all the files that are compatibles with the app.</p>
<h2>Choosing Files: GetOpenFolderItem</h2>
<p>For these cases Xojo offers the <a href="http://developer.xojo.com/getopenfolderitem"><b>GetOpenFolderItem</b></a> function, passing along as a unique parameter the string representing, as a filter, the kind of files our app is interested in. When we use this parameter, the File Dialog Box will show only the compatibles ones as selectable by the user, leaving the rest in ghost mode. We can also choose to not use any filter at all, passing the string &#8220;????&#8221; as the function parameter.</p>
<p>As result of this function invocation we will get a FolderItem instance. For example:</p>
<pre>Dim f a FolderItem = GetOpenFolderItem("????")
MsgBox f.path</pre>
<p>However, during the user interaction with the File Dialog Box it can be the case that the user selected a valid file clicking next the &#8216;Ok&#8217; button, in whose case our app would get a valid reference; but it can also be the case that the user canceled the operation clicking on the &#8216;Cancel&#8217; button, in which case our variable (&#8216;f&#8217; in the code example) would get a <b>Nil</b> reference. Thus, it&#8217;s important to apply the same kind of test over the variable that we have seen on the previous section.</p>
<h2>SpecialFolder: Direct Access to Well Known Directories</h2>
<p>Xojo also puts in our hands a third option, we can use to get valid references to files in a faster and multiplatform way using the <a href="http://developer.xojo.com/xojo-io-specialfolder"><b>SpecialFolder</b></a> Module. This module gives us access to well known paths on every supported OS, so our app always points to the right path no matter the OS it is running on. This is the way to go, for example, when we want to point to the Documents folder or other specific folders such as Library or Cache.</p>
<p>For example, if we want to get the right reference to the Documents folder on every supported deployment OS, we would have to use this fragment of code:</p>
<pre>Dim docs As Xojo.IO.FolderItem
docs = Xojo.IO.SpecialFolder.Documents
msgbx docs.path</pre>
<p>Try to run the previous fragment of code on several operating systems (virtual machines are a great help for this), and you will see how Xojo points to the right path in every case.</p>
<h2>Child: Adding Items to a FolderItem Path</h2>
<p>In the previous section we saw how to get a reference to a folder or directory; but, how can we complete the path so it also includes a specific file item, either an existing one or the one we want to create? For that we can use the method of the class instance <a href="http://developer.xojo.com/xojo-io-folderitem$Child" target="_blank"><b>Child</b></a>. With this method we can add as many path components as we need (for example, several folder or directories levels in the file system hierarchy) until we point to the file item over which we can get a valid reference. For example:</p>
<pre>Using Xojo.IO
Dim docs as FolderItem = SpecialFolder.Documents
docs = docs.child("MyFile.txt")</pre>
<p>Or we can use also:</p>
<pre>Using Xojo.IO
Dim docs as FolderItem = SpecialFolder.Documents
docs = docs.child("Recipes").child("MyRecipe.doc")</pre>
<p>With the first example, the reference points to a file item thanks to the use of the <b>Child</b> method. While the second example also adds an additional directory (&#8220;Recipes&#8221;) to the path via the use of <b>Child</b>, to finally point to the file item. In both cases, the referenced file may or may not exist. If the file doesn&#8217;t exist yet, then the &#8216;docs&#8217; variable will not include valid data on all of the properties that you could read if the variable were pointing to an existing file. For example, some of these properties are creation date, modification date or file length. When the variable points to a folder or directory, then we can use the <b>Count</b> property to know the number of items contained by the folder so we can iterate on them, for example.</p>
<h2>Iterating Files and Folders</h2>
<p>However, when we need to iterate a folder item, for example to manipulate every available item or transverse the file system hierarchy walking every found folder, the best we can do is get an <b>Iterator</b> on the folder/directory we want to use as the root point of the process. For this, the <b>Xojo.IO.FolderItem</b> class gives us the <a href="http://developer.xojo.com/xojo-io-folderitem$Children" target="_blank"><b>Children</b></a> method, so we can use the <b>For…Each…In</b> loop to walk every available item in the iterator.</p>
<p>For example, we can add all the visible files available under the Documents folder to a <a href="http://developer.xojo.com/listbox"><b>ListBox</b></a> using the following code snippet:</p>
<pre>using Xojo.io
dim f as FolderItem = SpecialFolder.Documents
for each i as FolderItem in f.Children
  if i.IsFolder = false and i.IsVisible then Listbox1.AddRow i.name
next</pre>
<p><iframe title="Trabajar con archivos en Xojo: FolderItem" width="500" height="375" src="https://www.youtube.com/embed/SjEfyEwQ7hQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
<h2>In Brief…</h2>
<p>We have seen the basics of the <b>FolderItem</b> class and how we can use it to get references to folders/directories and files, both using the Classic Framework or the Modern one. We have seen also several ways to compose the FolderItem paths, how to deal with Nil references, and the best way to walk through all the available files under a folder via an Iterator. Once we get the reference to the file and/or folder of interest, there are a lot of methods and properties you can explore under the FolderItem class!</p>
<p><em>Javier Rodri­guez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has used Xojo since 1998. He is in charge of <a href="http://www.aprendexojo.com">AprendeXojo.com</a> and 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/02/trabajo-con-archivos-folderitem/">Read this post in Spanish</a></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
