In article <466DC9D3.28768.F844A4@twegner.swbell.net>, "Tim Wegner" <twegner@swbell.net> writes:
First I need to invert the control loop for the I/O from polling to event driven using the existing driver model. Woo hoo.
That does sound challenging :-)
I just thought of an analogy while I was rototilling some garden space. Its similar to the idea that any recursive computation has an equivalent iterative computation. The compute "check for key pressed to stop" loops look like this: while (1) { if (key pressed) { if (escape) { break; } pause computation; while (! key pressed) { wait; } resume computation; } perform computation; } This is equivalent to: bool paused = false; bool done = false; while (!done) { if (key pressed) { handle_key(); } else if (idle) { do_idle_work(); } } do_idle_work() { if (paused) { return; } perform computation; } handle_key() { if (escape) { done = true; } else { paused = !paused; if (paused) { pause computation; } else { resume computation; } } } This involves a restructuring of the existing code by extracting functions (methods) from the existing functions and rearranging how they are called. However, take a look at the first while loop. This is the structure of every event driven application -- it gets events, dispatches them to handlers and if there are no events it does something with the idle time. The "done" flag is eventually set by the user clicking on the close button or selecting File / Exit from a menu. In FractInt, the trigger just happens to be the ESCAPE key instead, but its the same idea. In FractInt, you're "idle" whenever a key isn't pressed. This is why the existing mouse support fakes mouse movement as key presses -- everything is tied to the keyboard. The thing is that this key dispatching code loop is duplicated everywhere in FractInt. Duplicated code is bad. Once the existing processing loops are restructured to look like the event loops in the second code snippet, then the duplication can be eliminated by using a stack of interface pointers. The interface looks something like this: interface IKeyDispatcher { void handle_key_press(int key); void idle_work(); } Then all the duplicated dispatch loops can be collapsed into a single loop with a stack of interface pointers. When you go into a text screen, that amounts to pushing an interface onto the stack. The single event dispatching loop calls through the interface on the top of the stack to dispatch events. When you ESCape from a text screen back to the previous context, it pops its handler off the stack when processing the ESCape key. When you switch contexts you just change the current interface pointer on the top of the stack, such as when you change fractal types and the engine gets switched from standard_fractal() to cellular(). Once you're in a situation like that, then *everything* is dispatching events through a single location and you're ready to swap out your homebrew event dispatcher for the event handling mechanism in wxWidgets. -- "The Direct3D Graphics Pipeline" -- DirectX 9 draft available for download <http://www.xmission.com/~legalize/book/download/index.html> Legalize Adulthood! <http://blogs.xmission.com/legalize/>