#!/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