Delivered-To: lablgtk at yquem.inria.fr DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:received:date:to:subject:message-id:mail-followup-to:references:mime-version:content-type:content-disposition:in-reply-to:user-agent:from; bh=x++ITZMOkTHrqy/AFb7J6kSUFFEHTtuJuvS9EWckulc=; b=hEoLK0m44OB1p+JnFfVCQZ41QIjtatrXLbn5EGwlNlFEcd08jS/3Tfyf98uzfRsPu+EuXqEfjQxgcnoxm/msEWsxl/7NueBhRFpzlpOvktUHjJmnfRc6YhN6cfEP7oJ7RkhEYQCNdhLHQl2y7pam8S6vnle8asyJM0vks8UX1w8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:to:subject:message-id:mail-followup-to:references:mime-version:content-type:content-disposition:in-reply-to:user-agent:from; b=uMYzcE8lGAPWVV+G5yIUhHHgcRPOP2wCy1NhT7chRTroCVgtpggA3TrcLbhi2qj6RrV/VO09kLDRiT6aA7LTHNE7fHwF3BveXSesczstM2USm7O8zD2fvTdfG4ZzxNjpeOUNmoLzVYITzYYa8ezPgSaHAG0bZeD7gfPvhP4s7e0= Date: Sat, 16 Feb 2008 03:07:26 +0100 To: lablgtk at yquem.inria.fr Subject: Re: [Lablgtk] tooltip on treeview cell Message-ID: <20080216020726.GA20404 at localhost> Mail-Followup-To: Julien Moutinho , lablgtk@yquem.inria.fr References: <87ejbfc9z1.fsf at wanadoo.fr> <20080215154858.GA11325 at localhost> <87y79maq7u.fsf@wanadoo.fr> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <87y79maq7u.fsf at wanadoo.fr> From: Julien Moutinho Content-Type: multipart/mixed; boundary="6c2NcOVqGQ03X4Wi" Content-Length: 11443 --6c2NcOVqGQ03X4Wi Content-Type: text/plain; charset=utf-8 Content-Disposition: inline On Fri, Feb 15, 2008 at 03:01:57PM -0600, Yoann Padioleau wrote: > Julien Moutinho writes: > > On Thu, Feb 14, 2008 at 06:57:38PM -0600, Yoann Padioleau wrote: > >> How can I set the tooltip for a cell in a treeview ? > >> Apparently the other gtk bindings offer a method > >> set_tooltip_tree_cell() but I didn't find it in > >> lablgtk. > > > > AFAIK, if you use a GTK+ whose version is lower than 2.12, > > then its tooltip machinery, GtkTooltips (note the 's'), > > does not handle treeview tooltips. > > So the usual way is to do it manually, that is, to hook > > a motion_notify callback to the treeview, which will call > > a get_path_at_pos to retrieve the treeview cell under the cursor, > > whose data is then used to hide/show a popup window actually > > being the tooltip. > > > Is there some (ocaml) code somewhere that does exactly this ? FWIW, I'm joining to my mail a quite big chunk of OCaml code I wrote when I was experimenting this way. It is far from being perfect, but it should give you a fair overview of what could be done. > > However GTK+ 2.12 came up with a new tooltip machinery, > > GtkTooltip (no 's' now), which is way more powerful > > and handles treeview tooltips: > > http://mail.gnome.org/archives/gtk-devel-list/2007-June/msg00092.html > > > > A few months ago, I've wrapped GtkTooltip into the SVN of LablGTK: > > http://svn.gna.org/viewcvs/lablgtk/trunk > > One example for doing what you want with it being there: > > http://svn.gna.org/viewcvs/lablgtk/trunk/examples/tooltip.ml?rev=1392 > > I get this when I try to compile tooltip.ml from > the lablgtk subversion repository: > > $ ocamlc -c -I ../src/ tooltip.ml > File "tooltip.ml", line 66, characters 1-12: > This expression has type GObj.misc_ops > It has no method set_tooltip_text > > Do I also need a special version of lablgtk ? Unfortunately yes, you need the commit bringing the GtkTooltip wrap; the easiest is to checkout the branch named after me: svn co svn://svn.gna.org/svn/lablgtk/branches/moutinho lablgtk And before you configure'ing or make'ing anything, make sure you have GLib 2.14 plus GTK+2.12 installed, http://www.gtk.org/download-linux.html Once you've been able to compile and run tooltip.ml, try to stroll the mouse on the widgets a little long; if you end up with a segfault, you may try the patch joined to my previous mail. HTH. --6c2NcOVqGQ03X4Wi Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="tooltips.ml" Content-Transfer-Encoding: quoted-printable (* ocamlc -o tooltips -I +lablgtk2 lablgtk.cma gtkInit.cmo tooltips.ml && .= /tooltips *) class contact ~(name: string) () =3D object (self) method name =3D name end class account ~(name: string) ~(contacts: contact list) () =3D object (self) method name =3D name method contacts =3D contacts end let model () =3D let cols =3D new GTree.column_list in let column =3D cols#add Gobject.Data.caml in let model =3D GTree.tree_store cols in List.iter begin fun account -> let row =3D model#append () in model#set ~row ~column (`Account account); List.iter begin fun contact -> let row =3D model#append ~parent: row () in model#set ~row ~column (`Contact contact) end account#contacts end [ new account () ~name: "Fernand Naudin" ~contacts: [ new contact () ~name: "Ma=C3=AEtre Folace" ; new contact () ~name: "Jean" ] ; new account () ~name: "Raoul Volfoni" ~contacts: [ new contact () ~name: "Paul Volfoni" ] ]; (model, column) class tooltip ?(show_delay =3D 1000) ?(hide_delay =3D 2000) () =3D object (self) val window =3D GWindow.window () ~title: "gtk-tooltips" ~resizable: true ~kind: `POPUP ~border_width: 1 ~show: true method window =3D window val style =3D new GObj.style (GtkData.Style.create ()) =09 val show_delay =3D show_delay val hide_delay =3D hide_delay val mutable is_hidden =3D true method is_hidden =3D is_hidden method show =3D is_hidden <- false; window#show () method hide =3D is_hidden <- true; window#misc#hide () val mutable timeout =3D None (* the timeout to hide/show the window *) =09 method stop_timeout ?(on_some =3D (ignore: unit -> unit)) () =3D match timeout with | Some id -> GMain.Timeout.remove id; timeout <- None; on_some () | None -> () method start_timeout ?(on_some =3D (ignore: unit -> unit)) ?(on_expire =3D (fun () -> self#hide)) ?(ms =3D hide_delay) () =3D self#stop_timeout () ~on_some; timeout <- Some (GMain.Timeout.add ~ms ~callback: (fun _ -> timeout <- None; on_expire (); false)) =09 initializer window#misc#set_app_paintable true; (* style *) let state_type =3D `NORMAL in style#set_bg [state_type, `BLACK]; window#misc#set_style style; (* callbacks *) let _ =3D window#connect#destroy ~callback: GMain.quit in let _ =3D window#event#connect#enter_notify ~callback: (fun ev -> self#stop_timeout (); true) in let _ =3D window#event#connect#leave_notify ~callback: (fun ev -> self#start_timeout (); true) in () =09 method set (content: GPack.box) =3D let module Private =3D struct exception Exn end in try let child =3D try window#child with Gpointer.Null -> raise Private.Ex= n in if child#get_oid <> content#get_oid then (child#destroy (); window#add content#coerce); with Private.Exn -> window#add content#coerce end class type ['cell] treeview_tooltip_content =3D object method box : GPack.box (* the box to be packed within the tooltip window *) method has_changed : 'cell -> 'cell -> bool (* to avoid useless refresh *) method set : path: Gtk.tree_path -> (* the path to the cell *) connection: (GObj.event_ops -> unit) -> (* to stop the timeout hidding the tooltip *) 'cell -> unit (* to update the tooltip content *) end class ['cell] treeview_tooltip ~(content: 'cell treeview_tooltip_content) (* the object used to put the tooltip content up to date *) ~(column: 'cell GTree.column) (* the column holding the tooltip data used to get the tooltip content = *) ~(treeview: GTree.view) (* the treeview related to the tooltip *) ~(get_position: tooltip_rect: Gtk.rectangle -> GdkEvent.Motion.t -> int *= int) (* coordinates where the tooltip shall be *) ?(hide_delay =3D 2000) () =3D object (self) inherit tooltip () ~hide_delay as super_tooltip =09 val mutable last_cell =3D None (* the content of the last cell for which a tooltip has been drawn *) =09 initializer (* callback that try to refresh the tooltip * when the mouse is over the treeview *) let _ =3D treeview#event#connect#motion_notify ~callback: (fun ev -> self#start_timeout () ~ms: show_delay ~on_some: (fun _ -> last_cell <- None) ~on_expire: begin fun _ -> match treeview#get_path_at_pos ~x: (int_of_float (GdkEvent.Motion.x ev)) ~y: (int_of_float (GdkEvent.Motion.y ev)) with | Some (path, view_col, _, _) -> self#stop_timeout (); let row =3D treeview#model#get_iter path in let cell =3D treeview#model#get ~row ~column in (match last_cell with | Some old_cell when not (content#has_changed old_cell cell) -> () | _ -> last_cell <- Some cell; content#set cell ~path ~connection: begin fun event -> let _ =3D event#connect#enter_notify ~callback: (fun ev -> self#stop_timeout (); true) in let _ =3D event#connect#leave_notify ~callback: (fun ev -> self#start_timeout (); true) in let _ =3D event#connect#button_press ~callback: (fun ev -> self#hide; true) in () end; self#set content#box; let {Gtk.x=3Dtx; y=3Dty; width=3Dtw; height=3Dth} as tooltip_rect =3D GtkBase.Widget.allocation self#window#as_widget in let x, y =3D get_position ~tooltip_rect ev in let sw, sh =3D Gdk.Screen.width (), Gdk.Screen.height () in let x =3D (* set x inside the screen *) if x < 0 then 0 else if x + tw > sw then sw - tw else x in let y =3D (* set y inside the screen *) if y < 0 then 0 else if y + th > sh then sh - th else y in self#show; self#window#move ~x ~y) | _ -> self#start_timeout () end; true) in let _ =3D treeview#event#connect#leave_notify ~callback: (fun ev -> self#start_timeout (); true) in () end let main () =3D let (model, column) =3D model () in let window =3D GWindow.window () ~title: "TreeView" ~show: true in let vbox =3D GPack.vbox () ~border_width: 0 ~spacing: 8 ~packing: window#add in let sw =3D GBin.scrolled_window () ~shadow_type: `ETCHED_IN ~hpolicy: `NEVER ~vpolicy: `AUTOMATIC ~packing: vbox#add in let _ =3D window#connect#destroy ~callback: GMain.quit in =09 let treeview =3D GTree.view () ~model ~packing: sw#add in =09 let col =3D GTree.view_column () ~title: "Column title" in let renderer_name =3D GTree.cell_renderer_text [] in col#set_sizing `FIXED; col#set_fixed_width 50; col#pack renderer_name; col#set_cell_data_func renderer_name begin fun model row -> match model#get ~row ~column with | `Account account -> let text =3D account#name in renderer_name#set_properties [ `TEXT text ; `WEIGHT `BOLD ] | `Contact contact -> renderer_name#set_properties [ `TEXT contact#name ; `WEIGHT `NORMAL ] end; ignore (treeview#append_column col); =09 let tooltip_tree_view =3D new treeview_tooltip () ~column ~treeview: treeview ~get_position: begin fun ~tooltip_rect ev -> let cursor_x =3D int_of_float (GdkEvent.Motion.x_root ev) in let cursor_y =3D int_of_float (GdkEvent.Motion.y_root ev) in cursor_x + 16, cursor_y + 16 end ~content: begin object (self: 'self) constraint 'self =3D 'cell #treeview_tooltip_content val vbox =3D GPack.vbox () ~border_width: 0 ~spacing: 0 val style =3D new GObj.style (GtkData.Style.create ()) initializer let state_type =3D `NORMAL in style#set_bg [state_type, `NAME "yellow"]; style#set_fg [state_type, `BLACK]; method set ~path ~connection cell =3D List.iter (fun child -> child#destroy ()) vbox#children; let event_box =3D GBin.event_box () ~packing: vbox#add in connection event_box#event; event_box#misc#set_style style; let path_string =3D GtkTree.TreePath.to_string path in let name =3D (* XXX: be careful to do a match on the good thing: no static type che= cking *) match cell with | `Account o -> o#name | `Contact o -> o#name in let markup =3D "path=3D" ^ path_string ^ " name=3D" ^ name ^ = "" in let _ =3D GMisc.label () ~markup ~packing: event_box#add in () method box =3D vbox method has_changed old_cell cell =3D old_cell !=3D cell end end in let _ =3D window#event#connect#configure ~callback: (fun _ -> tooltip_tree_view#hide; false) in () ;; main ();; GMain.Main.main () --6c2NcOVqGQ03X4Wi Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Lablgtk mailing list Lablgtk@yquem.inria.fr http://yquem.inria.fr/cgi-bin/mailman/listinfo/lablgtk --6c2NcOVqGQ03X4Wi--