As mentioned in the last post, both the TextBox and the MultiLineTextBox respond to key repeats and moved the cursor appropriately. The implementations in both were exactly the same. They included a WoopsiTimer gadget that was started when a key was pressed and stopped when the key was released. By tracking the last key pressed, they could respond to the timer’s “action” event and move the cursor in the appropriate direction.
This approach worked perfectly, but it was somewhat cumbersome - any gadget that needed to respond to key repeats would have to implement its own copy of the solution outlined above. A better approach would be to bake it into the core of the system itself, which I have now done. The base Gadget class includes a keyRepeat() method that is called when a button on the DS is held for the required amount of time (25 frames for the initial repeat; 5 frames for subsequent repeats). All gadgets can raise key repeat events.
In other textbox news, if the string is longer than the box it is now possible to scroll the text using the d-pad. When the cursor hits either end of the box, the text will scroll one character to the left or right. The cursor will not scroll outside the boundaries of the textbox. Additionally, if the width of the text exceeds the size of the box, the horizontal alignment options are overruled and the box switches to left-aligned. This ensures that the scrolling works.
I changed the way that the gadget destructor worked back in April 2008. It was more intelligent and would recursively delete the children of a gadget that was itself being deleted. However, I’d noticed that Xcode would occasionally throw a segfault when deleting gadgets. A lot of testing later and I found the problem - the child deletion didn’t quite work properly.
The parent gadget was doing this:
for i = 0 to child count delete child[i]
Meanwhile, the child gadget was doing this:
remove self from parent
When the child removed itself from its parent, the child count reduced. Thus, children at the end of the list were not being deleted. This caused memory leaks and, in certain situations, segfaults.
I’ve changed the parent’s loop and fixed it.