Re: CamlTk and LablTk

From: Pierre Weis (Pierre.Weis@inria.fr)
Date: Mon May 22 2000 - 16:57:52 MET DST

  • Next message: Pierre Weis: "Re: reference initialization"

    > How can we compare camltk and labltk ??
    > (functionalities, ease of writing (complex) GUI, portability,
    > integration in Ocaml-3.00, ...)
    [...]
    > > 59650 Villeneuve d'Ascq mailto:mariano@terre.inrets.fr

    There is no reason to start a flameware on this subject :)

    In short: both libraries have comparable functionality, CamlTk being
    based on the core Caml language to interface Tk (with the drawback of
    some sort of dynamic type checking), while LablTk uses a set of new
    powerful features to ensure a strictly static type-checking (with no
    drawback, except that you have to know how to use the new features to
    write your GUI with the library).

    In some details:

    - functionality is somewhat equivalent, since both libraries are
    derived from the same ``Widget compiler'' interfacing Caml to the Tk
    library.

    - ``ease of writing (complex) GUI'' is questionable since:
      - LablTk has undoubtedly a better type system for Tk options that
        are now statically checked, whereas options are checked dynamically
        with CamlTk (hence more errors are statically detected with
        LablTk).
     
      - CamlTk is simpler since it does not use labels, options and
        polymorphic variants.

    - portability: both libraries seem equally portable (?)

    - integration in Ocaml-3.00: LablTk is distributed with O'Caml V3.0
      and uses the newest features of the language. CamlTk is distributed
      separately and uses the core language only.

    To give an idea of the difference between the two libraries, here is a
    small example due to June Furuse (the example mimicks Xeyes) given in
    the two styles:

    (* The eyes of Caml (CamlTk style) *)
    (* ocamlc -custom -I /usr/local/lib/ocaml/camltk41 -o tetris tk41.cma tetris.ml *)

    open Tk

    let _ =
      let top = openTk () in
      let fw = Frame.create top [] in
      pack [fw] [];
      let c = Canvas.create fw [Width (Pixels 200); Height (Pixels 200)] in
      let create_eye cx cy wx wy ewx ewy bnd =
        let o2 =
           Canvas.create_oval c
            (Pixels (cx - wx)) (Pixels (cy - wy))
            (Pixels (cx + wx)) (Pixels (cy + wy))
            [Outline (NamedColor "black"); Width (Pixels 7);
             FillColor (NamedColor "white")]
        and o =
          Canvas.create_oval c
           (Pixels (cx - ewx)) (Pixels (cy - ewy))
           (Pixels (cx + ewx)) (Pixels (cy + ewy))
           [FillColor (NamedColor "black")] in
        let curx = ref cx
        and cury = ref cy in
        bind c [[], Motion]
          (BindExtend ([Ev_MouseX; Ev_MouseY],
            (fun e ->
              let nx, ny =
                let xdiff = e.ev_MouseX - cx
                and ydiff = e.ev_MouseY - cy in
                let diff = sqrt ((float xdiff /. (float wx *. bnd)) ** 2.0 +.
                                   (float ydiff /. (float wy *. bnd)) ** 2.0) in
                if diff > 1.0 then
                  truncate ((float xdiff) *. (1.0 /. diff)) + cx,
                  truncate ((float ydiff) *. (1.0 /. diff)) + cy
                else
                  e.ev_MouseX, e.ev_MouseY
              in
              Canvas.move c o (Pixels (nx - !curx)) (Pixels (ny - !cury));
              curx := nx;
              cury := ny)))
      in
      create_eye 60 100 30 40 5 6 0.6;
      create_eye 140 100 30 40 5 6 0.6;
      pack [c] []

    let _ = Printexc.print mainLoop ()

    (* The eyes of Caml (LablTk) *)
    (* ocamlc -w s -labels -I /usr/local/lib/ocaml/labltk -o tetris labltk.cma tetris.ml *)

    open Tk

    let _ =
      let top = openTk () in
      let fw = Frame.create top in
      pack [fw];
      let c = Canvas.create ~width: 200 ~height: 200 fw in
      let create_eye cx cy wx wy ewx ewy bnd =
        let o2 = Canvas.create_oval
            ~x1:(cx - wx) ~y1:(cy - wy)
            ~x2:(cx + wx) ~y2:(cy + wy)
            ~outline: `Black ~width: 7
            ~fill: `White
            c
        and o = Canvas.create_oval
            ~x1:(cx - ewx) ~y1:(cy - ewy)
            ~x2:(cx + ewx) ~y2:(cy + ewy)
            ~fill:`Black
            c in
        let curx = ref cx
        and cury = ref cy in
        bind ~events:[`Motion] ~extend:true ~fields:[`MouseX; `MouseY]
          ~action:(fun e ->
            let nx, ny =
              let xdiff = e.ev_MouseX - cx
              and ydiff = e.ev_MouseY - cy in
              let diff = sqrt ((float xdiff /. (float wx *. bnd)) ** 2.0 +.
                                 (float ydiff /. (float wy *. bnd)) ** 2.0) in
              if diff > 1.0 then
                truncate ((float xdiff) *. (1.0 /. diff)) + cx,
                truncate ((float ydiff) *. (1.0 /. diff)) + cy
              else
                e.ev_MouseX, e.ev_MouseY
            in
            Canvas.move c o ~x: (nx - !curx) ~y: (ny - !cury);
            curx := nx;
            cury := ny)
          c
      in
      create_eye 60 100 30 40 5 6 0.6;
      create_eye 140 100 30 40 5 6 0.6;
      pack [c]

    let _ = Printexc.print mainLoop ()

    Pierre Weis

    INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://cristal.inria.fr/~weis/



    This archive was generated by hypermail 2b29 : Mon May 22 2000 - 18:15:08 MET DST