#22 new
lyle (at lylejohnson)

Enhancement for non-modal dialogs

Reported by lyle (at lylejohnson) | November 11th, 2009 @ 10:14 PM

As submitted by Joel VanderWerf:

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.

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

No comments found

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

FXRuby is a library for developing powerful and sophisticated cross-platform graphical user interfaces (GUIs) for your Ruby applications. It’s based on the FOX Toolkit, a popular open source C++ library developed by Jeroen van der Zijp. What that means for you as an application developer is that you’re able to write code in the Ruby programming language that you already know and love, while at the same time taking advantage of the performance and functionality of a featureful, highly optimized C++ toolkit.

Shared Ticket Bins

People watching this ticket

Tags

Pages