How to use the Basic Primitives Org Chart Tool

As I mentioned in my previous post, Basic Primitives is a powerful tool for making Org Charts for your website. I thought it would be useful to document a little bit how to use the Basic Primitives Org Chart tool, because the examples weren’t quite the tutorial I was hoping to find.

So, starting with a simple example of something I needed for my project, I wanted to change the chart’s orientation from top to bottom to left to right. I started by searching the reference guide for orientation. I found it was a part of the primitives.orgdiagram.Config class.

So far, not much on how to use it though. Clicking on orientation type takes you to a more detailed explanation:

Disappointingly, that’s a pretty terse explanation. Ideally, it would explain all the different choices, where to set this property, and have a code snippet to show you the synax. Some defaults in this document are linked to their choices. This one is not.

Searching the page for OrientationType does yield promising results for what the possible values are at least:

The best looking match is:

There’s also a close sounding match “primitives.text.TextOrientationType” however, the descriptions reveal that option is for changing the orientation of the text, not the chart.

So, now, how to use the information we’ve found from the reference guide?

If you go to the “How to Use” section, there’s a list of examples. You could really start with any of them, but I’ll pick the “First organizational chart”. On the plus sides, these examples are all editable, so you can experiment. On the down side, if you make a syntax mistake, the whole chart disappears and it doesn’t tell you where your mistake is.

So the important parts here are where the global options variable is initialized, and where they use it.

Initialization:

var options = new primitives.orgdiagram.Config();

this is given in the example. You’ll notice the variable options is of the type primitives.orgdiagram.Config, like we saw in the reference guide above. So this variable is the one you need to use to change any *global* configuration item that is in that same section of the reference guide.

Now skip down near the end of the example:

options.rootItem = rootItem;
options.hasSelectorCheckbox = primitives.common.Enabled.True;

These two lines change a couple of the global configuration options. So, to add another global option, you just need to add another line of code before or after these two lines, adding your new option.

Go back to the beginning of the reference guide, jump to the section on primatives.orgdiagram.config again, everything under the word “properties” here is a property of options that can be set:

The correct value to use is a little trickier in this particular case. The documentation showed an example of the default being primitives.orgdiagram.OrientationType.Top, however, the documentation shows the possible values for Orientation under a heading called primitives.common.OrientationType. Notice anything different about the package naming? Yeah, that’s a little confusing, and I ended up with a blank diagram a couple times because of this.

Looking at the source code for the enumeration, it appears to be a simple documentation error, that the comment was not updated when the package name was changed for whatever reasons. Here’s the definition in the source code:

/*
Enum: primitives.common.OrientationType
Defines diagram orientation type.

Top - Vertical orientation having root item at the top.
Bottom - Vertical orientation having root item at the bottom.
Left - Horizontal orientation having root item on the left.
Right - Horizontal orientation having root item on the right.
*/
primitives.orgdiagram.OrientationType =
{
Top: 0,
Bottom: 1,
Left: 2,
Right: 3
};

Yep, I’m sure you’ve all seen code like that before. Anyway, just use OrientationType defined in orgdiagram, because that’s what the code says, and what works. And if you find some other property you want to set, and it’s not working, check the package name in the source code to make sure it’s right.

So our working line of code to change the orientation becomes:

options.orientationType = primitives.orgdiagram.OrientationType.Left;

And you just have to put that with the other global options (technically, other places are ok too, but to keep things simple, leave all the options in one place.

If you go back to the orgdiagram.global properties list at the beginning of the documenation,

(there’s more than fit in this screenshot), any of these are set following the same formula. Orientation Type is not the only enumeration incorrectly documented. graphicsType isn’t defined in the documenation at all. Just search the source code for the possible enumeration values. Theres no apparent consistency about whether things are under common or orgdiagam, so just look up what’s in which spot, unless you start to notice a pattern I missed.

options.graphicsType = primitives.common.GraphicsType.Canvas;
options.pageFitMode = primitives.orgdiagram.PageFitMode.PageHeight;

and so forth.

A couple of other options I ended up changing for my diagram included:

options.connectorType = primitives.orgdiagram.ConnectorType.Squared;
options.hasSelectorCheckbox = primitives.common.Enabled.False;
options.minimalVisibility = primitives.orgdiagram.Visibility.Normal;

As a footnote, changing the template around, because we didn’t need pictures next to the roles (since we only showed names for board members on our chart) was a bit more complex and requires structural changes to the javascript. I wouldn’t recommend it for javascript/jquery beginners unless the demo one is really close to what you need. But if you’re a seasoned user of javascript, it’s quite doable.

In Search of An Org Chart

Another project I’ve been working on recently was an online org chart to show the leadership structure for my mom’s club. One of the leaders sent me a powerpoint version of the chart and said “we want this on the website”.

I was anticipating this document would change over time, as new roles are created or subdivided and old roles are retired, so I wanted to make the update process straightforward and quick, so I wasn’t too keen on using an image for the chart.

My first thought was to use Google Orgchart, as it’s super-easy to set up, and I could have the whole thing done in five minutes or so, and there initially appeared to be a section on customizations. But then when I started digging into the options, it turns out there’s no option to change the orientation to go left to right instead of top to bottom, which ended up being a deal-breaker. To illustrate why, here’s a demo of what Google Orgchart’s output looks like with a shallow but wide tree:

In reality, there are 2-5 coordinators under each director role, and a few of those have as many as 3 assisting roles beneath that, so the actual chart would have been much wider. I just wanted to show you how having horizontal labels on a wide chart without putting children far enough down to scrunch the previous level results in a hard to read chart. For a deep hierarchy with few nodes, Google Orgchart seems like a great simple tool, but for a shallow hierarchy with many nodes per level, it just wasn’t the right tool.

So I started looking into alternatives to Google Orgchart. There was absolutely nothing with the same level of simplicity. At one point I even looked into how hard would it be to just export the powerpoint chart to HTML. Oh, but it turns out Office took “export to html” out of the features list in Office 2010, so I would have had to reinstall Office 2003, or experiment with a rather complex workaround, just to evaluate whether that would be a feasible choice.

In the end I kept coming back to suggestions that Basic Primitives looked like the right tool for the job. It’s demos clearly showed it was capable of a horizontal layout, but unfortunately, their “how to use” section completely neglected to give a demo on how to change that option. The tool provides lengthy documentation on all the properties you could possibly set, however, the “reference guide” looked like a machine-generated documentation, and I felt like the “how to” section could have been a little more helpful at explaining how to use the different customization options, rather than leaving that as an exercise to the newbie who has no idea how to use this tool.

It took a a bit of time studying the examples they did provide, and trying to match up how they changed this and that to where in the reference guide that item was documented to figure out how to decipher the reference guide. But in the end, I was successful in creating the org chart I needed using this tool.

Here’s an image of what the layout ended up looking like using the basic primitives tool with custom (simplified) layouts for each role. The colors are designed to coordinate with the site ;-).

In my next post I’ll spell out a little more about how to use Basic Primitives because it’s a great tool, but the documentation isn’t very newbie friendly.

Installing Indy9 from Source Code

I’m finally working on getting Delphi 7 set up on my Win7 x64 machine. I think it’s been over a year since I last did this on my Vista machine or my Win7 x32 netbook, so my mind totally went blank trying to remember how to install the lastest version of Indy 9.

I already had pulled the code from Indy’s SVN server and been able to transfer that from the old machine, so I was one step ahead there.

I pulled up the “ManualInstall.txt” document in the Indy source directory and tried to follow the directions, only to find it didn’t work. At first it looked like it was a permissions issue, I needed to be running a batch file called fulld7.bat from a command line running on elevated privileges to get the script to run without errors, however, even after sorting all that out, when you get to the step of Installing the *.bpl, even after you’ve correctly remembered which one is the right menu option install such, it just doesn’t work. Complains about a missing file (that just doesn’t seem to exist in the provided repository or compiled files directory).

Well, after much fiddling and trying to figure it out on my own, since the internet had no solutions, it turns out, those directions probably are obsolete, and doing it the way that actually *worked* was much easier…just not obvious if you haven’t been working with Delphi recently.

In the Indy 9 directory from the SVN, there’s a .DPK package file for each delphi version. So, since I’m using Delphi 7, double click Indy70.DPK, it opens in Delphi with a package window visible displaying a list of all the files. At this point you’re two clicks away from a working Indy install. Click “Compile” and then “Install” on the package window, and dismiss the dialogs that confirm those steps work, and suddenly Indy is on the component toolbar without even restarting Delphi.

So there you have it. I’m thinking documenting the steps on installing this that work will be helpful, because by the next time I get around to trying to install Indy on a new machine, I almost certainly will have forgotten how you install it, since you do it once and never touch it again, and odds are good that it will need re-installing after a hiatus where I haven’t touched Delphi in a while period and can’t remember off the top of my head the difference  between installing a component and installing a package, since that’s very delphi-specific terminology.

Pattern Block Designer

I’ve started a new project recently. A pattern block designer written in Java 7. Yes, in spite of all the other projects I have yet to start ;-).

My mom gave my son a box of mis-matched pattern blocks that were left over from her classroom. Anyway, he’s not really old enough to “get” making designs on his own yet, but I figured he loves puzzles and matching shapes and colors isn’t too hard for him, so I started looking for some designs online of concrete objects drawn in pattern blocks, like a train, for example, since he’s really into trains.

But while the first site I found a bunch of animal designs had nice high quality printable PDFs, the second site (which had some cool designs like rockets and trains) had a word document with upscaled screenshots from a java applet. It was quite low resolution (like 32 pixels per inch instead of 300 pixels per inch…and no amount of anti-aliasing is going to make up for that), and the geometry of two of the shapes was just a little bit off for the sake of convenience. It just didn’t look very good printed. And there weren’t a lot of other free or instant-download alternatives.

So I decided to redraw a couple of those designs in Corel Draw, and set out creating isometric guidelines and measuring all the real pattern blocks with a ruler and compass to make sure I had the scale correct and everything before I created shape templates. And while the finished product didn’t look bad, I kept getting frustrated with how much simpler it “ought to be” to do this, mentally designing how it ought to work.

So that’s pretty much my inspiration for deciding to start this project. And just for fun, here’s one of my corel draw animal designs as a low quality gif image…and you can see a couple of my points of frustration trying to get the geometry to line up perfectly…even with the “snap” options in corel draw.

Computer Woes

My old computer was finally giving way, starting to have blue screens at least once a week and some other erratic issues. That’s never a good sign. And when you’re talking about a 5 year old laptop that’s already had the motherboard replaced once…well, it was just time to replace, before it dies a catastrophic death.

At first I was thinking I’d just get another laptop, but when I started looking at computers, a relatively new form-factor caught my eye–the all in one flat-panel touch-screen computers. Just think of how much desk space this would free up! And a full HD screen? That doesn’t require an external monitor sitting next to it? And it’s not like I ever take that computer with me when I travel, since the netbook is a lot more portable.
I was kind of procrastinating at making a decision about the new computer, until I got a look at the new Windows 8, and decided I really just wasn’t ready to make the leap toward the experiment of their new UI, which by all accounts is great for touch-screen tablets but “may be” a step backward for desktop users, accustomed to having a start button and doing heavy multi-tasking. Two days later, I’d ordered a clearance windows-7 machine online. I would have bought in person, but I really wanted an I5 processor (that seems to be the sweet spot of performance vs price at the moment) and not an AMD processor, and definitely not an intel pentium (they still make those?!?!), and that pretty much eliminated everything I could get locally.

A week later it arrived, and luckily turned out to be as fantastic as I expected, and fit on my desk with less than an inch to spare between the monitor and the hutch on my desk. Not that there aren’t a few things I would have done differently if I were designing the computer, but nothing I can’t live with.

Around the same time as I was trying to get everything installed on the new computer, I discovered a nasty click-fraud rootkit virus on the netbook that I primarily use for web-surfing. Long story short, even after running bunch of different virus scanners and malware removers and “fixing” multiple viruses, I couldn’t get the suspicious network activity to cease, so I had to order restore disks from Toshiba and reformat. Too bad I never got around to making the restore disks *before* it was infected. I suppose I’ll have to start doing a better job of actually installing all the windows security updates and browser updates, even if the lastest firefox is giving me nothing but trouble and crashes a lot ;-).

So, between all that and the holidays, and working on the annual photo calendars, I haven’t had as much time to work on my usual “geek projects” as I’d like. That and every time I go to work on a particular project I find another program or two I still need to install for that task, or some important registry key or password or file that got missed when I was migrating files to the new computer that I have to track down, which can just be time consuming. But things are coming together and I’m putting the computer to good use.

Oh, and there’s a hope I might actually be able to install the free version of Visual Studio on the new machine, since the issues I was having on the old computer with it being unable to install a certain service pack required for Visual Studio is now moot.

Disabling Auto-Check

I recently finished implementing a new feature for PopTrayU, conditionally disabling automatic checking for an email account based on the time of day. This feature already existed on a global level: you could disable checking for all accounts, so that your computer would not check for email while you’re sleeping or awaken you with a loud “you have new email” notification sound. But some users, particularly users who work from home and use the same computer for both work and pleasure, were making a feature request that they’d like to be able to turn off notifications for their work email outside of normal working hours.

The part of the implementation that was most difficult, of course, was the requirements analysis and the detailed design. On the surface, this feature seemed pretty straight-forward, but as I started to dive into actually implementing it, a lot of nuances come up where it isn’t exactly clear how this feature should work, and the design has to be hashed out in more detail, and the requirements clarified.

Each account has a status icon indicating whether the account is disabled or has new email or no new email. (For the sake of clarify, lets call this new per-account no-auto-check feature “sleeping”.) Should the visual appearance of an account that is “sleeping” appear like a normal account or a disabled account? Something else? What should the status-bar for the account say when an auto-check happens, but a single account is skipped because of the time? If the user presses “Check All Accounts” manually, should that skip or include accounts that are sleeping? What if they press “Check” for a single “sleeping” account?

Once I nailed down the design, implementation was pretty simple. Because the feature existed on a global level, most of the implementation was quite similar to the logic and UI of how it was done for the global level.

As far as how I decided to resolve some of those issues:

An account that is disabled is represented by an envelope with a red minus symbol on it, like this:  Previously, this was the only reason a specific account would be skipped when an auto-check occurred. Now we have two reasons an account might be skipped. It could, for some users, be handy to be able to differentiate the reason the account is not automatically checking, especially should they be troubleshooting settings gone awry. I experimented with making a new symbol that resembled sleeping, like something with zzz’s or a moon, but given the limited amount of space in a 16×16 image, trying to make an image that is clear and recognizable is difficult, so I decided to use the same symbol as a disabled account, but use a contrastingly different color to differentiate the different status.  

As far as when to check/not-check:

  • Automatic timer-interval checking, pretty straightforward, sleeping accounts should be skipped.
  • Manually pressing the “check all” button: more ambiguous, it’s not really an “auto-check”, but it behaves a lot like one. In the end I decided “check all” should replicate the behavior of auto-check, but on-demand, so accounts that are not in a state allowing automatic checking should be excluded, so it should behave like a disabled account.
  • Manually pressing the “Check” (this account) button: this one seemed pretty straightforward, even a disabled account will check when pressing this button, so a sleeping account should definitely check in this case.

On the status-bar for the account, I decided it ought to say *something* when an auto-check is scheduled but skipped, if only to handle the case where account1 is sleeping and account2 is enabled. The UI only shows one account at a time, so a visible indicator that an account check happened, and the time is useful. So “account skipped’ with the time. Autocheck was scheduled, but skipped beccause of the no-check hours for that account. Hopefully that’s clear, and it it wasn’t, they could read the manual (to be updated in the next release) to find out what “account skipped” means.

Upgrading from Indy9 to Indy10

Translating the source code to Indy10 only took about an hour. It would be nice if there were a more comprehensive upgrade guide, rather than having to google one piece after another to figure things out, and pulling up grep to search the source code to figure out what include is needed now.

Here’s a summary of a few of the changes I encountered needing (hope this helps someone save some time!)


  • POP3.MaxLineLength becomes Pop.IOHandler.MaxLineLength (watch out for IOHandler being null though)
  • wsOK moved, add uses IdIMap4
  • Pop3.Connect(Timeout) breaks into two commands, Pop3.ConnectTimeout := TimeOut; Pop3.Connect()
  • StoredPathName not found. Change TIdAttachment to TIdAttachmentFile
  • POP.Capture(Dest); moved to POP.IOHandler.Capture(Dest);
  • Signatures of OnWork and OnProcessWork changed. Change const Integer param to Int64 (not const)
  • EIDSocketError not found. Import/uses IdStack
  • CommaSeperatedToStringList not found. Add import/uses IdGlobalProtocols
  • TIdText not found. Add import IdText

A few articles about porting to Indy10:
http://conferences.embarcadero.com/article/32160
http://www.indyproject.org/docsite/html/MigratingIndy10.html
http://www.indyproject.org/docsite/html/ChangesObjectHierarchy.html

But when all was said and done, that didn’t fix my disconnect problem. Looking a little more into why it was crashing disconnecting, I changed closing the connection from being conditional on the correct response to unconditional, and instantly, things start working and I have email showing up in my client! Yay.

PopTrayU to Lazarus/Free Pascal Porting Update

Well, I’ve gotten a lot of the “cosmetic” stuff fixed. Here are updated screenshots, that you can compare to the ones my last update about this project:

First, here’s the options screen.

You’ll notice it looks pretty much about right. I had to use a third-party time control (ZVDateTimeControls) to get the time picker working. Lazarus doesn’t have an equivalent of TDateTimePicker. They have a TDateEdit, but that only does calendar and not time only. But the third party one seems to work fine, though I’m not in love with the arrows on it, I’d rather see it using the native windows picker control under the hood, since cross-platform compatibility is not a primary concern of mine at the moment. But at least it’s functional for now.

Here’s the main window at the moment:

You’ll notice the main screen now looks “almost” like the real thing now. The toolbar is there, but the labels are in the wrong spot. I stumbled almost on accident onto the solution for how you do the labels on the right. Apparently you have to use TSpeedButton(s) on a TBevel instead of using a TToolbar to get labels on the right. Sounds pretty doable, but is lower priority than some of the other issues I’m dealing with.

Those tabs also don’t appear totally “right”. You’ll notice there’s some weirdness about the borders for them. The tabs are a TTabControl because they don’t have individual content, it’s really just an array of accounts it’s representing. But there’s a key difference in Lazarus from Delphi that the TTabControl is not designed to have child components, so it’s resizing it wrong to make room for the components that should be nested on the tab. This might actually be kind of involved to fix. One guy supposedly submitted a patch at one time that made it work more like Delphi, but it got rejected because it didn’t work “right” for all the different platforms Lazarus supports. So looks like I could try to track down that patch and make it into a third party control, or I could change the TTabControl to a TTabSheet, and replicate the buttons onto every tab, but that would lead to a lot more UI overhead. But either way, it’s not worth fixing unless I find a way to fix the blocking issue that could be a showstopper.

Right now the blocker issue is Indy 9. In 2005, Marco van de Voort ported Indy9 to Free Pascal, at least for 32 bit architecture, not 64 bit. But then he decided to upgrade to Indy10 so it wasn’t maintained. So, showstopper issue, Indy9 isn’t working right. I’m focusing on the “test account” button right now since that’s about the simplest network-operation the app does. Connect to the Pop3 server, login, and disconnect. Login is actually working. The problem is disconnecting. It’s reading garbage instead of “+OK” for the disconnect message, so it fails to disconnect and throws an exception that causes other problems, like skipping actually closing the connection. The problem is, using Wireshark to sniff what’s actually going on in the network, the server is actually sending the correct response back. But what PopTrayU is seeing when I step through the debugger is half of the account’s domain name, “bear.net” Stepping through the routines where it moves pointers around to find the response, it looks like it’s reading the wrong place in memory, it’s skipping right over where it should be reading, and reading from some random spot a little bit farther out that presumably contains memory that was previously used for something else. Tricky right? The code doing this is totally obscure, and has very few comments, so it might take a while to understand it well enough to figure out *why* it’s reading the wrong address when it goes to disconnect. The warnings in Lazarus that it’s doing Pointer to Integer conversions could be a hint though. Theoretically that shouldn’t mess it up on 32 bit, but you never know, seems to be doing some bad pointer math somewhere.

Interestingly, poking through the Indy10 codebase, they appear to have reworked the whole “managed buffer” that’s giving me issues and eliminated this weird pointer math. And Indy10 is officially supported in Free Pascal, so I may have to bite the bullet and upgrade. Apparently there were some non-trivial issues when Renier tried to port to Indy10 once long ago, but perhaps they would be less nasty to resolve than buffer overrun issues.

Oh, and unrelated to all of that, I also have the tray icon partly working now. The right click menu is working, but changing the icon images is not. The rules and about screens are also on the todo list if I can resolve blocker issues. The about screen lost all the strings in the tables, because they’re encoded in binary in Delphi, so I have to retype them. And the rules stuff was using some components that have to be manually ported/fixed.

Debugging Forms Ported from Delphi to Lazarus

One problem I was encountering in converting a few of the Delphi forms into Lazarus forms is that after I got to the point where everything was compiling, and even the point where I could run the application and bring up the main window, I still couldn’t successfully edit the forms properly.

I’d open the converted LFM (Lazarus form) and it would only display in code-view and not the “Unit View” where you can visually edit the UI. Go to View->Toggle Form/Unit View, which should cause it to switch to Unit view, and nothing would happen. Not so helpful. Or one time the option was greyed out entirely. With no real clear hints about why.

Clearly, something was wrong, and not a lot of feedback about what. I was unsuccessful in finding any guides online about how to troubleshoot such, so it took a bit of tinkering and guessing. So here’s what steps were actually useful in solving the problem.

1. Make sure all expected dependencies are listed in the Project Options (under Compiler Options->Paths)

First, since the form was fully working in Delphi before converting, there’s a very good chance the problem is an unknown property name or an object of an unknown type. This is probably not a totally unfamiliar to a Delphi developer who’s ever had a missing dependency on a form before. But since you’ve probably already done that or you wouldn’t be still trying to fix it…

2. Tools -> Check LFM in Editor

This brings up a window that checks for various errors in the LFM. If anything is found here, you should definitely fix them. In this example, I’d already replaced TDateTimePicker with TDateEdit in the corresponding .pas unit file, since Lazarus doesn’t have quite the exact same component available. But the form needed to be updated too.

Mind you, that wasn’t enough to make the form actually load. But now at least the form check has fixed all the problems it can. The wording on the informational dialog that tells you this could probably stand to be more clear, but  if you thought to read the title, that would be a big hint that this isn’t an error message.

In some cases I found it better to edit the fixes I wanted into the file in notepad rather than letting it automatically delete the objects/properties.

3. Make sure the LFM is open and saved, then select File -> Reload

Hmm, that’s interesting, all of a sudden I’m seeing a new error it didn’t tell me about when I first loaded the form.

It’s not the most easy to decipher error message, but essentially it’s the same sort of message you see in Delphi when you try to load a form that uses a component that’s not in the project path correctly. Stream position (presumably either in bytes or characters) is not nearly as helpful as a line number would be. But it did give me enough information to know what I’m looking for. Unfortunately, TabOrder is all over the file, because almost everything has a tab order. So I decided to take the easy way out and just wipe out all the TabOrder properties (Later I’ll recreate the necessary tab order properties using the GUI builder) and be done with it rather than trying to decipher the Stream position.

4. Turn on Lazarus logging

For one stubborn form, the one that was conveniently almost 3,000 lines long (not easy to find the problem by eye!), I found all these other steps were giving me no further errors or hints as to what was wrong. I researched whether there was any way to turn on a debug log or something for Lazarus. Maybe there’s an error happening or bug it’s not telling me about.

So (after some googling) I copied the shortcut for Lazarus from my start menu onto the desktop, added “ --debug-log=c:\temp\lazarusdebuglog.txt” to the run target, and restarted Lazarus from my new shortcut. I tried the menu option to switch the view that failed, quit lazarus to end caching on the log, and looked at the log. The log actually gave me a very good hint what was wrong.

TMainIDE.DoLoadLFM loading nested class TIdAntiFreeze needed by C:\projectpath\uMain.lfm
TMainIDE.DoLoadLFM DoLoadComponentDependencyHidden NestedClassName=TIdAntiFreeze failed for C:\projectpath\uMain.lfm

There were a couple other lines too, but clearly this was a problem. Dependency problem. I searched the lfm in text view for TIdAntiFreeze and quickly located the offending object on the form, which was easy to delete (to be fixed later). After editing that object out and saving, it was able to load in the GUI builder, and fix some of the other more important UI issues.

So hopefully these troubleshooting steps will be helpful to me or someone else down the line having to resolve similar types of problems.

Initial Stages of Porting PopTrayU to Lazarus

Yesterday I started working on trying to port PopTrayU to Free Pascal/Lazarus. The built-in converters seemed to do a good job for the most part, though they did leave hundreds of errors for me to clean up before I could even say it compiled, and its pretty far from, well, working.

But here’s where we’re at right now:

This is the main screen, and it does look fairly close to what it’s supposed to look like, but as you’ll notice, a few key UI items (the toolbars and list of messages) are missing.

On the options screen, things look even worse:

Though I’d be willing to bet that in the end, the problems with the options screen turn out to mostly be cosmetic (a list that needs to be manually repopulated), and that the main screen will turn out to be way more work to get working.

So what issues have I been running into as I port? Thanks for asking.

The CoolTrayIcon component that PopTrayU relies on for the tray icon in the windows tray is super-broken to the point where it was easier to comment out everything relating to the tray icon rather than cobble the Tray Icon component into running skeleton code. The Tray icon relies heavily on Application.Handle and Application.Hook methods to get references to the application to do snazzy things like minimizing to the tray. Those methods are conveniently not available in Lazarus. So I’m going to have to do more research about workarounds for that, because there doesn’t appear to be a straightforward “just do this instead” option.

When the Lazarus porting guide said most of the things that aren’t implemented are “things that are very windows specific” it turns out to be quite the list, and some of those components that are “wontfix” missing components are ones that the app uses.

For example, THotKey has no equivalent. THotKey is a class that hooks into the system settings to set system wide hotkeys to control PopTrayU when you’re using other programs. That’s not to say it can’t be done, but if it can be done the code is probably going to look a lot more ugly. But that’s a low-priority feature compared to say, checking your email and the tray icon being also broken.

I actually came across this handly list that shows which Delphi components do and do not have equivalents in Lazarus. Unfortunately for me, the “not included” list includes TActionManager, TActionToolBar, TPopUpActionBar, and TCustomizeDlg. I may be forgetting others. So basically, in Delphi, all the menus and toolbars used to use Actions to link the menu items to the code it runs when you click on them, and then you could drag and drop menu items into toolbars and vice versa and fully customize the toolbars, which is a really nice to have but not essential feature. Having menus and toolbars is, however, an essential feature, so I’m going to have to check out TToolbar, TActionList (that is available) and TPopupMenu which are candidate replacement classes.

Some of the more straightforward replacements that the auto-code-fixer couldn’t figure out for me were things like:

  • TTabSet -> replace with TTabControl
  • TColorBox -> add import ColorBox
  • GetTime() in SysUtils -> replace w/ Time()

There were also a couple type (struct) definitions that I had to manually add (related to hotkeys), which wasn’t a big deal other than figuring out what was missing.

One of the tricks I found handy for fixing things was keeping Delphi open at the same time and using the “Browse Symbol at Cursor” feature to plug in the name of whatever it was complaining was missing to find out where that was defined, so I could figure out whether it’s an import name that’s missing or something from one of the dependencies or delphi or wherever it’s from.

But overall, most of the issues have been with UI stuff and NOT indy stuff, so it’s looking optimistic that this is a feasible port worth continuing to pursue. I was having a couple minor issues with indy, but I think they’re minor, figuring out where to store the data.

On with the porting!