--- /dev/null
+(* $Id$ *)
+
+open GdkKeysyms
+open Gtk
+open GObj
+
+open Utils
+open TiBase
+
+let main_project_modify = ref false
+
+let main_window = GWindow.window ~title:"ZOOM" ~x:10 ~y:10 ()
+let main_vbox = GPack.vbox ~packing:main_window#add ()
+let main_menu = GMenu.menu_bar ~packing:(main_vbox#pack ~expand:false) ()
+
+let can_copy = ref (fun _ -> assert false)
+let can_paste = ref (fun _ -> assert false)
+
+class project () =
+ let project_box = GPack.vbox ~packing:main_vbox#pack () in
+ let project_tree = GTree2.tree ~packing:project_box#pack () in
+ object(self)
+ val mutable window_list = []
+
+(* the selected window *)
+ val mutable selected = (None : window_and_tree option)
+
+ method change_selected sel =
+ match selected with
+ | None ->
+ selected <- Some sel;
+ sel#project_tree_item#misc#set_state `SELECTED;
+ !can_copy true
+ | Some old_sel ->
+ if sel = old_sel then begin
+ selected <- None;
+ sel#project_tree_item#misc#set_state `NORMAL;
+ !can_copy false
+ end else begin
+ old_sel#project_tree_item#misc#set_state `NORMAL;
+ selected <- Some sel;
+ sel#project_tree_item#misc#set_state `SELECTED;
+ !can_copy true
+ end
+
+ val mutable filename = ""
+ val mutable dirname = ""
+
+ method set_filename f =
+ let dir, file = split_filename f ~ext:".rad" in
+ filename <- file;
+ dirname <- dir
+
+ method get_filename () =
+ get_filename ~callback:self#set_filename ~dir:dirname ()
+
+ method dirname = dirname
+
+(* method set_dirname f = dirname <- f *)
+
+ method add_window ~name ?tree:wt () =
+ let wt = match wt with
+ | None -> new window_and_tree ~name
+ | Some wt -> wt in
+ let tiwin = wt#tiwin and tw=wt#tree_window in
+ let project_tree_item = wt#project_tree_item in
+ project_tree#append project_tree_item;
+ let show = ref true in
+ project_tree_item#event#connect#button_press ~callback:
+ (fun ev ->
+ match GdkEvent.get_type ev with
+ | `BUTTON_PRESS ->
+ if GdkEvent.Button.button ev = 1 then begin
+ self#change_selected wt
+ end else
+ if GdkEvent.Button.button ev = 3 then begin
+ let menu = GMenu.menu () in
+ let name = wt#tiwin#name in
+ let mi_remove = GMenu.menu_item ~label:("delete " ^ name)
+ ~packing:menu#append ()
+ and mi_copy = GMenu.menu_item ~label:("copy " ^ name)
+ ~packing:menu#append ()
+ and mi_cut = GMenu.menu_item ~label:("cut " ^ name)
+ ~packing:menu#append () in
+ mi_remove#connect#activate
+ ~callback:(fun () -> self#delete_window wt);
+ mi_copy#connect#activate
+ ~callback:(fun () -> self#copy_wt wt);
+ mi_cut#connect#activate
+ ~callback:(fun () -> self#cut_wt wt);
+ menu#popup ~button:3 ~time:(GdkEvent.Button.time ev)
+ end;
+ GtkSignal.stop_emit ();
+ true
+ | `TWO_BUTTON_PRESS ->
+ if GdkEvent.Button.button ev = 1 then begin
+ if !show then begin
+ show := false;
+ tiwin#widget#misc#hide ();
+ tw#misc#hide ()
+ end
+ else begin
+ show := true;
+ tiwin#widget#misc#show ();
+ tw#misc#show ()
+ end
+ end;
+ true
+ | _ -> false);
+ tiwin#connect_event#delete ~callback:
+ (fun _ -> show := false; tiwin#widget#misc#hide (); true);
+ tw#event#connect#delete ~callback:
+ (fun _ -> show := false; tw#misc#hide (); true);
+ window_list <- wt :: window_list;
+ add_undo (Remove_window name);
+ main_window#misc#set_can_focus false;
+ main_window#misc#grab_focus ()
+
+
+ method add_window_by_node
+ (Node ((classe, name, proplist), children)) =
+ if classe <> "window"
+ then failwith "add_window_by_node: class <> \"window\"";
+ let name = change_name name in (* for paste *)
+ let wt = new window_and_tree ~name in
+ let tiwin = wt#tiwin in
+ List.iter proplist ~f:(fun (n,v) -> tiwin#set_property n v);
+ begin match children with
+ | [] -> ()
+ | [ ch ] -> tiwin#add_children_wo_undo ch; ()
+ | _ -> failwith "add_window_by_node: more than one child"
+ end;
+ self#add_window ~name ~tree:wt ()
+
+ method delete_window (wt : window_and_tree) =
+ let tiwin = wt#tiwin in
+ project_tree#remove wt#project_tree_item;
+ tiwin#remove_me ();
+ wt#tree_window#destroy ();
+ window_list <- list_remove ~f:(fun w -> w = wt) window_list
+
+ method delete_window_by_name ~name =
+ let wt = List.find window_list ~f:(fun wt -> wt#tiwin#name = name) in
+ self#delete_window wt
+
+ method delete () =
+ List.iter window_list
+ ~f:(fun wt -> self#delete_window wt);
+ main_vbox#remove project_box#coerce;
+(* remove after test *)
+ if !name_list <> [] then failwith "name_list not empty"
+
+ method save_as () = if self#get_filename () then self#save ()
+
+ method save () =
+ if filename = "" then self#save_as ()
+ else begin
+ let outch = open_out (dirname ^ filename ^ ".rad") in
+ let f = Format.formatter_of_out_channel outch in
+ List.iter window_list ~f:(fun wt -> wt#tiwin#save f);
+ close_out outch;
+ main_project_modify := false
+ end
+
+ method copy_wt (wt : window_and_tree) =
+ wt#tiwin#copy ();
+ !can_paste true
+
+ method cut_wt (wt : window_and_tree) =
+ self#copy_wt wt;
+ self#delete_window wt
+
+ method copy () =
+ match selected with
+ | None -> failwith "main_project copy"
+ | Some sel -> self#copy_wt sel
+
+ method cut () =
+ match selected with
+ | None -> failwith "main_project cut"
+ | Some sel -> self#cut_wt sel
+
+ method paste () =
+ let lexbuf = Lexing.from_string !window_selection in
+ let node = Load_parser.window Load_lexer.token lexbuf in
+ self#add_window_by_node node
+
+ method emit () =
+ let outc = open_out (dirname ^ filename ^ ".ml") in
+ let f = Format.formatter_of_out_channel outc in
+ List.iter window_list ~f:(fun wt -> wt#emit f);
+ Format.fprintf f "let main () =@\n";
+(* this is just for demo *)
+ List.iter window_list ~f:
+ begin fun wt ->
+ let name = wt#tiwin#name in
+ Format.fprintf f " let %s = new %s () in %s#show ();@\n"
+ name name name
+ end;
+ Format.fprintf f
+ " GMain.Main.main ()@\n@\nlet _ = main ()@\n";
+ close_out outc
+
+ end
+
+
+let main_project = ref (new project ())
+
+let load () =
+ let filename = ref "" in
+ get_filename ~callback:(fun f -> filename := f) ~dir:!main_project#dirname ();
+ if !filename <> "" then begin
+ !main_project#delete ();
+ main_project := new project ();
+ let inch = open_in !filename in
+ let lexbuf = Lexing.from_channel inch in
+ let project_list = Load_parser.project Load_lexer.token lexbuf in
+ close_in inch;
+ List.iter project_list
+ ~f:(fun node -> !main_project#add_window_by_node node);
+ !main_project#set_filename !filename
+ end
+
+
+let interpret_undo = function
+ | Add (parent_name, node, pos) ->
+ let parent = Hashtbl.find widget_map parent_name in
+ parent#add_children node ~pos
+ | Remove child_name ->
+ let child = Hashtbl.find widget_map child_name in
+ child#remove_me ()
+ | Property (property, value_string) ->
+ property#set value_string
+ | Add_window node -> !main_project#add_window_by_node node
+ | Remove_window name -> !main_project#delete_window_by_name ~name
+
+let undo () =
+ if !last_action_was_undo then begin
+ match !next_undo_info with
+ | hd :: tl -> interpret_undo hd; next_undo_info := tl
+ | [] -> message "no more undo info"
+ end
+ else begin
+ match !undo_info with
+ | hd :: tl -> interpret_undo hd; next_undo_info := tl
+ | [] -> message "no undo info"
+ end;
+ last_action_was_undo := true
+
+
+let targets = [ { target = "STRING"; flags = []; info = 0} ]
+
+let xpm_window () =
+ let source_drag_data_get classe _ (data : selection_data) ~info ~time =
+ data#set ~typ:data#target ~format:0 ~data:classe in
+ let window = GWindow.window ~title:"icons" ~x:250 ~y:10 () in
+ window#misc#realize ();
+ let vbox = GPack.vbox ~packing:window#add () in
+ let table = GPack.table ~rows:1 ~columns:5 ~border_width:20
+ ~packing:vbox#pack () in
+ let tooltips = GData.tooltips () in
+ let add_xpm ~file ~left ~top ~tip =
+ let gdk_pix = GDraw.pixmap_from_xpm ~file ~window () in
+ let ev = GBin.event_box ~packing:(table#attach ~left ~top) () in
+ let pix = GMisc.pixmap gdk_pix ~packing:ev#add () in
+ ev#event#connect#button_press ~callback:
+ (fun ev -> match GdkEvent.get_type ev with
+ | `BUTTON_PRESS ->
+ if GdkEvent.Button.button ev = 1 then begin
+ !main_project#add_window ~name:(make_new_name "window") ()
+ end;
+ true
+ | _ -> false);
+ tooltips#set_tip ev#coerce ~text:tip
+ in
+ add_xpm ~file:"window.xpm" ~left:0 ~top:0 ~tip:"window";
+ GMisc.separator `HORIZONTAL ~packing:vbox#pack ();
+ let table = GPack.table ~rows:6 ~columns:6 ~packing:vbox#pack
+ ~row_spacings:20 ~col_spacings:20 ~border_width:20 () in
+ let add_xpm file ~left ~top ~classe =
+ let gdk_pix = GDraw.pixmap_from_xpm ~file ~window () in
+ let ev = GBin.event_box ~packing:(table#attach ~left ~top) () in
+ let pix = GMisc.pixmap gdk_pix ~packing:ev#add () in
+ ev#drag#source_set ~modi:[`BUTTON1] targets ~actions:[`COPY];
+ ev#drag#source_set_icon ~colormap:window#misc#style#colormap
+ gdk_pix;
+ ev#drag#connect#data_get ~callback:(source_drag_data_get classe);
+ tooltips#set_tip ev#coerce ~text:classe
+ in
+
+ add_xpm "button.xpm" ~left:0 ~top:0 ~classe:"button";
+ add_xpm "togglebutton.xpm" ~left:1 ~top:0 ~classe:"toggle_button";
+ add_xpm "checkbutton.xpm" ~left:2 ~top:0 ~classe:"check_button";
+ add_xpm "radiobutton.xpm" ~left:3 ~top:0 ~classe:"radio_button";
+ add_xpm "toolbar.xpm" ~left:4 ~top:0 ~classe:"toolbar";
+ add_xpm "hbox.xpm" ~left:0 ~top:1 ~classe:"hbox";
+ add_xpm "vbox.xpm" ~left:1 ~top:1 ~classe:"vbox";
+ add_xpm "hbuttonbox.xpm" ~left:2 ~top:1 ~classe:"hbutton_box";
+ add_xpm "vbuttonbox.xpm" ~left:3 ~top:1 ~classe:"vbutton_box";
+ add_xpm "fixed.xpm" ~left:4 ~top:1 ~classe:"fixed";
+ add_xpm "frame.xpm" ~left:0 ~top:2 ~classe:"frame";
+ add_xpm "aspectframe.xpm" ~left:1 ~top:2 ~classe:"aspect_frame";
+ add_xpm "scrolledwindow.xpm" ~left:2 ~top:2 ~classe:"scrolled_window";
+ add_xpm "eventbox.xpm" ~left:3 ~top:2 ~classe:"event_box";
+ add_xpm "handlebox.xpm" ~left:4 ~top:2 ~classe:"handle_box";
+ add_xpm "viewport.xpm" ~left:5 ~top:2 ~classe:"viewport";
+ add_xpm "hseparator.xpm" ~left:0 ~top:3 ~classe:"hseparator";
+ add_xpm "vseparator.xpm" ~left:1 ~top:3 ~classe:"vseparator";
+ add_xpm "clist.xpm" ~left:2 ~top:3 ~classe:"clist";
+ add_xpm "label.xpm" ~left:0 ~top:4 ~classe:"label";
+ add_xpm "statusbar.xpm" ~left:1 ~top:4 ~classe:"statusbar";
+ add_xpm "notebook.xpm" ~left:2 ~top:4 ~classe:"notebook";
+ add_xpm "colorselection.xpm" ~left:3 ~top:4 ~classe:"color_selection";
+ add_xpm "pixmap.xpm" ~left:4 ~top:4 ~classe:"pixmap";
+ add_xpm "entry.xpm" ~left:0 ~top:5 ~classe:"entry";
+ add_xpm "spinbutton.xpm" ~left:1 ~top:5 ~classe:"spin_button";
+ add_xpm "combo.xpm" ~left:2 ~top:5 ~classe:"combo";
+
+ window#show ();
+ window
+
+
+let main () =
+ let _ = GMain.Main.init () in
+ let prop_win = Propwin.init () in
+ let palette = xpm_window () in
+ main_window#show ();
+ main_window#connect#destroy ~callback:GMain.Main.quit;
+
+ let mp = main_project in
+ let f = new GMenu.factory main_menu in
+ let accel_group = f#accel_group in
+ main_window#add_accel_group accel_group;
+ prop_win#add_accel_group accel_group;
+ palette#add_accel_group accel_group;
+
+ let file_menu = new GMenu.factory (f#add_submenu "File") ~accel_group
+ and edit_menu = new GMenu.factory (f#add_submenu "Edit") ~accel_group
+ and view_menu = new GMenu.factory (f#add_submenu "View") ~accel_group
+ and project_menu = new GMenu.factory (f#add_submenu "Project") ~accel_group
+ in
+
+ file_menu#add_item "Quit" ~key:_Q ~callback:GMain.Main.quit;
+
+ project_menu#add_item "New" ~key:_N
+ ~callback:(fun () -> !mp#delete (); mp := new project ());
+ project_menu#add_item "Open..." ~key:_O ~callback:load;
+ project_menu#add_item "Save" ~key:_S ~callback:(fun () -> !mp#save ());
+ project_menu#add_item "Save as..." ~callback:(fun () -> !mp#save_as ());
+ project_menu#add_separator ();
+ project_menu#add_item "Emit code" ~callback:(fun () -> !mp#emit ());
+
+ let copy_item =
+ edit_menu#add_item "Copy" ~key:_C ~callback:(fun () -> !mp#copy ())
+ and cut_item =
+ edit_menu#add_item "Cut" ~key:_X ~callback:(fun () -> !mp#cut ())
+ and paste_item =
+ edit_menu#add_item "Paste" ~key:_V ~callback:(fun () -> !mp#paste ())
+ in
+ can_copy :=
+ (fun b -> copy_item#misc#set_sensitive b; cut_item#misc#set_sensitive b);
+ can_paste := paste_item#misc#set_sensitive;
+ !can_copy false; !can_paste false;
+ edit_menu#add_item "Undo" ~key:_Z ~callback:undo;
+
+ let palette_visible = ref true in
+ palette#event#connect#delete ~callback:
+ (fun _ -> palette_visible := false; palette#misc#hide (); true);
+ view_menu#add_item "Palette"
+ ~callback:(fun () ->
+ if !palette_visible then begin
+ palette#misc#hide ();
+ palette_visible := false
+ end else begin
+ palette#misc#show ();
+ palette_visible := true
+ end);
+ let prop_win_visible = ref true in
+ prop_win#event#connect#delete ~callback:
+ (fun _ -> prop_win_visible := false; prop_win#misc#hide (); true);
+ view_menu#add_item "Properties window"
+ ~callback:(fun () ->
+ if !prop_win_visible then begin
+ prop_win#misc#hide ();
+ prop_win_visible := false
+ end else begin
+ prop_win#misc#show ();
+ prop_win_visible := true
+ end);
+
+ GMain.Main.main ()
+
+let _ = main ()