Autoresizing NSTextFields are now working quite well, except in one instance – when there are several of them stacked and the window is resized several times very rapidly. I’ve left this alone for now while tackling another problem: text editing. Let me explain this a little.
One of my basic UI elements is a fast hex editor view. Here’s what it looks like at present:
Three columns, hex displacement at the left, hex characters in the center, MacOSRoman (or any other encoding) to the right. All in a scrolling view. That’s where things began to get strange. For normal Cocoa use, you’d normally define an NSTextView inside an NSScrollView. The three columns might be done by NSTextBlocks, as this will be Tiger-only. Or three different NSTextContainers, each one referencing an aspect of the same NSTextStorage…
The main stumbling point here is, I want to be able to edit very large files with no performance penalty. Files tens of gigabytes in size or even larger. All the standard Cocoa text objects above are out; they use 32-bit offsets and ranges for text sizes and selections, meaning things are limited to 4GB (or even 2GB in some cases). Also, NSTextView becomes slow as molasses well before text sizes reach those magnitudes, as the entire text needs to be laid out first to determine line breaks. Also, RAM requirements to generate the hex interpretation go up – remember a standard Mac OS X app can allocate just a little over 2GB of RAM. Finally, NSScrollView uses floats to track the scroll thumb position, meaning that scroll tracking becomes imprecise when you’re trying to track millions of lines.
Well, my fate apparently is to recode most of the NeXT-era UI widgets anyway – see RBSplitView. I tackled the scroller problem first, as I needed it for the file browser anyway, and soon had a special scroll view that tracked scrolling positions with unsigned 64-bit displacements – large enough for the largest file supported by Mac OS X – and faster and simpler than the standard one. It basically consists of the vertical NSScroller and the empty (document) space to its left; no intervening NSClipView. Any subviews are relocated by the offset when the scroller changes and drawing is optimized to the visible portion.
I also put in the option to have the view’s delegate redraw the visible portion directly – this was the idea I had to optimize the hex editor. Indeed, drawing is very fast; I have my own cached CoreGraphics bitmaps of the characters, and blit them to the visible portion of the sscroll view. And only the necessary part of the displayed file needs to be accessed, thanks to mapping only that part to memory with mmap(). And putting in editing later would be easy once the display portion is finished…
Famous last words. Turns out that the Cocoa text system is rather more complex than I expected – the standard NSTextView/NSTextField objects hide that very successfully from the “normal” developer. After several days of reading the very terse docs, and trying to find out which methods are called where, I’m finally at a point where the normal text input methods are working. However, I still can’t figure out how the standard copy/cut/paste menu items are enabled, and the whole process is still too clunky for wider use.
Stay tuned for developments…