Blame frx/frx_listbox.ml

Packit bd2e5d
(***********************************************************************)
Packit bd2e5d
(*                                                                     *)
Packit bd2e5d
(*                 MLTk, Tcl/Tk interface of OCaml                     *)
Packit bd2e5d
(*                                                                     *)
Packit bd2e5d
(*    Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis    *)
Packit bd2e5d
(*               projet Cristal, INRIA Rocquencourt                    *)
Packit bd2e5d
(*            Jacques Garrigue, Kyoto University RIMS                  *)
Packit bd2e5d
(*                                                                     *)
Packit bd2e5d
(*  Copyright 2002 Institut National de Recherche en Informatique et   *)
Packit bd2e5d
(*  en Automatique and Kyoto University.  All rights reserved.         *)
Packit bd2e5d
(*  This file is distributed under the terms of the GNU Library        *)
Packit bd2e5d
(*  General Public License, with the special exception on linking      *)
Packit bd2e5d
(*  described in file LICENSE found in the OCaml source tree.          *)
Packit bd2e5d
(*                                                                     *)
Packit bd2e5d
(***********************************************************************)
Packit bd2e5d
open Camltk
Packit bd2e5d
Packit bd2e5d
let version = "$Id$"
Packit bd2e5d
Packit bd2e5d
(*
Packit bd2e5d
 * Link a scrollbar and a listbox
Packit bd2e5d
 *)
Packit bd2e5d
let scroll_link sb lb =
Packit bd2e5d
  Listbox.configure lb
Packit bd2e5d
        [YScrollCommand (Scrollbar.set sb)];
Packit bd2e5d
  Scrollbar.configure sb
Packit bd2e5d
        [ScrollCommand (Listbox.yview lb)]
Packit bd2e5d
Packit bd2e5d
(*
Packit bd2e5d
 * Completion for listboxes, Macintosh style.
Packit bd2e5d
 * As long as you type fast enough, the listbox is repositioned to the
Packit bd2e5d
 * first entry "greater" than the typed prefix.
Packit bd2e5d
 * assumes:
Packit bd2e5d
 *   sorted list (otherwise it's stupid)
Packit bd2e5d
 *   fixed size, because we don't recompute size at each callback invocation
Packit bd2e5d
 *)
Packit bd2e5d
Packit bd2e5d
let add_completion lb action =
Packit bd2e5d
  let prefx = ref ""              (* current match prefix *)
Packit bd2e5d
  and maxi = Listbox.size lb - 1 (* maximum index (doesn't matter actually) *)
Packit bd2e5d
  and current = ref 0             (* current position *)
Packit bd2e5d
  and lastevent = ref 0 in
Packit bd2e5d
Packit bd2e5d
  let rec move_forward () =
Packit bd2e5d
    if Listbox.get lb (Number !current) < !prefx then
Packit bd2e5d
      if !current < maxi then begin incr current; move_forward() end
Packit bd2e5d
Packit bd2e5d
  and recenter () =
Packit bd2e5d
    let element = Number !current in
Packit bd2e5d
     (* Clean the selection *)
Packit bd2e5d
     Listbox.selection_clear lb (Number 0) End;
Packit bd2e5d
     (* Set it to our unique element *)
Packit bd2e5d
     Listbox.selection_set lb element element;
Packit bd2e5d
     (* Activate it, to keep consistent with Up/Down.
Packit bd2e5d
        You have to be in Extended or Browse mode *)
Packit bd2e5d
     Listbox.activate lb element;
Packit bd2e5d
     Listbox.selection_anchor lb element;
Packit bd2e5d
     Listbox.see lb element in
Packit bd2e5d
Packit bd2e5d
  let complete time s =
Packit bd2e5d
    if time - !lastevent < 500 then   (* sorry, hard coded limit *)
Packit bd2e5d
      prefx := !prefx ^ s
Packit bd2e5d
    else begin (* reset *)
Packit bd2e5d
      current := 0;
Packit bd2e5d
      prefx := s
Packit bd2e5d
    end;
Packit bd2e5d
    lastevent := time;
Packit bd2e5d
    move_forward();
Packit bd2e5d
    recenter() in
Packit bd2e5d
Packit bd2e5d
Packit bd2e5d
  bind lb [[], KeyPress]
Packit bd2e5d
      (BindSet([Ev_Char; Ev_Time],
Packit bd2e5d
          (function ev ->
Packit bd2e5d
             (* consider only keys producing characters. The callback is called
Packit bd2e5d
              * even if you press Shift.
Packit bd2e5d
              *)
Packit bd2e5d
             if ev.ev_Char <> "" then complete ev.ev_Time ev.ev_Char)));
Packit bd2e5d
  (* Key specific bindings override KeyPress *)
Packit bd2e5d
  bind lb [[], KeyPressDetail "Return"] (BindSet([], action));
Packit bd2e5d
  (* Finally, we have to set focus, otherwise events dont get through *)
Packit bd2e5d
  Focus.set lb;
Packit bd2e5d
  recenter()   (* so that first item is selected *)
Packit bd2e5d
Packit bd2e5d
let new_scrollable_listbox top options =
Packit bd2e5d
  let f = Frame.create top [] in
Packit bd2e5d
  let lb = Listbox.create f options
Packit bd2e5d
  and sb = Scrollbar.create f [] in
Packit bd2e5d
    scroll_link sb lb;
Packit bd2e5d
    pack [lb] [Side Side_Left; Fill Fill_Both; Expand true];
Packit bd2e5d
    pack [sb] [Side Side_Left; Fill Fill_Y];
Packit bd2e5d
    f, lb