None -> false
| Some n1' -> descendant_of n1' n2
+let remove_descendants_of (el : Gdome.element) =
+ let rec aux =
+ function
+ [] -> []
+ | hd::tl when descendant_of (hd :> Gdome.node) (el :> Gdome.node) -> aux tl
+ | hd::tl -> hd::(aux tl)
+ in
+ aux
+
(* mem el l = true if the node n is stored in the list l *)
let mem (el : Gdome.element) =
let rec mem_aux =
class single_selection_math_view obj =
object(self)
inherit GMathView.math_view_skel obj
- val mutable root_selection = None
+ val mutable first_selected = None
+ val mutable root_selected = None
val mutable selection_changed = (fun _ -> ())
- method set_selection root_selection' =
+ method set_selection elem =
begin
- match root_selection with
+ match root_selected with
None -> ()
| Some e -> self#unselect e
end;
- root_selection <- root_selection';
- match root_selection' with
+ root_selected <- elem;
+ match elem with
None -> ()
| Some e -> self#select e
- method get_selection = root_selection
+ method get_selection = root_selected
method connect =
new single_selection_math_view_signals obj (function f -> selection_changed <- f)
+ method action_toggle (elem : Gdome.element) =
+ match elem#get_namespaceURI, elem#get_localName with
+ Some ns, Some ln when ns#to_string = "http://www.w3.org/1998/Math/MathML" &&
+ ln#to_string = "maction" ->
+ begin
+ let selection_attr = Gdome.domString "selection" in
+ let selection =
+ if elem#hasAttribute ~name:selection_attr then
+ int_of_string (elem#getAttribute ~name:selection_attr)#to_string
+ else
+ 1
+ in
+ self#freeze ;
+ (* the widget will cast the index back into a valid range *)
+ elem#setAttribute ~name:selection_attr ~value:(Gdome.domString (string_of_int (selection + 1))) ;
+ self#thaw ;
+ true
+ end
+ | _ ->
+ begin
+ match elem#get_parentNode with
+ Some p ->
+ begin
+ try
+ self#action_toggle (new Gdome.element_of_node p)
+ with
+ GdomeInit.DOMCastException _ -> false
+ end
+ | None -> assert false (* every element has a parent *)
+ end
+
initializer
ignore
- (self#connect#press_move
- (fun (first: Gdome.element option) (last: Gdome.element option) ->
- match first, last with
+ (self#connect#select_begin
+ (fun (elem : Gdome.element option) _ ->
+ if not (elem = root_selected) then selection_changed elem ;
+ first_selected <- elem)) ;
+
+ ignore
+ (self#connect#select_over
+ (fun (elem : Gdome.element option) _ ->
+ match first_selected, elem with
None, _
| _, None -> selection_changed None
| Some first', Some last' ->
selection_changed
(Some (new Gdome.element_of_node (common_ancestor (first' :> Gdome.node) (last' :> Gdome.node)))))) ;
- ignore (self#connect#clicked (fun _ -> self#set_selection None))
+
+ ignore
+ (self#connect#select_end
+ (fun (elem : Gdome.element option) _ -> first_selected <- None)) ;
+
+ ignore
+ (self#connect#select_abort
+ (fun () ->
+ first_selected <- None ;
+ selection_changed None)) ;
+
+ ignore (self#connect#click (fun _ _ -> self#set_selection None))
end
;;
method remove_selections =
List.iter (fun e -> self#unselect e) selected ;
- selected <- []
+ selected <- [] ;
+ match self#get_selection with
+ None -> ()
+ | Some e -> self#select e
method add_selection (elem : Gdome.element) =
- if not (mem elem selected) then
- selected <- elem::selected ;
- self#select elem
+ selected <- elem::(remove_descendants_of elem selected) ;
+ self#select elem
method get_selections = selected
- method set_selection root_selection' =
+ method set_selection elem =
begin
- match root_selection with
+ match root_selected with
None -> ()
| Some e -> self#unselect e ; List.iter (fun e -> self#select e) selected
end;
- root_selection <- root_selection';
- match root_selection' with
+ root_selected <- elem;
+ match elem with
None -> ()
| Some e -> self#select e
- end
-;;
+
+ initializer
+ ignore
+ (self#connect#select_begin
+ (fun _ state ->
+ if not (List.mem `CONTROL (Gdk.Convert.modifier state)) then self#remove_selections)) ;
+
+ ignore
+ (self#connect#select_over
+ (fun _ state ->
+ Printf.printf "stable selections: %d\n" (List.length selected) ;
+ Printf.printf "select_over with state: " ;
+ let c =
+ function
+ `SHIFT -> "shift "
+ | `LOCK -> "lock "
+ | `CONTROL -> "control "
+ | `MOD1 -> "mod1 "
+ | _ -> ""
+ in
+ List.iter (fun x -> print_string (c x)) (Gdk.Convert.modifier state) ;
+ print_char '\n' ;
+ flush stdout)) ;
+
+ ignore
+ (self#connect#select_end
+ (fun _ state ->
+ Printf.printf "select_end\n" ; flush stdout ;
+ if not (List.mem `CONTROL (Gdk.Convert.modifier state)) then self#remove_selections ;
+ match root_selected with
+ None -> ()
+ | Some e -> self#set_selection None ; self#add_selection e))
+
+ end
+ ;;
let multi_selection_math_view ?adjustmenth ?adjustmentv ?font_size ?font_manager ?border_width
?width ?height ?packing ?show () =