Goldenseal Pro- Breakdown Table Redesign (Dec 29)

For software designers, a table is anything that shows a list of items in rows. Sometimes it has multiple columns of data, sometimes just one. For modern Mac OS, tables are made with NSTableView, built into Apple’s Cocoa framework.

In Goldenseal, we use tables for many things. Once we figured out the basics of NSTableView, we got most of them working fine in Goldenseal Pro, also.

The most complicated tables in Goldenseal are breakdown tables. Those show detailed line items in Estimates, Sales, Material Purchases, etc. They work kinda like a spreadsheet, but on steroids. Each row has several different types of data entry cells— text, popup lists, check boxes, padlocks. Some cells can change their type, depending on what’s in other cells.

A year ago, breakdown tables were already showing data, so we were optimistic about them. We just had to add data entry. Click and type, or click and choose from a menu, or click to unlock a padlock.

Alas, our staff has really struggled with that part. We’ve tried many different approaches. Each got some things working OK, but then hit a dead end. Each time we took a break and worked on other things for a while, then tried again.  Each failure made it all the more frustrating.

During holiday break this week, there was a “eureka” moment. Maybe the problem is bigger than just getting table cells to show popup menus. Maybe breakdown tables need a more extreme solution. Maybe the current design is fundamentally wrong.

Breakdown tables were also a struggle in the original Goldenseal. They took over a year of programmer time, with lots of futzing and fiddling. They’ve had the most bugs since then. Users often find them confusing. They still aren’t perfect.

Part of the problem is that the tables are very dense. Each line item only gets a little rectangular strip of screen space, maybe 1/4″ x 7″. It’s not many pixels to work with. Even worse, many table cells pop up a list of choices. That has to happen from a teensy box about 1/4″ x  1″. It’s too small for good interface design. Overall, the crowding makes breakdowns hard to program, and hard for users to understand.

For Goldenseal Pro, we already decided to put breakdown tables into a separate window, rather than in the main layout. It’s better use of screen space. Also, now there is room for useful buttons: you can click the Insert Row button, instead of control-click, click Delete Row instead of control-shift-click. The new setup is much more obvious for beginners.

We will now make the same interface change for data entry into table rows. Instead of typing or list-choosing directly in the row, you’ll double-click and see a data entry window. It will have regular data entry fields in a comfy layout, with helpful buttons.

For our programmers, the change saves a few thousand lines of code, and lots of frustration. No more futzing with rows and columns, and cramped interface design. In fact, breakdowns will have the same interface that we already use for lists, so we can reuse that code. Simpler design, which means fewer bugs.

For beginners, the new interface will be much easier to understand. Useful buttons, and less clutter. Easier for tired data entry staff, as well.

The change probably will be hardest for our long-time users, especially those who started out on the MacNail estimating spreadsheet. Goldenseal breakdowns still look and behave a bit like an Excel spreadsheet. Goldenseal Pro breakdowns will be less so.

Hopefully, the advantages will offset the annoyances, even for users who love Excel.

Dennis Kolva
Programming Director



Goldenseal Pro Progress- Breakdowns & Cocoa (Dec 21)

Last week we finished redoing the basic windows setup in Goldenseal Pro for Mac. This time we built the code with the latest OS version (and the latest version of Apple’s Xcode development tool). Xcode now gives better log messages for improper setup, so we could eliminate the errors, one by one.  Finally, everything was proper.

As a result, Goldenseal Pro now runs fine for all OS versions. The former crashes are gone. All windows are also resizable, now. They used to be stubbornly fixed-size, probably because their constraints weren’t valid.

There is still one more big hurdle to overcome.  Our staff has started on breakdown tables several times, but every time we get stuck. Most things work OK, but the basic interface is just not right. We want to have an editable text field appear promptly when you click in a cell. Unfortunately, that basic task has been extremely challenging to pull off.

What we finally figured out is that Apple’s table class (NSTableView) is designed for Finder-like lists.  To change a file name in the Macintosh Finder, you click in the text, then wait a second, then click again. It works that way so you won’t accidentally rename files when you really just want to double-click to open a file, or click-and-drag to move it.

Unfortunately, click-wait-click is not a good fit for Goldenseal Pro. That behavior is deeply baked into NSTableView.

To solve problems like this in C++ and PowerPlant, we would set breakpoints in the code, and then step through line by line to see how the library works. Eventually that leads to a clear understanding of the mechanics. Then, eventually, we can write code that does the job reliably.

Unfortunately, Apple’s Cocoa library is header-only.  Stepping into it show machine language. It is much, much harder to understand than C or C++ code. Even worse, it doesn’t show any of the comments that good programmers add, to help others understand their code. As a result, Cocoa is pretty much a ‘black box’. We have to try things, and see what they do. Then try other things. Maybe we can eventually understand the code, and maybe not.

Best guess right now is another week until we get the breakdown tables working properly, when you click on a cell. After that it will go much faster. Most of the rest is already programmed.

Dennis Kolva
Programming Director

Goldenseal Pro Progress- Containers & Constraints (Dec 11)

Every computer app needs to position stuff on the screen. Usually it takes four coordinates for each item: horizontal and vertical positions, plus height and width. The whole setup is called a frame, since it defines a rectangle that encloses the field, button, window or whatever.

Numbers are fine for computers, but not great for humans. We programmers would rather use a drawing program to lay out the screen appearance. Then we can see what we’re doing.

Goldenseal includes a simple drawing program in the Custom Layouts command. It lets anyone drag around fields, and change the appearance of data entry windows, printed forms or reports. Our staff used Custom Layouts to set up the stock layouts. Users can customize anything with it.

To set up the rest of the interface for Goldenseal, our staff used Constructor. It was a simple drawing program that came with PowerPlant, the library we used to build the first Goldenseal. Constructor set up the rest of the appearance that Custom Layouts couldn’t handle.

For Goldenseal Pro, we use similar visual drawing environments built into Xcode (for Mac) and Visual Studio (for Windows). They save a lot of time.

Frames are good enough for a simple screen layout. Everything has its size and place. But, what happens when you resize the window? These days, people expect stuff to rearrange, and stay useful whatever the size and shape of the window they are in. Unfortunately, a dynamic layout is much harder to set up than a static one. There are many complications.

One layout tool that every programming library uses is containers. All the contents of a container will move together. As a bonus, containers make programming a bit tidier. PowerPlant called them panes, Apple’s Cocoa framework calls them views, and Microsoft’s MFC calls them windows (in Windows programming, everything is a window). Containers are generally a good idea, but they do add some complexity.

Cocoa also has separate controllers for each view, as part of their MVC architecture (model/view/controller). Another good idea, but it adds even more complexity.  The main window in Goldenseal Pro has 9 different views, each with their own controller. Even worse, we need to swap several different views into the top bar and main record area, depending on what you are doing. It took a few months to get it all working correctly.

The other layout tool found in modern programming libraries is constraints. Basically, they are a way to bind each item to its neighbors, so it knows where to go when its container moves or resizes.

PowerPlant and Constructor had a very simple constraints system, but we rarely used it.

For the Mac version of Goldenseal Pro, it’s required that we use the constraints built into the Cocoa framework. We tried doing without it, but just got errors. Unfortunately, they are a confusing mess.

Apple started out with a ‘struts and springs’ metaphor, pretty much like connecting screen items with paper clips and rubber  bands. Then they replaced it with an auto-layout feature in the drawing view. It works great for some things, but can’t be used everywhere.

In OS 10.7, Apple added a NSLayoutConstraint class.  Every view needs at least four constraints, and each looks something like this in the code:

NSLayoutConstraint *rightConstraint = [NSLayoutConstraint                                                                                constraintWithItem : statusBar
                                                    attribute : NSLayoutAttributeTrailing
                                                    relatedBy : NSLayoutRelationEqual
                                                    toItem : theRecordView
                                                    attribute : NSLayoutAttributeTrailing
                                                    multiplier : 1.0    constant : 0];
Throw in a few hundred of those, and the code gets very cluttered. Finally, in OS 10.11, they added yet another constraint system, with much simpler code. Now each constraint looks like this:
[statusBar.topAnchor constraintEqualToAnchor :
                                                  theRecordView.topAnchor].active = YES;

It’s much more palatable, and less prone to stupid errors.

Over the past two years, we used frames to lay out some things in Goldenseal Pro. For others we used constraints, with some of each type. The screens looked OK, but we were definitely bumbling around and didn’t always do the right thing. Sometimes we accidentally added duplicate constraints. Some conflicted with others. Some were just plain wrong. Those inconsistencies are probably why the code crashes when we build with the latest versions of Mac OS.

This week we are redoing all the windows to use the most recent Cocoa constraint system. It’s going to be all anchors.  Newer versions of Xcode are better at reporting errors, so I think we can finally get it right.

Dennis Kolva
Programming Director