Today was one of those days. I thought I came up with a really cool solution to block times and appointments sharing a cell span for the new appointment scheduler using JIDE. I had it all implemented yesterday and it appeared to be working nicely as I went home for the night and off to enjoy my son's band concert.
This morning I sat down and ran the program again just to see if I could get it to fail. Of course it did fail after a short time of testing. My fake data starts with one time block and two appointments with none of them overlapping. A time block is used to paint the background of the group of cells - say from 8 AM to noon - in a special hatched color pattern. This allows the provider to block a set of time for specific tasks such as OB or cancer only patients. You are allowed, encouraged actually, to schedule appointments in that time block. You can't move or resize the time block using the mouse, that is all done via a configuration dialog so you don't accidentally move it about during normal business activity. It needs to paint first and all appointments on top of it.
I had a bunch of code looking at each appointment as it was added to the schedule to see if the an existing cell span needed to be extended - either earlier start row or growing the row count. It worked most of the time unless I added appointments in a certain order and they overlapped but did not cause the cell span to grow. So the block was from 8 to noon and an appointment was from 9 to 10. It fits but I did not account for it thus I ended up adding two cell spans to JIDE table which annoys it when you try to delete them. I had added a cell span dump call to my table allowing me to see why the painting was all wacky. I tied the dump into an unused button on my test interface as I did not want the output filling up as I was dragging appointments around trying to get the problem to replicate. Once I really looked at the code I was not happy about adding a bunch more logic for special overlaps and cleaning up JIDE table Cell Spans and internal Cell Spans. Time to step back and take a new perspective.
What I decided to do is add the appointments as a collection. I can put each appointment in its column, then I can sort a column of appointments by row and row span. After sorting I can easily come up with unique cell spans. I add those spans to the JIDE grid then I also calculate which row / column to do the setValueAt call for adding appointments to a collection for that cell. You don't get paint calls for every cell in the table, only the one in the upper left corner of a cell span. I needed to consolidate all appointments for a span to that one callback spot. An earlier attempt at that had less than stellar results.
I ended up deleting a lot of code and making the logic a ton easier to debug and understand. Looking at the data to decide what to paint is also cleaner. Still runs slower on the Mac that I want so tuning will be in order but I want to get overlapped appointment painting to work first then I will tune things. I have a feeling it is JXLayer related on the Mac and I might not have much control over that. I have broken down and reconstructed the logic more than once already so no need to optimize yet.
Today's implementation appears to be pretty solid. I have been unable to get it to screw up after beating on it via lots of drag and drop and tossing numerous appointments at the grid. I even fixed a clipping issue that only occurred on the Mac. I am doing all my development on the PC but I copy the code over to the Mac as a backup being as I don't have a sandbox area in SVN to check anything in just yet. It is also good to run on more than one platform to catch any weird errors, graphical glitches or performance problems early in the process.
I have notes all over my whiteboard, scratch paper and in PSPad that I will go through so I can cross off the random thoughts that did not work. Next up is painting overlapping appointments by insetting them from the edge and tracking the mouse into them allowing you to change the Z order. Could get kind of hairy but I think the new way I am storing things is going to help. My plan today was to implement that once I felt the code was solid. Since the code was not solid I did not get around to it today. Guess that is why we have tomorrows.
Next scary piece will be implementing a pivot. Allowing time to run in the columns and column categories to run as the rows. I don't want an IF statement every other line so I might have an object ready for each layout type for processing rows vs. columns. I hate to duplicate code but if it becomes too messy it will be worth it. Double the testing for sure. Get that all in place and I get to do week and month views. Somewhere in there I will have to move this into our main application to replace the current MigLayout. It needs to be a fully working custom control before I do that so I can concentrate on the real appointment data at hand and not on fixing scrolling and painting bugs. Plus it will allow other developers here to help out with dialog boxes and all the other decorations needed by a scheduler.