File: kaimono.ml

package info (click to toggle)
lablgtk2 2.18.3%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 3,732 kB
  • ctags: 5,914
  • sloc: ml: 30,868; ansic: 9,983; makefile: 611; sh: 75
file content (141 lines) | stat: -rw-r--r-- 4,438 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
(**************************************************************************)
(*    Lablgtk - Examples                                                  *)
(*                                                                        *)
(*    There is no specific licensing policy, but you may freely           *)
(*    take inspiration from the code, and copy parts of it in your        *)
(*    application.                                                        *)
(*                                                                        *)
(**************************************************************************)

(* $Id$ *)

open StdLabels
open GMain
open Printf

let file_dialog ~title ~callback ?filename () =
  let sel = GWindow.file_selection ~title ~modal:true ?filename () in
  sel#cancel_button#connect#clicked ~callback:sel#destroy;
  sel#ok_button#connect#clicked ~callback:
    begin fun () ->
      let name = sel#filename in
      sel#destroy ();
      callback name
    end;
  sel#show ()

let w = GWindow.window ~title:"Okaimono" ()
let vb = GPack.vbox ~packing:w#add ()

let menubar = GMenu.menu_bar ~packing:vb#pack ()
let factory = new GMenu.factory menubar
let file_menu = factory#add_submenu "File"
let edit_menu = factory#add_submenu "Edit"

let sw = GBin.scrolled_window ~height:200 ~packing:vb#add
    ~hpolicy:`AUTOMATIC ~vpolicy:`AUTOMATIC ()
let vp = GBin.viewport ~width:340 ~shadow_type:`NONE ~packing:sw#add ()
let table = GPack.table ~columns:4 ~rows:256 ~packing:vp#add ()
let _ =
  table#focus#set_vadjustment (Some vp#vadjustment)

let top = ref 0
and left = ref 0
let add_to_table  w =
  table#attach ~left:!left ~top:!top ~expand:`X w;
  incr left;
  if !left >= 4 then (incr top; left := 0)

let entry_list = ref []

let add_entry () =
  let entry =
    List.map [40;200;40;60]
      ~f:(fun width -> GEdit.entry ~packing:add_to_table ~width ())
  in entry_list := entry :: !entry_list

let _ =
  List.iter2 ["Number";"Name";"Count";"Price"] [40;200;40;60] ~f:
    begin fun label width ->
      let b = GButton.button ~label ~packing:add_to_table () in
      b#misc#set_size_request ~width ()
    end;
  for i = 1 to 9 do add_entry () done

let split ~sep s =
  let len = String.length s in
  let rec loop pos =
    let next =
      try String.index_from s pos sep with Not_found -> len
    in
    let sub = String.sub s ~pos ~len:(next-pos) in
    if next = len then [sub] else sub::loop (next+1)
  in loop 0

let load name =
  try
    let ic = open_in name in
    List.iter !entry_list
      ~f:(fun l -> List.iter l ~f:(fun e -> e#set_text ""));
    let entries = Stack.create () in
    List.iter !entry_list ~f:(fun x -> Stack.push x entries);
    try while true do
      let line = input_line ic in
      let fields = split ~sep:'\t' line in
      let entry =
	try Stack.pop entries
	with Stack.Empty ->
	  add_entry (); List.hd !entry_list
      in
      List.fold_left fields ~init:entry ~f:
	begin fun acc field ->
	  (List.hd acc)#set_text field;
	  List.tl acc
	end
    done
    with End_of_file -> close_in ic
  with Sys_error _ -> ()
    

let save name =
  try
    let oc = open_out name in
    List.iter (List.rev !entry_list) ~f:
      begin fun entry ->
	let l = List.map entry ~f:(fun e -> e#text) in
	if List.exists l ~f:((<>) "") then
	  let rec loop = function
	      [] -> ()
	    | [x] -> fprintf oc "%s\n" x
	    | x::l -> fprintf oc "%s\t" x; loop l
	  in loop l
      end;
    close_out oc
  with Sys_error _ -> ()

open GdkKeysyms

let _ =
  w#connect#destroy ~callback:Main.quit;
  w#event#connect#key_press ~callback:
    begin fun ev ->
      let key = GdkEvent.Key.keyval ev and adj = vp#vadjustment in
      if key = _Page_Up then
	adj#set_value (adj#value -. adj#page_increment)
      else if key = _Page_Down then
	adj#set_value (min (adj#value +. adj#page_increment)
			 (adj#upper -. adj#page_size));
      false
    end;
  w#add_accel_group factory#accel_group;
  let ff = new GMenu.factory file_menu ~accel_group:factory#accel_group in
  ff#add_item ~key:_O "Open..."
    ~callback:(file_dialog ~title:"Open data file" ~callback:load);
  ff#add_item ~key:_S "Save..."
    ~callback:(file_dialog ~title:"Save data" ~callback:save);
  ff#add_separator ();
  ff#add_item ~key:_Q "Quit" ~callback:w#destroy;
  let ef = new GMenu.factory edit_menu ~accel_group:factory#accel_group in
  ef#add_item ~key:_A "Add line" ~callback:add_entry;
  w#show ();
  Main.main ()