Skip to content
Snippets Groups Projects
scribble-orig.rb 5.24 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/usr/bin/env ruby
    
    require 'fox16'
    require 'fox16/responder'
    require 'fox16/colors'
    
    include Fox
    
    class ScribbleWindow < FXMainWindow
    
      include Responder
    
      def initialize(app)
        # Call base class initializer first
        super(app, "Scribble Application", nil, nil, DECOR_ALL,
          0, 0, 800, 600)
    
        # Message identifiers for this class
        identifier :ID_CANVAS, :ID_CLEAR
    
        # And here's the message map for this class
        FXMAPFUNC(SEL_PAINT,             ID_CANVAS, :onPaint)
        FXMAPFUNC(SEL_LEFTBUTTONPRESS,   ID_CANVAS, :onMouseDown)
        FXMAPFUNC(SEL_LEFTBUTTONRELEASE, ID_CANVAS, :onMouseUp)
        FXMAPFUNC(SEL_MOTION,            ID_CANVAS, :onMouseMove)
        FXMAPFUNC(SEL_COMMAND,           ID_CLEAR,  :onCmdClear)
        FXMAPFUNC(SEL_UPDATE,            ID_CLEAR,  :onUpdClear)
    
        # Construct a horizontal frame to hold the main window's contents
        @contents = FXHorizontalFrame.new(self,
          LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0)
    
        # Left pane contains the canvas
        @canvasFrame = FXVerticalFrame.new(@contents,
          FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT,
          0, 0, 0, 0, 10, 10, 10, 10)
    
        # Place a label above the canvas
        FXLabel.new(@canvasFrame, "Canvas Frame", nil,
          JUSTIFY_CENTER_X|LAYOUT_FILL_X)
    
        # Horizontal divider line
        FXHorizontalSeparator.new(@canvasFrame, SEPARATOR_GROOVE|LAYOUT_FILL_X)
    
        # Drawing canvas
        @canvas = FXCanvas.new(@canvasFrame, self, ID_CANVAS,
          LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
    
        # Right pane for the buttons
        @buttonFrame = FXVerticalFrame.new(@contents,
          FRAME_SUNKEN|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT,
          0, 0, 0, 0, 10, 10, 10, 10)
    
        # Label above the buttons
        FXLabel.new(@buttonFrame, "Button Frame", nil,
          JUSTIFY_CENTER_X|LAYOUT_FILL_X)
    
        # Horizontal divider line
        FXHorizontalSeparator.new(@buttonFrame,
          SEPARATOR_RIDGE|LAYOUT_FILL_X)
    
        # Button to clear the canvas
        FXButton.new(@buttonFrame, "&Clear", nil, self, ID_CLEAR,
          FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,
          0, 0, 0, 0, 10, 10, 5, 5)
    
        # Exit button
        FXButton.new(@buttonFrame, "&Exit", nil, app, FXApp::ID_QUIT,
          FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,
          0, 0, 0, 0, 10, 10, 5, 5)
    
        # Initialize other member variables
        @drawColor = FXColor::Red
        @mouseDown = false
        @dirty = false
      end
    
      # Create and show the main window
      def create
        super                  # Create the windows
        show(PLACEMENT_SCREEN) # Make the main window appear
      end
    
      # Mouse button was pressed somewhere
      def onMouseDown(sender, sel, ptr)
        @canvas.grab
        @mouseDown = true
        return 1
      end
    
      # Mouse has moved, so draw a line
      def onMouseMove(sender, sel, event)
        if @mouseDown
          # Get device context for the canvas
          dc = FXDCWindow.new(@canvas)
    
          # Set the foreground color for drawing
          dc.setForeground(@drawColor)
    
          # Draw a line from the previous mouse coordinates to the current ones
          dc.drawLine(event.last_x, event.last_y, event.win_x, event.win_y)
    
          # We have drawn something, so now the canvas is dirty
          @dirty = true
    
          # Release the DC immediately
          dc.end
        end
        return 1
      end
    
      # Mouse button released
      def onMouseUp(sender, sel, event)
        @canvas.ungrab
        if @mouseDown
          # Get device context for the canvas
          dc = FXDCWindow.new(@canvas)
    
          # Set the foreground color for drawing
          dc.setForeground(@drawColor)
    
          # Draw a line from the previous mouse coordinates to the current ones
          dc.drawLine(event.last_x, event.last_y, event.win_x, event.win_y)
    
          # We have drawn something, so now the canvas is dirty
          @dirty = true
    
          # Mouse no longer down
          @mouseDown = false
    
          # Release the DC immediately
          dc.end
        end
        return 1
      end
    
      # Paint the canvas
      def onPaint(sender, sel, event)
        dc = FXDCWindow.new(@canvas, event)
        dc.setForeground(@canvas.backColor)
        dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
        dc.end
      end
    
      # Handle the clear message
      def onCmdClear(sender, sel, ptr)
        dc = FXDCWindow.new(@canvas)
        dc.setForeground(@canvas.backColor)
        dc.fillRectangle(0, 0, @canvas.width, @canvas.height)
        @dirty = false
        dc.end
        return 1
      end
    
      # This function handles the update message sent by the Clear button
      # to its target. Every widget in FOX receives a message (SEL_UPDATE)
      # during idle processing, asking it to update itself. For example,
      # buttons could be enabled or disabled as the state of the application
      # changes.
      #
      # In this case, we'll disable the sender (the Clear button) when the
      # canvas has already been cleared (i.e. it's "clean"), and enable it when
      # it has been painted (i.e. it's "dirty").
      #
      def onUpdClear(sender, sel, ptr)
        message = @dirty ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE
        sender.handle(self, MKUINT(message, SEL_COMMAND), nil)
        return 1
      end
    end
    
    def run
      # Construct the application object
      application = FXApp.new('Scribble', 'FoxTest')
      
      # Construct the main window
      scribble = ScribbleWindow.new(application)
      
      # Create the application
      application.create
      
      # Run the application
      application.run
    end
    
    run