Hi Sander,
bool ProcessingInterface::IsDynamicInterface() const
Is just a declaration of intentions. It's necessary for an interface to work dynamically, but it isn't sufficient. Along with returning true from IsDynamicInterface(), you need to reimplement:
bool Launch( const MetaProcess& P, const ProcessImplementation* p, bool& dynamic, unsigned& flags )
The Launch member function gets called when the user invokes your interface, for example by double-clicking a process icon, or from the Process Explorer. To start a dynamic session, a possible implementation could be (code excerpted from DynamicCropInterface.cpp):
bool DynamicCropInterface::Launch( const MetaProcess& P, const ProcessImplementation*, bool& dynamic, unsigned& /*flags*/ )
{
// ### Deferred initialization
if ( GUI == 0 )
{
GUI = new GUIData( *this );
SetWindowTitle( "DynamicCrop" );
InitControls();
UpdateControls();
}
dynamic = true;
return &P == TheDynamicCropProcess;
}
Note that we are assigning
true to
dynamic. In this way the core application knows that the interface wants to start a new dynamic session. After this function, the whole set of dynamic event handlers are available and will be called automatically by the core application when the corresponding events occur.
The "###" comment above is there because the "normal" way a processing interface initializes is by reimplementing the ProcessingInterface::Initialize() virtual member function, which is called briefly after module installation.
Deferred initialization is a technique that postpones initialization of all GUI resources until the first call to Launch(). This technique saves a lot of time and memory and is currently used by all standard interfaces; it is of course the recommended way to initialize newly created interfaces (eventually, Initialize() will be obsoleted).
It seems I'm missing the part where the framework tells my code that a view has been selected so I can grab it.
Actually, that doesn't happen. Your interface must select one or more views explicitly through calls to:
void View::AddToDynamicTargets();
A
dynamic target is a view that is being controlled by a dynamic interface. In some way your interface
owns all dynamic targets during a dynamic session, and the core ensures that no dynamic target can be closed or modified. Following a strict object-oriented methodology, even your dynamic interface is not allowed to modify one of its dynamic targets (it must explicitly remove it from the dynamic targets set with View::RemoveFromDynamicTargets() before attempting to change it).
Your interface is free to use the most appropriate method to select one or more dynamic targets. However, you must do it in an event handler. The usual way is to wait until the first call to DynamicMousePress(). This is what DynamicCrop, CloneStamp, DBE, etc. do. By "first call" we mean the first call after the Launch() invocation that assigns
true to the
dynamic reference argument, as shown above.
Now the bad news
I guess what you're trying to do doesn't require a dynamic interface at all
Are you trying to write a tool that does "something" whenever the user clicks on a view? I ask this because you're reimplementing WantsReadoutNotifications(). In fact, using the readout notification system is the recommended way to implement
relatively simple tools that don't require the fully-fledged interactive functionality provided by dynamic interfaces. Note that
relatively simple here refers just to interactivity; your interface can do extremely sophisticated things using only readout notifications.
To be a client of the readout notification system, your interface must reimplement the following virtual member functions of ProcessingInterface:
virtual bool WantsReadoutNotifications() const
{
return true; // to receive readout notifications.
}
virtual void BeginReadout( const View& v )
{
// This is called when the user clicks on a view.
}
virtual void UpdateReadout( const View& v, const DPoint& p, double R, double G, double B, double A )
{
// Called when a new pixel readout is available.
// *** Edited: Of course, the R,G,B,A pixel sample values are in the [0,1] range, irrespective of v's
// data type. Sure you already guessed this, but just wanted to point out this important fact.
}
virtual void EndReadout( const View& v )
{
// Called when the user releases the mouse after a readout operation.
}
By reimplementing just these four member functions, your interface can do
almost everything 8)
Does this help you? (hope so
)