Notebooks

The NoteBook Widget is a collection of “pages” that overlap each other, each page contains different information with only one page visible at a time. This widget has become more common lately in GUI programming, and it is a good way to show blocks of similar information that warrant separation in their display.

The first function call you will need to know, as you can probably guess by now, is used to create a new notebook widget: see GPack.notebook.

val GPack.notebook :
	?enable_popup:bool ->
	?homogeneous_tabs:bool ->
	?scrollable:bool ->
	?show_border:bool ->
	?show_tabs:bool ->
	?tab_border:int ->
	?tab_pos:Gtk.Tags.position ->
	?border_width:int ->
	?width:int ->
	?height:int ->
	?packing:(GObj.widget -> unit) ->
	?show:bool -> unit -> notebook

Once the notebook has been created, there are a number of functions that operate on the notebook widget. Let’s look at them individually.

The first one we will look at is how to position the page indicators. These page indicators or “tabs” as they are referred to, can be positioned in four ways: top, bottom, left, or right.

method set_tab_pos : Gtk.Tags.position -> unit

Gtk.Tags.position will be one of the following, which are pretty self explanatory:

  `LEFT
  `RIGHT
  `TOP
  `BOTTOM

`TOP is the default.

Next we will look at how to add pages to the notebook. There are three ways to add pages to the NoteBook. Let’s look at the first two together as they are quite similar.

method append_page :
	?tab_label:GObj.widget ->
	?menu_label:GObj.widget ->
	GObj.widget -> unit

method prepend_page :
	?tab_label:GObj.widget ->
	?menu_label:GObj.widget ->
	GObj.widget -> unit

These functions add pages to the notebook by inserting them from the back of the notebook (append), or the front of the notebook (prepend). The given widget is placed within the notebook page, and tab_label is the label for the page being added. The given widget must be created separately, and is typically a set of options setup within one of the other container widgets, such as a table.

The final function for adding a page to the notebook contains all of the properties of the previous two, but it allows you to specify what position you want the page to be in the notebook.

method insert_page :
	?tab_label:GObj.widget ->
	?menu_label:GObj.widget ->
	pos:int ->
	GObj.widget -> unit

The parameters are the same as append and prepend except it contains an extra parameter, pos. This parameter is used to specify what place this page will be inserted into the first page having position zero.

Now that we know how to add a page, lets see how we can remove a page from the notebook.

method remove_page : int -> unit

This function takes the page number of int type and removes it from the notebook.

To find out what the current page is in a notebook use the function:

method current_page : int

These next two functions are simple calls to move the notebook page forward or backward. Simply provide the respective function call with the notebook widget you wish to operate on. Note: When the NoteBook is currently on the last page, and next_page() is called, the notebook will wrap back to the first page. Likewise, if the NoteBook is on the first page, and prev_page() is called, the notebook will wrap to the last page.

method next_page : unit -> unit
method previous_page : unit -> unit

This next function sets the “active” page. If you wish the notebook to be opened to page 5 for example, you would use this function. Without using this function, the notebook defaults to the first page.

method goto_page : int -> unit

The next two functions add or remove the notebook page tabs and the notebook border respectively.

method set_show_tabs : bool -> unit
method set_show_border : bool -> unit

The next function is useful when the you have a large number of pages, and the tabs don’t fit on the page. It allows the tabs to be scrolled through using two arrow buttons.

method set_scrollable : bool -> unit

show_tabs, show_border and scrollable methods can be either true or false.

Now let’s look at an example, it is expanded from the testgtk.c code that comes with the GTK distribution. This small program creates a window with a notebook and six buttons. The notebook contains 11 pages, added in three different ways, appended, inserted, and prepended. The buttons allow you rotate the tab positions, add/remove the tabs and border, remove a page, change pages in both a forward and backward manner, and exit the program.

notebooks

(* file: notebook.ml *)

(* This function rotates the position of the tabs *)
let rotate_book notebook () =
  notebook#set_tab_pos
    (match notebook#tab_pos with
    | `BOTTOM -> `LEFT
    | `LEFT -> `TOP
    | `TOP -> `RIGHT
    | `RIGHT -> `BOTTOM
	)

(* Add/Remove the page tabs and the borders *)
let tabsborder_book notebook () =
  notebook#set_show_tabs (not notebook#show_tabs);
  notebook#set_show_border (not notebook#show_border)

(* Remove a page from the notebook *)
let remove_book notebook () =
  notebook#remove_page notebook#current_page;
  ()

let main () =
  let window = GWindow.window ~title:"Notebook demo" ~border_width:10 ()in
  window#connect#destroy ~callback:GMain.Main.quit;
  
  let table = GPack.table ~rows:3 ~columns:6 ~packing:window#add () in

  (* Create a new notebook, place the position of the tabs *)
  let notebook = GPack.notebook ~tab_pos:`TOP
    ~packing:(table#attach ~left:0 ~right:6 ~top:0) () in

  for i = 1 to 5 do
	let text = "Append Frame " ^ string_of_int i in
	let label = GMisc.label ~text:("Page " ^ string_of_int i) () in
    let frame = GBin.frame ~label:text ~width:100 ~height:75 ~border_width:10
	  ~packing:(notebook#append_page ~tab_label:label#coerce) () in
	let label = GMisc.label ~text ~packing:frame#add () in
	()
  done;

  (* Now let's add a page to a specified spot *)
  let label = GMisc.label ~text:"Add page" () in
  let checkbutton = GButton.check_button ~label:"Check me please!"
	~packing:(notebook#insert_page ~tab_label:label#coerce ~pos:2) ()
	in
  checkbutton#misc#set_size_request ~width:100 ~height:75 ();

  (* Now finaly let's prepend pages to the notebook *)
  for i = 1 to 5 do
	let text = "Prepend Frame " ^ string_of_int i in
	let label = GMisc.label ~text:("PPage " ^ string_of_int i) () in
    let frame = GBin.frame ~label:text ~width:100 ~height:75 ~border_width:10
	  ~packing:(notebook#prepend_page ~tab_label:label#coerce) () in
	let label = GMisc.label ~text ~packing:frame#add () in
	()
  done;

  (* Set what page to start at (page 4) *)
  notebook#goto_page 3;

  (* Create a bunch of buttons *)
  let button = GButton.button ~label:"close" 
    ~packing:(table#attach ~left:0 ~top:1) () in
  button#connect#clicked ~callback:GMain.Main.quit;

  let button = GButton.button ~label:"next page" 
    ~packing:(table#attach ~left:1 ~top:1) () in
  button#connect#clicked ~callback:notebook#next_page;

  let button = GButton.button ~label:"prev page" 
    ~packing:(table#attach ~left:2 ~top:1) () in
  button#connect#clicked ~callback:notebook#previous_page;

  let button = GButton.button ~label:"tab position" 
    ~packing:(table#attach ~left:3 ~top:1) () in
  button#connect#clicked ~callback:(rotate_book notebook);

  let button = GButton.button ~label:"tabs/border on/off" 
    ~packing:(table#attach ~left:4 ~top:1) () in
  button#connect#clicked ~callback:(tabsborder_book notebook);

  let button = GButton.button ~label:"remove page" 
    ~packing:(table#attach ~left:5 ~top:1) () in
  button#connect#clicked ~callback:(remove_book notebook);

  window#show ();
  GMain.Main.main ()

let _ = Printexc.print main ()

I hope this helps you on your way with creating notebooks for your GTK applications.

comments powered by Disqus