(* CTM Chapter #10 Examples in Alice ML *) import structure Gtk from "x-alice:/lib/gtk/Gtk" import structure Canvas from "x-alice:/lib/gtk/Canvas" (* syntactic sugar for solutions using promises/futures *) open Promise open Future infix 3 ?= val op?= = fulfill val ? = future (* Functions defined in previous chapters *) datatype gtkglue = NOGLUE | N | S | W | E | NS | NW | NE | SW | SE | WE | NSW | NWE | SWE | NSWE datatype gtk = GtkTD of gtk list | GtkLR of gtk list | GtkTitle of {text:string} | GtkLabel of {text:string} | GtkText of {object:(Gtk.object promise), tdscrollbar:bool, glue:gtkglue} | GtkButton of {text:string, action:(Gtk.callback_function), glue:gtkglue} | GtkGlue of gtkglue fun gtkBuild d = let val window = Gtk.Window.new Gtk.WindowType.TOPLEVEL val destroyEvent = fn _ => OS.Process.exit OS.Process.success fun gtkPack (box, widget) = if (widget <> Gtk.NULL) then Gtk.Box.packStart(box, widget, false, false, 0) else () fun build (GtkTD xs) = let val vBox = Gtk.VBox.new(false, 0) in map (fn x => let val widget = build x in gtkPack(vBox, widget) end) xs; vBox end | build (GtkLR xs) = let val hBox = Gtk.HBox.new(false, 0) in map (fn x => let val widget = build x in gtkPack(hBox, widget) end) xs; hBox end | build (GtkTitle {text}) = let val _ = Gtk.Window.setTitle(window, text) in Gtk.NULL end | build (GtkLabel {text}) = let val label = Gtk.Label.new text in label end | build (GtkText {object, tdscrollbar, glue}) = let val _ = fulfill(object, Gtk.TextView.new()) in future object end | build (GtkButton {text, action, glue}) = let val button = Gtk.Button.newWithLabel text in Gtk.signalConnect(button, "clicked", action); button end | build (GtkGlue x) = Gtk.NULL in Gtk.signalConnect(window, "destroy-event", destroyEvent); Gtk.Container.setBorderWidth(window, 4); Gtk.Container.add(window, build d); window end (* 10.2.2 Using the declarative/procedural approach - Build the GUI *) fun gtkTextOutput field = let val textBuffer = Gtk.TextView.getBuffer(future field) val textIterStart = Gtk.TextIter.new() val textIterEnd = Gtk.TextIter.new() in Gtk.TextBuffer.getBounds(textBuffer, textIterStart, textIterEnd); Gtk.TextBuffer.getText(textBuffer, textIterStart, textIterEnd, false) end fun getText a = let val h = promise() val t = promise() val pWindow = promise() fun a1 _ = let in t ?= gtkTextOutput(h); Gtk.Widget.destroy(future pWindow) end val d = GtkTD[ GtkLR[ GtkLabel {text="Input:"}, GtkText {object=h, tdscrollbar=true, glue=NSWE}], GtkButton {text="Ok", action=a1, glue=NSWE} ] val window = gtkBuild(d) in fulfill(pWindow, window); Gtk.Widget.showAll window; await (future t); future t end; inspect (getText "Type your name:"); (* 10.2.3 Using the declarative/procedural approach - Declarative geometry *) val d = GtkLR[ GtkLabel {text="left"}, GtkLabel {text="center"}, GtkLabel {text="right"} ] val w1 = gtkBuild(d); Gtk.Widget.showAll w1; val e = GtkTD[ GtkLabel {text="top"}, GtkLabel {text="center"}, GtkLabel {text="down"} ] val w2 = gtkBuild(e); Gtk.Widget.showAll w2; |