Post by Chuck PeltoHow does one manage control of activities between a floating window,
e.g., a pallete, and the document window where the work is being done?
I've tried a few different approaches to this in RB. The one I like
best (so far) uses a small set of shared methods that I implement for
each palette window class. Here they are for my ToolsPalette class:
//////////////////////////////
//////////////////////////////
Shared Function InstanceThatIsOpen() As ToolsPalette
// If an instance of this class is open, return it.
// Otherwise return nil.
for i as integer = 0 to WindowCount-1
if Window(i) isA ToolsPalette then
return ToolsPalette(Window(i))
end if
next i
return nil
End Function
//////////////////////////////
Shared Sub InvalidateClients()
// This routine should be called when client availability for
// this window has changed. Typically this is done when a
// document window has been deactivated or closed, or when
// this palette window has just been opened.
dim Instance as ToolsPalette = InstanceThatIsOpen
if Instance <> nil then
Instance.UpdateControls // a palette-specific update method
end if
End Sub
//////////////////////////////
Shared Function IsOpenAndFrontmost() As boolean
// Returns true if the window is "in use"; that is, like
// the function name says, if it's open and it is the
// frontmost palette.
//
// Typically used for deciding whether to put a check
// mark next to a Window menu item for this palette.
dim Instance as ToolsPalette = InstanceThatIsOpen
return (Instance <> nil) and (Instance = Window(0))
End
//////////////////////////////
Shared Sub Toggle()
// If the window is open and frontmost, close it.
// Otherwise, open it if needed and make it frontmost.
// Typically used to handle a user selection of the
// corresponding menu item.
dim Instance as ToolsPalette = InstanceThatIsOpen
if Instance = nil then
Instance = new ToolsPalette // make a new one if we didn't have one
elseif IsOpenAndFrontmost then
Instance.Close
else
Instance.Show // makes it frontmost
end if
End Sub
//////////////////////////////
//////////////////////////////
The first routine is used by the others, which are called from various
external events as described in the comments. For instance, my
document window class has this method:
Private Sub UpdatePalettes()
ImageColorsPalette.InvalidateClients
ImageGridPalette.InvalidateClients
MiniViewPalette.InvalidateClients
ToolsPalette.InvalidateClients
End Sub
This method is called by the Activate, Deactivate, and Close events
for my document window class, so that when the active document window
changes, all relevant palettes will get notified if they are open.
(You'd probably want to be more careful about updates if you were
doing a potentially CPU-intenstive task like typing in an EditField
and updating the word count, for instance.)
If you're not familiar with RB shared methods, they are methods in a
class that are called without reference to a particular instance of
the class. If you're using a version of RB that doesn't support shared
methods, you can implement these methods in modules instead. I like
them as part of the class simply because it means fewer RB code chunks
to keep track of.
Apart from the class name, the set of methods is identical for every
palette window class. Thus if RB had macros, it would allow
implementation of these routines with one line of code per palette
window class. OO purists will scoff at this notion, and doubtless
offer their own suggestions for making things even cleaner and
eliminating the small dependencies that remain here. I can't wait...
:)
lj