Monday, May 25, 2026

Delphi Tip of the Day: Folding Code

 Every once in a while, I run into one of those small Delphi features that makes me wonder, “Why haven't I been using this more?

Code folding is one of those features.

I was reminded of this during
a recent ChatGPT coding session

It does not make your code run faster. It does not fix bad logic. It does not magically turn a messy unit into clean architecture. But it does make the Delphi editor easier to work in, and when you spend a lot of time moving around in the source code, that matters.

I was reminded of this during a recent ChatGPT coding session while working in Delphi 13.1.

We were not doing anything glamorous. We were not building some grand framework or rewriting the whole application. We were doing the kind of careful work real programmers do all the time: find this section of code, replace it with that section of code, compile, test, and move on to the next small change.

In other words, it was surgical coding.

ChatGPT would tell me something like, “Find this method,” or “Replace this block,” or “Add this procedure right below that one.” That works fine when the unit is small. But once the source file starts growing, finding the right place in the code can turn into a scroll hunt. You move up, move down, pass the section you were looking for, scroll back, and hope you do not paste the new code in the wrong place.

That is when folding code started looking a lot less like an editor gimmick and a lot more like a practical navigation tool.

I created a simple test form with one button so I could slow down and look at how Delphi handles folded regions and folded methods. Nothing fancy. Just a small, controlled example where I could see what happens when the editor shows the code as an outline instead of one long strip of source code.

The lesson was simple: when you are making careful, targeted edits, folded code helps you find the right operating table before you pick up the scalpel.

unit Unit1;

interface

{$REGION 'Interface Comments'}
// ============================================================================
// Interface comments go here
// ============================================================================
//
//
// ============================================================================
{$ENDREGION}

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$REGION 'Implementation Comments'}
// ============================================================================
// Implementation comments go here
// ============================================================================
//
//
// ============================================================================
{$ENDREGION}

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  //
  // Button1 Click Code Goes Here
  //
end;


end.

What Is a Delphi Region?

A Delphi region starts with {$REGION ...} and ends with {$ENDREGION}.

For example:

{$REGION 'Interface Comments'}

// code or comments go here

{$ENDREGION}

The text inside the quotes becomes the folded label in the editor. In this example, Delphi shows the folded section as Interface Comments.

That may not seem like much in a small unit, but once a source file grows, these regions can act like road signs. Instead of scrolling through everything line by line, you can collapse the sections you do not need and keep the overall structure visible.

The Before Picture

Nothing Folded

This first screenshot shows the unit with nothing folded.

In a tiny example like this, it is not a big deal. Everything fits on the screen, and there is not much to hunt for. But that is not how real Delphi projects usually stay. A form starts simple, then a few more event handlers get added. Then a few helper methods show up. Then some temporary test code appears. Before long, you are scrolling through the file trying to find the one method you need.

That is where folding starts to earn its keep.

Folding the Regions

Regions Folded

In the second screenshot, the two comment regions are folded.

The code is still there. Nothing has been removed. Delphi simply collapses those sections so they take up less room in the editor.

This is one of the things I like about folding code. It lets me get things out of the way without deleting anything. Sometimes I want those big comment blocks. Sometimes they are helpful. But when I am working on a method, I do not always need to see them.

Folding lets me say, “Not now. Stay there, but get out of my way.”

That is useful.

Folding Regions and Methods

Regions & Methods Folded

The third screenshot shows both the regions and the method body folded.

At this point, the source file starts to look more like an outline. You can see the major parts of the unit without seeing every line inside each part.

That is probably my favorite use of folding. It helps me move around in the source file without getting pulled into the details too soon. When everything is expanded, every line competes for attention. When sections are folded, I can scan the shape of the unit first, then open only the part I need.

For someone like me, that matters. I do not “picture” the code in my mind. I work better when the structure is visible on the screen. Folding code gives me a simple way to make the editor show the structure instead of forcing me to mentally hold it all together.

Customizing the Folded Code Color

Delphi also lets you customize the way folded code looks in the editor.

You can find this under:

Tools > Options > Editor > Color

Then scroll down to the Folded code element.

Delphi 13.1 Editor Color settings

I usually work in the Light theme, so I changed my folded code colors to something I could spot quickly without making the editor look like a warning sign.

My settings are:

Foreground color: Palevioletred
Background color: Mistyrose

That is just my personal preference. You may like something different. The important thing is that folded code should be easy to recognize. I want it to stand out, but I do not want it shouting at me all day.

Palevioletred on Mistyrose works for me. It is visible, but not obnoxious.

At least in my humble opinion.

Why This Helps

The real benefit of folding code is navigation.

When I am working in a source file, I do not always need to see everything. Sometimes I only need the interface section. Sometimes I only need the implementation section. Sometimes I want to hide temporary test methods so I can focus on the production code. Sometimes I want to collapse a group of helper methods because they are not the thing I am working on right now.

That is where regions can be helpful.

For example, you might use:

{$REGION 'Helper Methods'}

or

{$REGION 'Temporary Sample/Test Methods'}

or

{$REGION 'Initialization Code'}

The region names become little signposts inside the editor. When they are folded, they help you move around the unit faster.

Used carefully, code folding reduces visual clutter. Used carelessly, it can become clutter of its own. I would not wrap every tiny thing in a region just because Delphi lets me do it. But for logical sections of code, longer comment blocks, temporary test code, or helper methods, regions can make a unit easier to live in.

Final Thought

Code folding is a small feature, but it solves a real problem.

It helps you move around inside your code without scrolling through every line. It lets you collapse the parts you do not need right now. It turns a long source file into something closer to an outline.

And when you can see the outline, it is easier to find your way.

Sometimes the best productivity improvement is not a new tool. Sometimes it is just making the tool you already use a little easier to work with.

Share Your Colors With a Comment

Please share the foreground and background colors you are using for your Folded Code in the comments.

Enjoy!
Semper Fi
Gunny Mike
https://zilchworks.com
https://debtblaster.com

GOTCHAS!

As pointed out by SilverWarrior in the comments. Code errors lead to unfolded code from that point on. There are two very quick ways to re-fold all the methods instead of toggling the ( - ) or ( + ) in the left margin.

Method Folding quick Steps

Mouse:         Right Click > Fold > Methods
Keyboard:    [ Ctrl ] + [ Shift ] (keep held down) press K then press M





Friday, May 15, 2026

Concrete by Day, Nero by Night: A Practical Light/Dark Style Pair for Delphi FMX

 One of the nice things about Delphi FMX is that you can change the look of an application without rewriting the application.

That sounds simple.

In practice, finding two styles that work well together can take some trial and error.

For Debt Blaster, I wanted a clean light theme and a clean dark theme. I did not want the application to feel like two completely different programs depending on the selected theme. I wanted the light and dark versions to feel related.

That is where the Concrete and Nero FMX styles came in.

The GetIt Package Manager

Both styles are available through the Delphi GetIt Package Manager.

In GetIt, I installed:

FMX Style - Concrete 1.0
FMX Style - Nero 1.0

The style files I am using are:

Concrete_Win.style
Concrete_macOS.style
Nero_Win.style
Nero_macOS.style

That gives me a light and dark style for both Windows and macOS.

Concrete and Nero styles installed from Delphi's GetIt Package Manager

Concrete for the Light Theme

The Concrete style gives the application a clean light appearance without making it look too flat or unfinished.

It works well for traditional business software because the controls are easy to read, the grid lines are clear, and the interface still feels like a desktop application.

For Debt Blaster, that matters.

This is not a game. It is not a flashy demo. It is software people use to enter real debt information, compare payoff plans, and make decisions.

The user interface needs to stay out of the way.

Concrete does a good job of that.

Debt Blaster using the Concrete FMX style on Windows.

Nero for the Dark Theme

The Nero style is a strong companion to Concrete.

It gives the application a dark theme without changing the basic structure of the screen. The same grids, menus, fields, buttons, and panels are still there. They just shift into a darker working environment.

That is what I like about this pairing.

Concrete and Nero feel like they belong to the same family.

One works well when I want a light application. The other works well when I want a dark application.

Debt Blaster using the Nero FMX style on Windows

Why I Like This Pair

The big win is consistency.

When I switch between Concrete and Nero, the application does not feel redesigned. It feels restyled.

That distinction matters.

A good style should support the application. It should not make the user stop and think, "What happened to the program?"

Concrete and Nero give me:

Light theme: Concrete
Dark theme: Nero
Windows: platform-specific style files
macOS: platform-specific style files

That gives me a clean path for supporting both Windows and macOS without pretending one style file should handle every platform perfectly.

One Practical Lesson

FMX is cross-platform, but that does not mean every visual decision automatically behaves the same way on every platform.

For this reason, I prefer using the platform-specific style files:

Concrete_Win.style
Concrete_macOS.style
Nero_Win.style
Nero_macOS.style

That keeps the intent clear.

Windows gets the Windows style file.

macOS gets the macOS style file.

That is easier to understand, easier to debug, and easier to explain six months from now when I come back to the code and wonder what I was thinking.

Final Thought

If you are building a Delphi FMX application and want a clean light/dark style combination, Concrete and Nero are worth a look.

They are easy to install from GetIt, they work nicely together, and they give an FMX desktop application a more finished appearance with very little effort.

For me, Concrete and Nero are not just two random styles.

They are a practical pair:

Concrete by day.
Nero by night.

And for Debt Blaster, that pairing fits very nicely.

Enjoy
Semper Fi
Gunny Mike
https://zilchworks.com
https://debtblaster.com





Saturday, April 25, 2026

Delphi 13.1 Install: The Android JDK Checkbox Trap

Android was selected, but the installer did not automatically select the required JDK and Android SDK/NDK options. This led to the Java JDK error later in the install.

I had recently posted to the FB Delphi Developer group that Delphi 13.0 IDE insight was not working. (See post here)

Marco Cantu responded and mentioned that it was working in his Delphi 13.1. So I decided to go and upgrade my version of Delphi to 13.1. 

I overlooked a small little detail that sent me down "install hell". I chose the Android platform but forgot to check off  Eclipse JDK and Android SDK.

Critical Technologies I failed to check off

The installer ran and gagged on the JDK missing. It gave me two error messages. One telling me the JDK was missing and s second one with a nice "Retry" button. 





So I installed the JDK and clicked Retry. And Delphi eventually installed successfully. This got me thinking. Why didn't this installer warn me that those unchecked boxes might cause an error during installation? I can't answer that.

The other annoying thing is the installer seems to "hang" when it's performing the "Installing" task. Not all the time but most of the time. I made me feel like the computer froze.

So I loaded the Getit Install Log into TextPad. One of the nice features of TextPad is it does not cause a sharing violation when a file is being actively written to. Ig gives you a nice message that says "The file has been updated. Would you like to reload the file?" This was my cheap way of watching what was happening and being comforted that the install was not hung.

ChatGPT Dashboard using the Getit Installation Log


Then I decided to have a little fun. I gave the Getit Installation Log and asked ChatGPT to turn it into a stand-alone HTML dashboard showing me what happened. It came out pretty cool. I asked ChatGPT to give me a blogger-friendly version of HTML I could past in. Below is my Delphi 13.1 installation dashboard.

Oh I almost forgot. After installing 13.1 the IDE Insight is working again. 

I went back and checked when the IDE Insight was working:

  • Delphi 13.1 - Working
  • Delphi  13.0 - Not Working
  • Delphi 12 - Not Working
  • Delphi 11.3 - Not Working
  • Delphi  10.3 - Not Working
  • Delphi 10.2.3 - Working
I guess we'll never know what happened between Delphi 10.2.3 and Delphi 13.1 that IDE Insight to not work. 

RAD Studio 13.1 GetIt Install Dashboard

A Blogger-friendly summary generated from the GetIt install log. This version is scoped to this post and uses inline styling so it should not disturb the Blogger theme.

Total elapsed
58m 54s
2:45:21 PM to 3:44:15 PM
Active installer time
41m 5s
Across 4 install attempts
Final successful run
26m 29s
After the JDK retry
Platforms selected
5
Android, iOS, macOS, Windows on Arm, Windows
Packages installed
27
Unique successful packages

Install story

The log shows 4 install attempts on 2026-04-25: 3 failed Android SDK/JDK attempts, followed by 1 successful run. This version includes macOS/OSX work done before the retry, so it does not disappear from the timeline.

Platforms selected

Android
iOS
macOS
ARMWindows on Arm
Windows

Process time - full current install sequence

Moving folders25m 22s
61.7% of measured time
Downloading7m 45s
18.9% of measured time
Extracting5m 39s
13.8% of measured time
Commands1m 40s
4.1% of measured time
Other / setup27s
1.1% of measured time
Completion markers7s
0.3% of measured time
Registry / environment5s
0.2% of measured time

Process time - final successful retry only

Moving folders18m 3s
68.2% of measured time
Downloading5m 45s
21.7% of measured time
Commands1m 40s
6.3% of measured time
Extracting45s
2.8% of measured time
Other / setup7s
0.4% of measured time
Registry / environment5s
0.3% of measured time
Completion markers4s
0.3% of measured time

Install attempts

SessionStartEndDurationStatusSelected platformsRoot error
42:45:21 PM2:50:27 PM5m 6sFailedAndroid, iOS, macOS, Windows on Arm, WindowsError when executing an action of "AndroidSDK" catalog. The action is "CheckJavaInstalled" (ID 22).
52:50:36 PM2:53:06 PM2m 30sFailedAndroid, iOS, macOS, Windows on Arm, WindowsError when executing an action of "AndroidSDK" catalog. The action is "CheckJavaInstalled" (ID 22).
63:03:47 PM3:10:47 PM7m 0sFailedAndroid, iOS, macOS, Windows on Arm, WindowsError when executing an action of "AndroidSDK" catalog. The action is "CheckJavaInstalled" (ID 22).
73:17:46 PM3:44:15 PM26m 29sSuccessfulAndroid, iOS, macOS, Windows on Arm, WindowsNone

macOS / OSX package detail

These packages were installed before the final JDK retry, which is why they can be missed if you only look at the final successful retry.

PackageObserved timeFirst seenLast seenSuccessesMeasured phase time
OSX and iOS Common Files Professional7s2:45:35 PM3:04:08 PM2Downloading: 6s
Moving folders: 1s
PAServer for OSX10s2:45:39 PM3:04:14 PM2Extracting: 8s
Downloading: 2s
OSX and Linux Common Files2s2:45:44 PM3:04:15 PM2Extracting: 2s
OSX64 Common Files Professional8m 56s2:45:45 PM3:09:05 PM2Moving folders: 7m 18s
Downloading: 1m 38s
OSX Common Files Professional13s3:33:06 PM3:33:19 PM1Downloading: 12s
Installing: 1s
PAServer for Win6417s3:33:19 PM3:33:36 PM1Extracting: 13s
Downloading: 4s
Delphi macOS Professional10s3:40:15 PM3:40:25 PM1Moving folders: 6s
Downloading: 4s

Slowest package spans - full current install sequence

The horizontal position shows where the work happened within the overall timeline. Gaps may include error screens, retry time, user intervention, setup checks, and log entries that were not assigned to a named package.

PAServer for OSX5s
Session 4 • 2:45:39 PM to 2:45:44 PM
OSX64 Common Files Professional4m 6s
Session 4 • 2:45:45 PM to 2:49:51 PM
OSX64 Common Files Professional4m 50s
Session 6 • 3:04:15 PM to 3:09:05 PM
AndroidSDK1m 24s
Session 7 • 3:17:53 PM to 3:19:17 PM
Android Common Files Professional5m 9s
Session 7 • 3:19:17 PM to 3:24:26 PM
Core Common Files Professional4m 19s
Session 7 • 3:24:26 PM to 3:28:45 PM
Delphi Common Files Professional17s
Session 7 • 3:28:46 PM to 3:29:03 PM
IOS Common Files Professional4m 2s
Session 7 • 3:29:03 PM to 3:33:05 PM
OSX Common Files Professional13s
Session 7 • 3:33:06 PM to 3:33:19 PM
PAServer for Win6417s
Session 7 • 3:33:19 PM to 3:33:36 PM
Win64 Common Files Professional2m 51s
Session 7 • 3:33:36 PM to 3:36:27 PM
AdoptOpenJDK16s
Session 7 • 3:36:27 PM to 3:36:43 PM
Help Files Professional19s
Session 7 • 3:36:51 PM to 3:37:10 PM
Sample Applications17s
Session 7 • 3:37:10 PM to 3:37:27 PM
TeeChart Standard Professional24s
Session 7 • 3:37:28 PM to 3:37:52 PM
Delphi iOS Professional2m 18s
Session 7 • 3:37:57 PM to 3:40:15 PM
Delphi macOS Professional10s
Session 7 • 3:40:15 PM to 3:40:25 PM
Delphi WinArm Professional3m 48s
Session 7 • 3:40:25 PM to 3:44:13 PM

Errors and recovery

The repeated failure was the Android SDK action CheckJavaInstalled. After the JDK was installed, the retry completed successfully.
Error messageCountSessions
Error when executing an action of "AndroidSDK" catalog. The action is "CheckJavaInstalled" (ID 22).64, 5, 6
A problem occurred during the process.34, 5, 6

What was installed

Successful packages across the current install attempts.

PackageSuccessesFailed/incompleteObserved timeFirst seenLast seenMeasured phase time
InterBase Redist224s2:45:26 PM3:04:02 PMExtracting: 6s
Downloading: 4s
Windows and Android Common Files200s2:45:26 PM3:03:56 PMn/a
LivePreview202s2:45:33 PM3:04:04 PMExtracting: 2s
Roboto Fonts202s2:45:34 PM3:04:05 PMDownloading: 2s
OSX and iOS Common Files Professional207s2:45:35 PM3:04:08 PMDownloading: 6s
Moving folders: 1s
PAServer for OSX2010s2:45:39 PM3:04:14 PMExtracting: 8s
Downloading: 2s
OSX and Linux Common Files202s2:45:44 PM3:04:15 PMExtracting: 2s
OSX64 Common Files Professional208m 56s2:45:45 PM3:09:05 PMMoving folders: 7m 18s
Downloading: 1m 38s
AndroidSDK131m 32s2:49:51 PM3:19:17 PMExtracting: 4m 42s
Installing: 1m 14s
Downloading: 10s
Android Common Files Professional105m 9s3:19:17 PM3:24:26 PMMoving folders: 4m 23s
Downloading: 46s
Core Common Files Professional104m 19s3:24:26 PM3:28:45 PMMoving folders: 3m 12s
Downloading: 1m 3s
Installing: 4s
Delphi Common Files Professional1017s3:28:46 PM3:29:03 PMDownloading: 13s
Moving folders: 3s
Installing: 1s
IOS Common Files Professional104m 2s3:29:03 PM3:33:05 PMMoving folders: 3m 18s
Downloading: 43s
Extracting: 1s
OSX Common Files Professional1013s3:33:06 PM3:33:19 PMDownloading: 12s
Installing: 1s
PAServer for Win641017s3:33:19 PM3:33:36 PMExtracting: 13s
Downloading: 4s
Win64 Common Files Professional102m 51s3:33:36 PM3:36:27 PMMoving folders: 2m 15s
Downloading: 36s
AdoptOpenJDK1016s3:36:27 PM3:36:43 PMExtracting: 10s
Downloading: 4s
Installing: 2s
AndroidSDK-NDK104s3:36:43 PM3:36:47 PMInstalling: 2s
Downloading: 1s
Extracting: 1s
Fonts104s3:36:47 PM3:36:51 PMInstalling: 3s
Extracting: 1s
Help Files Professional1019s3:36:51 PM3:37:10 PMDownloading: 17s
Moving folders: 1s
Installing: 1s
Sample Applications1017s3:37:10 PM3:37:27 PMExtracting: 13s
Downloading: 3s
Installing: 1s
TeeChart Standard Professional1024s3:37:28 PM3:37:52 PMMoving folders: 17s
Downloading: 6s
Installing: 1s
Delphi Android Professional104s3:37:53 PM3:37:57 PMDownloading: 2s
Moving folders: 1s
Installing: 1s
Delphi iOS Professional102m 18s3:37:57 PM3:40:15 PMMoving folders: 1m 46s
Downloading: 31s
Installing: 1s
Delphi macOS Professional1010s3:40:15 PM3:40:25 PMMoving folders: 6s
Downloading: 4s
Delphi WinArm Professional103m 48s3:40:25 PM3:44:13 PMMoving folders: 2m 49s
Downloading: 58s
Installing: 1s
Delphi Windows Professional102s3:44:13 PM3:44:15 PMExtracting: 1s
Installing: 1s

How the timing was calculated

Durations are estimates inferred from timestamp gaps between log entries. A package duration runs from the first logged action for that package through its success marker. Installer housekeeping, retry gaps, error screens, registry updates, file copies, and command execution can create visible gaps in the timeline.


Enjoy
Semper Fi
Gunny Mike
https://zilchworks.com
https://debtblaster.com