blob: 9783f4e180d9c80e3ab62238997f9010bcc0b243 [file] [log] [blame]
###
### This demonstration script creates a canvas widget showing a 2-D
### plot with data points that can be dragged with the mouse.
###
### It is a ripoff of the plot.tcl demo from the tk 8.0 distribution
### All I did was to add the code to plot the fitted regression line.
# Copyright (C) 2000-2008 The R Core Team
require(tcltk) || stop("tcl/tk library not available")
require(graphics); require(stats)
local({
have_ttk <- as.character(tcl("info", "tclversion")) >= "8.5"
if(have_ttk) {
tkbutton <- ttkbutton
tkframe <- ttkframe
tklabel <- ttklabel
}
tclServiceMode(FALSE) # don't display until complete
top <- tktoplevel()
tktitle(top) <- "Plot Demonstration"
msg <- tklabel(top,
font="helvetica",
wraplength="4i",
justify="left",
text="This window displays a canvas widget containing a simple 2-dimensional plot. You can doctor the data by dragging any of the points with mouse button 1.")
tkpack(msg, side="top")
buttons <- tkframe(top)
tkpack(buttons, side="bottom", fill="x", pady="2m")
dismiss <- tkbutton(buttons, text="Dismiss",
command=function()tkdestroy(top))
tkpack(dismiss, side="left", expand=TRUE)
canvas <- tkcanvas(top, relief="raised", width=450, height=300)
tkpack(canvas, side="top", fill="x")
plotFont <- "Helvetica 18"
tkcreate(canvas, "line", 100, 250, 400, 250, width=2)
tkcreate(canvas, "line", 100, 250, 100, 50, width=2)
tkcreate(canvas, "text", 225, 20, text="A Simple Plot",
font=plotFont, fill="brown")
# X tickmarks & labels
for (i in 0:10) {
x <- 100 + i * 30
tkcreate(canvas, "line", x, 250, x, 245, width=2)
tkcreate(canvas, "text", x, 254,
text=10*i, anchor="n", font=plotFont)
}
# Y tickmarks & labels
for (i in 0:5) {
y <- 250 - i * 40
tkcreate(canvas, "line", 100, y, 105, y, width=2)
tkcreate(canvas, "text", 96, y,
text=formatC(50*i,format="f",digits=1),
anchor="e", font=plotFont)
}
# The (original) data
points <- matrix(c(12, 56,
20, 94,
33, 98,
32, 120,
61, 180,
75, 160,
98, 223), ncol=2, byrow=TRUE)
## `self-drawing' point object
point.items <- apply(points, 1, function(row) {
x <- 100 + 3 * row[1]
y <- 250 - 4/5 * row[2]
item <- tkcreate(canvas, "oval", x - 6, y - 6, x + 6, y + 6,
width=1, outline="black",
fill="SkyBlue2")
tkaddtag(canvas, "point", "withtag", item)
item
})
plotDown <- function(x, y) {
## This procedure is invoked when the mouse is pressed over one
## of the data points. It sets up state to allow the point
## to be dragged.
##
## Arguments:
## x, y - The coordinates of the mouse press.
x <- as.numeric(x)
y <- as.numeric(y)
tkdtag(canvas, "selected")
tkaddtag(canvas, "selected", "withtag", "current")
tkitemraise(canvas,"current")
lastX <<- x
lastY <<- y
}
plotMove <- function(x, y) {
## This procedure is invoked during mouse motion events.
## It drags the current item.
##
## Arguments:
## x, y - The coordinates of the mouse.
x <- as.numeric(x)
y <- as.numeric(y)
tkmove(canvas, "selected", x - lastX, y - lastY)
lastX <<- x
lastY <<- y
}
### FIXME : Don't allow points to be moved outside the canvas !!
plotLine <- function(){
coords <- lapply(point.items,
function(item)
as.double(tkcoords(canvas,item)))
x <- sapply(coords, function(z) (z[1]+z[3])/2)
y <- sapply(coords, function(z) (z[2]+z[4])/2)
lm.out <- lm(y~x)
x0 <- range(x)
y0 <- predict(lm.out, data.frame(x=x0))
tkcreate(canvas, "line", x0[1], y0[1], x0[2], y0[2], width=3)
}
line <- plotLine()
lastX <- 0
lastY <- 0
tkitembind(canvas, "point", "<Any-Enter>",
function() tkitemconfigure(canvas, "current",
fill="red"))
tkitembind(canvas, "point", "<Any-Leave>",
function() tkitemconfigure(canvas, "current",
fill="SkyBlue2"))
tkitembind(canvas, "point", "<1>", plotDown)
tkitembind(canvas, "point", "<ButtonRelease-1>",
function(x){
tkdtag(canvas, "selected")
tkdelete(canvas, "withtag", line)
line <<- plotLine()
})
tkbind(canvas, "<B1-Motion>", plotMove)
tclServiceMode(TRUE)
cat("******************************************************\n",
"The source for this demo can be found in the file:\n",
file.path(system.file(package = "tcltk"), "demo", "tkcanvas.R"),
"\n******************************************************\n")
})