SMALLTALK GRAPHICS important classes: Point -- 2d points, with a x and a y value Rectangle -- a rectangular region on the screen other geometric objects: Circle, LineSegment, Spline, etc Window and its subclass ScheduledWindow GraphicsContext -- holds information on how to display objects "open a scheduled window" Smalltalk at: #W put: ScheduledWindow new. W component: 'hi there' asComposedText. "add a component to the window" W label: 'test window'. W open. W close. =================================================== " menus and dialogs" | menu | menu := PopUpMenu labels: 'clams\oysters\octopi' withCRs. menu startUp DialogView request: 'order please:' DialogView request: 'order please:' initialAnswer: 'HUB food' DialogView confirm: 'has Smalltalk gotten a bit complex??' ============================================= "graphical objects" "all of the following examples just write into the window, but don't keep a permanent record of the graphical actions, so that the window won't refresh properly. To keep a permanent record, add a component (see above example, or page 284-289 of the Smalltalk manual). "a simple example -- displaying a rectangle" | gc r | gc := W graphicsContext. gc clear. gc paint: ColorValue blue. r := Rectangle fromUser translatedBy: W globalOrigin negated. gc displayRectangle: r. gc paint: ColorValue black. gc lineWidth: 20. gc displayRectangularBorder: r. "displaying lines" "windows understand the message graphicsContext, which returns an instance of GraphicsContext. The gc has information about how to display lines and text, clipping, and so forth." 5 to: 400 by: 5 do: [:i | W graphicsContext displayLineFrom: 0@i to: i@400] | gc | gc := W graphicsContext. gc clear. gc paint: ColorValue blue. "change the color" 5 to: 400 by: 5 do: [:i | gc displayLineFrom: 0@i to: i@400] "display a set of lines of different colors, labelled by their color (from page 295 of the manual) | gc endPoint | gc := W graphicsContext. gc clear. gc lineWidth: 7. endPoint := 350@0. "ColorValue constantNames returns a collection of names of standard colors" ColorValue constantNames do: [:c | endPoint := endPoint + (-10@12). "Use the constant name (a Symbol) as the message selector, then display a line segment with the resulting color" gc paint: (ColorValue perform: c). gc displayLineFrom: 0@0 to: endPoint. "display the constant name in black" gc paint: ColorValue black. c asString displayOn: gc at: endPoint + (0@8)] "a mandala" | n diameter points center gc | n := 10. diameter := 100. center := 200@200. points := Array new: n. gc := W graphicsContext. gc clear. 1 to: n do: [:k | points at: k put: center + (Point r: diameter theta: 2 * Float pi * k / n)]. 1 to: n-1 do: [:j | j to: n do: [ :k | gc displayLineFrom: (points at: j) to: (points at: k)]] "a multicolored mandala" | n diameter points center gc | n := 10. diameter := 100. center := 200@200. points := Array new: n. gc := W graphicsContext. gc clear. 1 to: n do: [:k | points at: k put: center + (Point r: diameter theta: 2 * Float pi * k / n)]. 1 to: n-1 do: [:j | gc paint: (ColorValue perform: (ColorValue constantNames at: j)). gc lineWidth: 2. j to: n do: [ :k | gc displayLineFrom: (points at: j) to: (points at: k)]] "a squiral (this is a traditional example in Logo -- much more simply defined though if you have a Turtle that understands go and turn messages Ñ here we have to do some trigonometry. There used to be a class Pen in Smalltalk (like a Logo Turtle), but it seems to have disappeared." | pt1 pt2 length angle deltaLength deltaAngle gc | pt1 := 200@200. length := 1. angle := 0. deltaLength := 2. deltaAngle := 89.0. gc := W graphicsContext. gc clear. 1 to: 200 do: [:k | pt2 := pt1 + (Point r: length theta: angle * 2.0 * Float pi / 360.0). gc displayLineFrom: pt1 to: pt2. length := length+deltaLength. angle := angle + deltaAngle. pt1 := pt2] "a tunnel of green (shows how to make a color value from scratch)" | gc origin | gc := W graphicsContext. origin := 0@0. 1 to: 0 by: -0.01 do: [:grn | gc paint: (ColorValue red: 0.0 green: grn blue: 0.0). origin := origin + 4. gc displayRectangle: (origin extent: 400-origin)] "varying the brightness to give depth to a cone (see page 298 of the manual)" | gc r x y| gc := W graphicsContext. gc lineWidth: 2. r := 50. gc clear. "the lightest cone" gc translation: 150@150. 0 to: 1 by: 0.005 do: [:i | x := (i * Float pi) cos * r. y := (i*Float pi) sin * r/2. gc paint: (ColorValue hue: 0.0 saturation: 0.5 brightness: i). gc displayLineFrom: x@y to: 0@ -100]. "the intermediate cone" gc translation: 200@200. 0 to: 1 by: 0.005 do: [:i | x := (i * Float pi) cos * r. y := (i*Float pi) sin * r/2. gc paint: (ColorValue hue: 0.0 saturation: 0.75 brightness: i). gc displayLineFrom: x@y to: 0@ -100]. "the darkest cone" gc translation: 250@250. 0 to: 1 by: 0.005 do: [:i | x := (i * Float pi) cos * r. y := (i*Float pi) sin * r/2. gc paint: (ColorValue hue: 0.0 saturation: 1.0 brightness: i). gc displayLineFrom: x@y to: 0@ -100]. "how to be really fussy with graphics (different styles of joining line segments)" | gc | gc := W graphicsContext. gc clear. gc paint: ColorValue red. gc lineWidth: 20. gc joinStyle: (GraphicsContext joinMiter). gc displayPolyline: (Array with: 30@50 with: 80@30 with: 80@80). gc joinStyle: (GraphicsContext joinRound). gc displayPolyline: (Array with: 30@150 with: 80@130 with: 80@180). gc joinStyle: (GraphicsContext joinBevel). gc displayPolyline: (Array with: 30@250 with: 80@230 with: 80@280). "demonstration of animation with and without double buffering" "move two rectangles, without double buffering. Include the delay if desired to slow it down a bit" | gc r1 r2 | gc := W graphicsContext. gc paint: ColorValue gray. 1 to: 200 do: [:i | r1 := Rectangle origin: i@i extent: 20@20. r2 := Rectangle origin: (300-i)@(300-i) extent: 20@20. gc clear. gc displayRectangle: r1. gc displayRectangle: r2. "(Delay forMilliseconds: 50) wait"] "now the same example, using double buffering" | buffer gc windowGC r1 r2 | windowGC := W graphicsContext. buffer := Pixmap extent: 400@400. gc := buffer graphicsContext. gc paint: ColorValue gray. 1 to: 200 do: [:i | r1 := Rectangle origin: i@i extent: 20@20. r2 := Rectangle origin: (300-i)@(300-i) extent: 20@20. gc clear. gc displayRectangle: r1. gc displayRectangle: r2. buffer displayOn: windowGC. "(Delay forMilliseconds: 50) wait"]