let slicing_selector (popup_factory:GMenu.menu GMenu.factory)
    (main_ui:Design.main_window_extension_points) ~button localizable =
  if (not (Db.Value.is_computed ())) || not (Enabled.get ())
  then
    ignore
      (popup_factory#add_item "Enable _slicing"
         ~callback:
         (fun () ->
            if (not (Db.Value.is_computed ()))
            then gui_compute_values main_ui ;
            if Db.Value.is_computed ()
            then (Enabled.set true;
                  !show_column ())
         ))
  else
    let slicing_project = !Db.Slicing.Project.get_project () in
    if button = 1 then
      begin let level = 1 in
      let slicing_view project =
        gui_annot_info main_ui ~level (fun () -> "Highlighting for " ^ (!Db.Slicing.Project.get_name project))
      in
      Extlib.may slicing_view slicing_project;
      if SlicingParameters.verbose_atleast level then begin
        let slicing_mark project =
          let slicing_mark kf get_mark =
            (* use -slicing-debug -verbose to get slicing mark information *)
            let add_mark_info txt = gui_annot_info ~level main_ui (fun () -> "Tag: " ^ (txt ())) in
            let slices = !Db.Slicing.Slice.get_all project kf in
            match slices with
            | [] -> (* No slice for this kf *)
                add_mark_info (fun () ->
                                 if !Db.Slicing.Project.is_called project kf
                                 then (* but the source function is called *)
                                   (Pretty_utils.sfprintf "<src>%a"
                                      !Db.Slicing.Mark.pretty (!Db.Slicing.Mark.get_from_src_func project kf))
                                 else
                                   "<   ><   >")
            | slices ->
                if !Db.Slicing.Project.is_called project kf
                then begin (* The source function is also called *)
                  assert (not (kf == fst (Globals.entry_point ()))) ;
                  add_mark_info (fun () ->
                                   Pretty_utils.sfprintf "<src>%a"
                                     !Db.Slicing.Mark.pretty (!Db.Slicing.Mark.get_from_src_func project kf))
                end ;
                let mark_slice slice =
                  add_mark_info (fun () -> Pretty_utils.sfprintf "%a" !Db.Slicing.Mark.pretty (get_mark slice))
                in List.iter mark_slice slices
          in match localizable with
          | Pretty_source.PTermLval(Some kf,(Kstmt ki),_) (* as for the statement *)
          | Pretty_source.PLval (Some kf,(Kstmt ki),_) (* as for the statement *)
          | Pretty_source.PStmt (kf,ki) -> slicing_mark kf (fun slice -> !Db.Slicing.Slice.get_mark_from_stmt slice ki)
          | Pretty_source.PVDecl (Some kf,vi) -> slicing_mark kf (fun slice -> !Db.Slicing.Slice.get_mark_from_local_var slice vi)
          | _ -> ()
        in Extlib.may slicing_mark slicing_project
      end
      end
    else if button = 3 then begin
      let submenu = popup_factory#add_submenu "Slicing" in
      let slicing_factory =
        new Design.protected_menu_factory (main_ui:>Gtk_helper.host) submenu
      in
      (* definitions for slicing plug-in *)
      let add_slicing_item name = add_item slicing_factory name in
      let mk_slice = gui_mk_slice main_ui in
      let add_slice_menu kf_opt kf_ki_opt =
        (let callback kf =
           mk_slice
             ~info:(fun () ->
               Pretty_utils.sfprintf
                 "Request for slicing effects of function %a"
                 Kernel_function.pretty kf)
             (mk_selection_all !Db.Slicing.Select.select_func_calls_to kf)
         in
         add_slicing_item "Slice calls to" kf_opt ~callback);

        (let callback kf =
           mk_slice
             ~info:(fun () ->
               Pretty_utils.sfprintf
                 "Request for slicing entrance into function %a"
                 Kernel_function.pretty kf)
             (mk_selection_all !Db.Slicing.Select.select_func_calls_into kf)
         in
        add_slicing_item "Slice calls into" kf_opt ~callback);

        (let callback kf =
           mk_slice
             ~info:(fun () ->
               Pretty_utils.sfprintf
                 "Request for returned value of function %a"
                 Kernel_function.pretty kf)
             (mk_selection_all !Db.Slicing.Select.select_func_return kf)
         in
         add_slicing_item "Slice result"
           (Extlib.opt_filter
              (fun kf ->
                let is_not_void_kf x =
                  match x.Cil_types.vtype with
                  | Cil_types.TFun (Cil_types.TVoid (_),_,_,_) -> false
                  | _ -> true
                in is_not_void_kf (Kernel_function.get_vi kf))
              kf_opt)
           ~callback);

        (let callback (kf, ki) =
           mk_slice
             ~info:(fun () ->
               Pretty_utils.sfprintf
                 "Request for slicing effects of statement %d"
                 ki.sid)
             (mk_selection_all !Db.Slicing.Select.select_stmt ki kf)
         in
         add_slicing_item "Slice stmt" kf_ki_opt ~callback);

        (let callback (kf, ki) =
          let do_with_txt txt =
            try
              let lval_str =
                Datatype.String.Set.add txt Datatype.String.Set.empty
              in
              mk_slice
                ~info:(fun () ->
                  Pretty_utils.sfprintf
                    "Request for slicing Lvalue %s before statement %d"
                    txt
                    ki.sid)
                (mk_selection_cad !Db.Slicing.Select.select_stmt_lval
                   lval_str ~before:true ki ~scope:ki ~eval:ki kf)
            with e ->
              main_ui#error "Invalid expression: %s" (Printexc.to_string e)
          in
          let txt =
            GToolbox.input_string
              ~title:"Input a pure Lvalue expression to slice before current statement"
              ""
          in
          Extlib.may do_with_txt txt
        in
        add_slicing_item "Slice lval" kf_ki_opt ~callback);

        (let callback (kf, ki) =
           let do_with_txt txt =
             try
               let lval_str =
                 Datatype.String.Set.add txt Datatype.String.Set.empty
               in
               mk_slice
                 ~info:(fun () ->
                   Pretty_utils.sfprintf
                     "Request for slicing read accesses to Lvalue %s"
                     txt)
                 (mk_selection_cad
                    !Db.Slicing.Select.select_func_lval_rw
                    ~rd:lval_str
                    ~wr:Datatype.String.Set.empty
                    ~scope:ki
                    ~eval:ki kf)
             with e ->
               main_ui#error "Invalid expression: %s" (Printexc.to_string e)
           in
           let txt =
             GToolbox.input_string
               ~title:"Input a pure Lvalue expression to slice read accesses"
               ""
           in
           Extlib.may do_with_txt txt
         in
         add_slicing_item "Slice rd" kf_ki_opt ~callback);

        (let callback (kf, ki) =
           let do_with_txt txt =
             try
               let lval_str =
                 Datatype.String.Set.add txt Datatype.String.Set.empty
               in
               mk_slice
                 ~info:(fun () ->
                   Pretty_utils.sfprintf
                     "Request for slicing writen accesses to Lvalue %s"
                     txt)
                 (mk_selection_cad
                    !Db.Slicing.Select.select_func_lval_rw
                    ~rd:Datatype.String.Set.empty
                    ~wr:lval_str
                    ~scope:ki
                    ~eval:ki kf)
             with e ->
               main_ui#error "Invalid expression: %s" (Printexc.to_string e)
           in
           let txt =
             GToolbox.input_string
               ~title:"Input a pure Lvalue expression to slice read accesses"
               ""
           in
           Extlib.may do_with_txt txt
         in
        add_slicing_item "Slice wr" kf_ki_opt ~callback);

        let callback (kf, ki) =
          mk_slice
            ~info:(fun () ->
              Pretty_utils.sfprintf
                "Request for slicing accessibility to statement %d"
                ki.sid)
            (mk_selection_all !Db.Slicing.Select.select_stmt_ctrl ki kf)
        in
        add_slicing_item "Slice ctrl" kf_ki_opt ~callback
      in
      let some_kf_from_vi vi =
        try let kf = Globals.Functions.get vi in
        if Enabled.get () && !Db.Value.is_called kf then Some kf else None
        with Not_found -> None in
      let some_kf_from_lv  lv =
        match lv with
        | Var vi,_ -> some_kf_from_vi vi
        | _ -> None in
      let some_kf_ki kf stmt =
        if Enabled.get ()
          && !Db.Value.is_called kf
          && Db.Value.is_reachable_stmt stmt
        then Some (kf, stmt) else None in
      begin  (* add menu for slicing and scope plug-in *)
        match localizable with
        | Pretty_source.PLval (Some kf,(Kstmt stmt),lv) ->
            add_slice_menu (some_kf_from_lv lv) (some_kf_ki kf stmt)
        | Pretty_source.PTermLval(Some kf,(Kstmt ki),_) (* as for the statement *)
        | Pretty_source.PStmt (kf,ki) ->
            add_slice_menu None (some_kf_ki kf ki)
        | Pretty_source.PVDecl (_,vi) ->
            add_slice_menu (some_kf_from_vi vi) None
        | _  ->
            add_slice_menu None None
      end;
      let projects = !Db.Slicing.Project.get_all() in
      ignore (slicing_factory#add_separator ());
      add_slicing_item "_Disable"
        (Some ())
        ~callback:(fun () -> Enabled.set false);
      add_slicing_item "_Clear"
        (if slicing_project = None then None else Some ())
        ~callback:(fun () -> gui_set_project main_ui None) ;
      List.iter
        (fun proj ->
           let add_highlight_menu sensitive =
             add_slicing_item
               ("Highlight " ^ (Pretty_utils.escape_underscores (!Db.Slicing.Project.get_name proj)))
               sensitive
               ~callback:(fun () -> gui_set_project main_ui (Some proj))
           in match slicing_project with
           | Some project -> add_highlight_menu (if (proj == project) then None else Some ())
           | None -> add_highlight_menu (Some()))
        projects;
    end