I had to convert some modal dialogs to non-modal, and I abstracted out
some of what I was doing. The result is a mixin that uses closures to
make non-modal dialogs almost as easy to implement as modal ones. It''s
going into the next release of FoxTails, but since it stands alone and
is quite simple, I''m submitting it here. Hope it helps someone.
The key to using this mixin is in the initialization of the main window:
nonModalButton.connect(SEL_COMMAND) do
@dialog.execute_nonmodal do |accepted|
@label.text = accepted ? "Dialog accepted" : "Dialog
cancelled"
end
end
The code block is saved away and called later when the dialog is exited.
But since it''s closure, you can operate on local vars, etc. to apply
the
result of the dialog. Normally, the way non-modal dialogs interact with
their callers is much more awkward than in the modal case, AFAICT.
-------------- next part --------------
require ''fox''
require ''fox/responder''
include Fox
module FoxTails
# Module to include in FXDialogBox to provide an easy nonmodal version
# of execute.
module FTNonModal
include Responder
def initialize(*args)
super if defined?(super)
FXMAPFUNC(SEL_COMMAND, FXDialogBox::ID_CANCEL, :onCmdCancel)
FXMAPFUNC(SEL_COMMAND, FXDialogBox::ID_ACCEPT, :onCmdAccept)
end
# Creates and shows the dialog, and registers the associated block to be
# called when the dialog is closed. The block is passed a boolean argument
# which is true if and only if the dialog was accepted.
def execute_nonmodal(placement = PLACEMENT_CURSOR, &block)
@__FTNonModal_block = block
create
show placement
end
def onCmdCancel(*args) # :nodoc:
on_nonmodal_close(false)
end
def onCmdAccept(*args) # :nodoc:
on_nonmodal_close(true)
end
# Called when dialog is closed, with _accepted_ equal to true if and only if
# the user accepted the dialog.
def on_nonmodal_close(accepted)
@__FTNonModal_block[accepted]
##return 0 -- why isn''t this enough to close window?
## oh well, let''s immitate FXTopWindow:
getApp().stopModal(self, accepted ? 1 : 0)
hide()
end
end
end
class TestDialog < FXDialogBox
include FoxTails::FTNonModal
def initialize(*args)
super
buttons = FXHorizontalFrame.new(self,
LAYOUT_SIDE_BOTTOM|FRAME_NONE|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH)
FXButton.new(buttons, "&Accept", nil, self, ID_ACCEPT,
FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
FXButton.new(buttons, "&Cancel", nil, self, ID_CANCEL,
FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
end
end
class MainWindow < FXMainWindow
def initialize(app)
super(app, "NonModal test", nil, nil, DECOR_ALL)
frame = FXHorizontalFrame.new(self)
nonModalButton = FXButton.new(frame, "&Non-Modal Dialog...",
nil, nil, 0,
FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_X|LAYOUT_CENTER_Y)
nonModalButton.connect(SEL_COMMAND) do
@dialog.execute_nonmodal do |accepted|
@label.text = accepted ? "Dialog accepted" : "Dialog
cancelled"
end
end
@label = FXLabel.new(frame, "Dialog not invoked yet")
@dialog = TestDialog.new(getApp(), "NonModal Dialog",
DECOR_TITLE|DECOR_BORDER)
show
end
end
if __FILE__ == $0
application = FXApp.new("NonModal", "FoxTailsTest")
window = MainWindow.new(application)
application.create
application.run
end