home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v941.tgz
/
icon.v941src.tar
/
icon.v941src
/
ipl
/
gprocs
/
bevel.icn
< prev
next >
Wrap
Text File
|
2000-07-29
|
15KB
|
535 lines
############################################################################
#
# File: bevel.icn
#
# Subject: Procedures for drawing beveled objects
#
# Author: Gregg M. Townsend
#
# Date: April 1, 1997
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# These procedures draw objects having a raised or sunken appearance.
#
# BevelReset(win) sets/resets shading colors.
#
# BevelCircle(win, x, y, r, bw) draws a beveled circle.
#
# BevelDiamond(win, x, y, r, bw) draws a beveled diamond.
#
# BevelTriangle(win, x, y, r, o, bw) draws a beveled triangle.
#
# BevelSquare(win, x, y, r, bw) draws a beveled square.
#
# FillSquare(win, x, y, r) fills a square.
#
# FillDiamond(win, x, y, r) fills a diamond.
#
# FillTriangle(win, x, y, r, o) fills a triangle.
#
# RidgeRectangle(win, x, y, w, h, bw) draws a ridged rectangle.
#
# GrooveRectangle(win, x, y, w, h, bw) draws a grooved rectangle.
#
# BevelRectangle(win, x, y, w, h, bw) draws a beveled rectangle.
#
# DrawRidge(win, x1, y1, x2, y2, w) draws a ridged line.
#
# DrawGroove(win, x1, y1, x2, y2, w) draws a grooved line.
#
############################################################################
#
# These procedures allow the drawing of buttons and other objects
# with a three-dimensional appearance. They are intended to be
# used like other graphics primitives (DrawRectangle() etc.).
# However, this abstraction fails if the background color changes
# or if clipping is set, due to the use of cached graphics contexts.
#
# BevelReset(win) -- set/reset colors for beveling
# This procedure is called automatically by the others.
# It can be called explicitly if the background color is changed.
#
# BevelCircle(win, x, y, r, bw) -- draw beveled circle
# BevelDiamond(win, x, y, r, bw) -- draw beveled diamond
# BevelTriangle(win, x, y, r, o, bw) -- draw beveled triangle
# BevelSquare(win, x, y, r, bw) -- draw beveled square
# These procedures draw a figure centered at (x,y) and having
# a "radius" of r. bw is the bevel width, in pixels.
# o is the triangle orientation: "n", "s", "e", or "w".
#
# FillSquare(win, x, y, r) -- fill square centered at (x,y)
# FillDiamond(win, x, y, r) -- fill diamond centered at (x,y)
# FillTriangle(win, x, y, r, o) -- fill triangle centered at (x,y)
# These procedures complement the beveled outline procedures
# by filling a figure centered at (x,y). Fillcircle is already
# an Icon function and so is not included here.
#
# RidgeRectangle(win, x, y, w, h, bw) -- draw ridged rectangle
# GrooveRectangle(win, x, y, w, h, bw) -- draw grooved rectangle
# BevelRectangle(win, x, y, w, h, bw) -- draw beveled rectangle
# These procedures draw a rectangle with the given external
# dimensions and border width. Beveled rectangles are raised
# if bw > 0 or sunken if bw < 0.
#
# DrawRidge(win, x1, y1, x2, y2, w) -- draw a ridged line
# DrawGroove(win, x1, y1, x2, y2, w) -- draw a grooved line
# These procedures draw a groove or ridge of width 2 at any angle.
# If w = 0, a groove or ridge is erased to the background color.
#
# For BevelSquare() and FillSquare(), the width drawn is 2 * r + 1,
# not just 2 * r. This is necessary to keep the visual center at the
# specified (x, y) and is consistent with the other centered procedures
# and the built-in function FillCircle.
#
############################################################################
#
# Includes: vdefns
#
############################################################################
#
# Links: graphics
#
############################################################################
#
# Requires: Version 9 graphics
#
############################################################################
$include "vdefns.icn"
link graphics
global bev_table
record bev_record(shadow, hilite)
# BevelReset(win) -- set/reset colors for beveling
#
# Called automatically the first time a beveling procedure is called;
# must also be called explicitly if the background color is changed.
# (Pale, weak background colors work best with beveling.)
procedure BevelReset(win) #: set colors for beveled drawing
local b, h, l, s, hilite, shadow, lhilite, lshadow
/win := &window
/bev_table := table()
if b := \bev_table[win] then {
Uncouple(b.hilite)
Uncouple(b.shadow)
b := &null
}
if WAttrib(win, "depth") >= 4 then {
HLS(ColorValue(Bg(win))) ? {
h := tab(many(&digits))
move(1)
l := tab(many(&digits))
move(1)
s := tab(0)
}
case l of {
0 <= l < 10 & l: { lshadow := 25; lhilite := 50 }
10 <= l < 25 & l: { lshadow := 0; lhilite := l + 25 }
25 <= l < 75 & l: { lshadow := l - 25; lhilite := l + 25 }
75 <= l < 90 & l: { lshadow := l - 25; lhilite := 100 }
default: { lshadow := 50; lhilite := 75 }
}
s /:= 2
shadow := Clone(win, "fg=" || HLSValue(h || ":" || lshadow || ":" || s),
"linewidth=1", "linestyle=solid", "fillstyle=solid", "drawop=copy")
hilite := Clone(shadow,
"fg=" || HLSValue(h || ":" || lhilite || ":" || s))
b := bev_record(\shadow, \hilite)
}
if /b then {
shadow := Clone(win,
"linewidth=1", "linestyle=solid", "fillstyle=solid", "drawop=copy")
hilite := Clone(shadow, "fillstyle=textured", "pattern=gray")
b := bev_record(shadow, hilite)
}
bev_table[win] := bev_record(shadow, hilite)
return win
end
# bev_lookup(win) -- look up and return bev_record for a window.
#
# (Internal procedure)
procedure bev_lookup(win)
local b, dx, dy
b := \(\bev_table)[win] | bev_table[BevelReset(win)]
dx := "dx=" || WAttrib(win, "dx")
dy := "dy=" || WAttrib(win, "dy")
every WAttrib(b.shadow | b.hilite, dx, dy)
return b
end
# BevelCircle(win, x, y, r, bw) -- draw beveled circle
procedure BevelCircle(win, x, y, r, bw) #: draw beveled circle
local b, upper, lower, a
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return BevelCircle((\&window | runerr(140)), win, x, y, r)
b := bev_lookup(win)
/r := 6
/bw := 2
if bw >= 0 then {
upper := b.hilite
lower := b.shadow
}
else {
upper := b.shadow
lower := b.hilite
bw := -bw
}
a := -&pi / 8
while (bw -:= 1) >= 0 do {
DrawCircle(lower, x, y, r, a, &pi)
DrawCircle(upper, x, y, r, a + &pi, &pi)
r -:= 1
}
return win
end
# BevelDiamond(win, x, y, r, bw) -- draw beveled diamond
procedure BevelDiamond(win, x, y, r, bw) #: draw beveled diamond
local b, upper, lower
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return BevelDiamond((\&window | runerr(140)), win, x, y, r)
b := bev_lookup(win)
/r := 6
/bw := 3
if bw >= 0 then {
upper := b.hilite
lower := b.shadow
}
else {
upper := b.shadow
lower := b.hilite
bw := -bw
}
while (bw -:= 1) >= 0 do {
DrawLine(lower, x - r, y, x, y + r, x + r, y)
DrawLine(upper, x - r, y, x, y - r, x + r, y)
r -:= 1
}
return win
end
# BevelTriangle(win, x, y, r, o, bw) -- draw beveled triangle
procedure BevelTriangle(win, x, y, r, o, bw)
local b, upper, lower
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return BevelTriangle((\&window | runerr(140)), win, x, y, r, o)
b := bev_lookup(win)
/r := 6
/bw := 2
if bw >= 0 then {
upper := b.hilite
lower := b.shadow
}
else {
upper := b.shadow
lower := b.hilite
bw := -bw
}
while (bw -:= 1) >= 0 do {
case o of {
default: { #"n"
DrawLine(lower, x - r, y + r, x + r, y + r, x, y - r)
DrawLine(upper, x - r, y + r, x, y - r)
}
"s": {
DrawLine(lower, x, y + r, x + r, y - r)
DrawLine(upper, x, y + r, x - r, y - r, x + r, y - r)
}
"e": {
DrawLine(lower, x - r, y + r, x + r, y)
DrawLine(upper, x - r, y + r, x - r, y - r, x + r, y)
}
"w": {
DrawSegment(lower, x - r, y, x + r, y + r, x + r, y + r, x + r, y-r)
DrawLine(upper, x - r, y, x + r, y - r)
}
}
r -:= 1
}
return win
end
# BevelSquare(win, x, y, r, bw) -- draw beveled square
procedure BevelSquare(win, x, y, r, bw) #: draw beveled square
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return BevelSquare((\&window | runerr(140)), win, x, y, r)
/r := 6
return BevelRectangle(win, x - r, y - r, 2 * r + 1, 2 * r + 1, bw)
end
# RidgeRectangle(win, x, y, w, h, bw) -- draw ridged rectangle
procedure RidgeRectangle(win, x, y, w, h, bw) #: draw ridged rectangle
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return RidgeRectangle((\&window | runerr(140)), win, x, y, w, h)
/bw := 2
return GrooveRectangle(win, x, y, w, h, -bw)
end
# GrooveRectangle(win, x, y, w, h, bw) -- draw grooved rectangle
procedure GrooveRectangle(win, x, y, w, h, bw) #: draw grooved rectangle
local abw
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return GrooveRectangle((\&window | runerr(140)), win, x, y, w, h)
/x := -WAttrib(win, "dx")
/y := -WAttrib(win, "dy")
/w := WAttrib(win, "width") - (x + WAttrib(win, "dx"))
/h := WAttrib(win, "height") - (y + WAttrib(win, "dy"))
if w < 0 then
x -:= (w := -w)
if h < 0 then
y -:= (h := -h)
/bw := 2
if bw >= 0 then
bw := (bw + 1) / 2
else
bw := -((-bw + 1) / 2)
abw := abs(bw)
BevelRectangle(win, x, y, w, h, -bw)
BevelRectangle(win, x + abw, y + abw, w - 2 * abw, h - 2 * abw, bw)
return win
end
# BevelRectangle(win, x, y, w, h, bw) -- draw beveled rectangle
#
# bw is the border width (>0 for raised bevel, <0 for sunken bevel).
# (x,y,w,h) bounds the entire beveled rectangle, not the usable area inside.
procedure BevelRectangle(win, x, y, w, h, bw) #: draw beveled rectangle
local b, upper, lower, xx, yy
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return BevelRectangle((\&window | runerr(140)), win, x, y, w, h)
b := bev_lookup(win)
/x := -WAttrib(win, "dx")
/y := -WAttrib(win, "dy")
/w := WAttrib(win, "width") - (x + WAttrib(win, "dx"))
/h := WAttrib(win, "height") - (y + WAttrib(win, "dy"))
if w < 0 then
x -:= (w := -w)
if h < 0 then
y -:= (h := -h)
/bw := 2
if bw >= 0 then {
upper := b.hilite
lower := b.shadow
}
else {
upper := b.shadow
lower := b.hilite
bw := -bw
}
xx := x + w
yy := y + h
FillRectangle(lower, x, yy, w, -bw, xx, y, -bw, h)
while (bw -:= 1) >= 0 do {
DrawLine(upper, x, yy -:= 1, x, y, xx -:= 1, y)
x +:= 1
y +:= 1
}
return win
end
# DrawRidge(win, x1, y1, x2, y2, w) -- draw a ridged line
#
# If w is negative, a groove is drawn instead.
procedure DrawRidge(win, x1, y1, x2, y2, w) #: draw ridged line
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return DrawRidge((\&window | runerr(140)), win, x1, y1, x2, y2)
/w := 2
DrawGroove(win, x1, y1, x2, y2, -w)
return win
end
# DrawGroove(win, x1, y1, x2, y2, w) -- draw a grooved line
#
# If w > 0, draw groove of width 2.
# If w = 0, erase groove/ridge of width 2.
# If w < 0, draw ridge of width 2.
#
# Horizontal and vertical grooves fill the same pixels as lines drawn
# linewidth=2. Angled grooves are not necessarily the same, though.
procedure DrawGroove(win, x1, y1, x2, y2, w) #: draw grooved line
local a, n, b, upper, lower, fg
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return DrawGroove((\&window | runerr(140)), win, x1, y1, x2, y2)
/w := 2
x1 := integer(x1)
y1 := integer(y1)
x2 := integer(x2)
y2 := integer(y2)
if w ~= 0 then { # if really drawing
b := bev_lookup(win)
upper := b.shadow
lower := b.hilite
}
else {
fg := Fg(win) # if erasing, draw in bg color
Fg(win, Bg(win))
upper := lower := win
}
a := atan(y2 - y1, x2 - x1)
if a < 0 then
a +:= &pi
n := integer(8 * a / &pi)
if w < 0 then # if groove/ridge swap
upper :=: lower
if n = 2 then # if tricky illumination angle
upper :=: lower
if 2 <= n <= 5 then { # approximately vertical
DrawLine(upper, x1 - 1, y1, x2 - 1, y2)
DrawLine(lower, x1, y1, x2, y2)
}
else { # approximately horizontal
DrawLine(upper, x1, y1 - 1, x2, y2 - 1)
DrawLine(lower, x1, y1, x2, y2)
}
Fg(win, \fg) # restore foreground if changed
return win
end
# FillSquare(win, x, y, r) -- fill square centered at (x,y)
procedure FillSquare(win, x, y, r) #: draw filled square
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return FillSquare((\&window | runerr(140)), win, x, y)
return FillRectangle(win, x - r, y - r, 2 * r + 1, 2 * r + 1)
end
# FillDiamond(win, x, y, r) -- fill diamond centered at (x,y)
procedure FillDiamond(win, x, y, r) #: draw filled diamond
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return FillDiamond((\&window | runerr(140)), win, x, y)
return FillPolygon(win, x - r, y, x, y + r + 1, x + r + 1, y, x, y - r - 1)
end
# FillTriangle(win, x, y, r, o) -- fill triangle centered at (x,y)
#
# r is "radius" (1/2 of side of enclosing square)
# o is orientation ("n", "s", "e", "w")
procedure FillTriangle(win, x, y, r, o) #: draw filled triangle
static type
initial type := proc("type", 0) # protect attractive name
if type(win) ~== "window" then
return FillTriangle((\&window | runerr(140)), win, x, y, r)
return case o of {
default: #"n"
FillPolygon(win, x - r - 1, y + r + 1, x, y - r, x + r + 1, y + r + 1)
"s":
FillPolygon(win, x - r, y - r, x, y + r, x + r, y - r)
"e":
FillPolygon(win, x - r, y - r, x + r, y, x - r, y + r)
"w":
FillPolygon(win, x + r + 1, y - r - 1, x - r, y, x + r + 1, y + r + 1)
}
end