2014-02-16 14:55:51 -06:00
// +build !windows,!darwin,!plan9
// TODO is there a way to simplify the above? :/
// 16 february 2014
2014-03-12 20:55:45 -05:00
2014-02-19 10:41:10 -06:00
package ui
2014-02-16 14:55:51 -06:00
import (
2014-04-09 11:04:04 -05:00
"fmt"
2014-02-16 14:55:51 -06:00
"unsafe"
)
// #cgo pkg-config: gtk+-3.0
2014-03-16 09:34:12 -05:00
// #include "gtk_unix.h"
2014-02-16 14:55:51 -06:00
import "C"
2014-04-27 11:43:15 -05:00
func gtk_init ( ) error {
var err * C . GError = nil // redundant in Go, but let's explicitly assign it anyway
// gtk_init_with_args() gives us error info (thanks chpe in irc.gimp.net/#gtk+)
2014-02-16 14:55:51 -06:00
// TODO allow GTK+ standard command-line argument processing
2014-04-27 11:43:15 -05:00
result := C . gtk_init_with_args ( nil , nil , nil , nil , nil , & err )
if result == C . FALSE {
return fmt . Errorf ( "%s" , fromgstr ( err . message ) )
}
return nil
2014-02-16 16:09:58 -06:00
}
2014-02-16 14:55:51 -06:00
func gtk_main ( ) {
C . gtk_main ( )
}
2014-03-05 12:25:19 -06:00
func gtk_main_quit ( ) {
C . gtk_main_quit ( )
}
2014-04-01 15:30:38 -05:00
func gtk_window_new ( ) * C . GtkWidget {
return C . gtk_window_new ( C . GTK_WINDOW_TOPLEVEL )
2014-02-16 14:55:51 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_widget_show ( widget * C . GtkWidget ) {
C . gtk_widget_show_all ( widget )
2014-02-16 14:55:51 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_widget_hide ( widget * C . GtkWidget ) {
C . gtk_widget_hide ( widget )
2014-02-16 14:55:51 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_window_set_title ( window * C . GtkWidget , title string ) {
2014-02-16 14:55:51 -06:00
ctitle := C . CString ( title )
defer C . free ( unsafe . Pointer ( ctitle ) )
2014-04-26 21:55:43 -05:00
C . gtk_window_set_title ( togtkwindow ( window ) , togstr ( ctitle ) )
2014-02-16 14:55:51 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_window_get_title ( window * C . GtkWidget ) string {
2014-04-26 21:55:43 -05:00
return fromgstr ( C . gtk_window_get_title ( togtkwindow ( window ) ) )
2014-02-16 17:57:50 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_window_resize ( window * C . GtkWidget , width int , height int ) {
2014-02-17 14:45:26 -06:00
C . gtk_window_resize ( togtkwindow ( window ) , C . gint ( width ) , C . gint ( height ) )
2014-02-16 14:55:51 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_window_get_size ( window * C . GtkWidget ) ( int , int ) {
2014-02-16 17:04:57 -06:00
var width , height C . gint
2014-02-17 14:45:26 -06:00
C . gtk_window_get_size ( togtkwindow ( window ) , & width , & height )
2014-02-16 17:04:57 -06:00
return int ( width ) , int ( height )
}
2014-04-09 11:04:04 -05:00
// on some themes, such as oxygen-gtk, GtkLayout draws a solid-color background, not the window background (as GtkFixed and GtkDrawingArea do)
// this CSS fixes it
// thanks to drahnr and ptomato in http://stackoverflow.com/questions/22940588/how-do-i-really-make-a-gtk-3-gtklayout-transparent-draw-theme-background
// TODO report to oxygen-gtk devs
var gtkLayoutCSS = [ ] byte ( ` GtkLayout {
background - color : transparent ;
}
` )
func makeTransparent ( layout * C . GtkWidget ) {
2014-04-27 11:43:15 -05:00
var err * C . GError = nil
2014-04-09 11:04:04 -05:00
provider := C . gtk_css_provider_new ( )
added := C . gtk_css_provider_load_from_data ( provider ,
( * C . gchar ) ( unsafe . Pointer ( & gtkLayoutCSS [ 0 ] ) ) , C . gssize ( len ( gtkLayoutCSS ) ) , & err )
if added == C . FALSE {
2014-04-26 21:55:43 -05:00
message := fromgstr ( err . message )
2014-04-09 11:04:04 -05:00
panic ( fmt . Errorf ( "error loading transparent background CSS for GtkLayout: %s" , message ) )
}
C . gtk_style_context_add_provider ( C . gtk_widget_get_style_context ( layout ) ,
( * C . GtkStyleProvider ) ( unsafe . Pointer ( provider ) ) ,
C . GTK_STYLE_PROVIDER_PRIORITY_USER )
}
2014-03-15 13:27:18 -05:00
// this should allow us to resize the window arbitrarily
// thanks to Company in irc.gimp.net/#gtk+
2014-04-01 15:30:38 -05:00
func gtkNewWindowLayout ( ) * C . GtkWidget {
2014-03-15 13:27:18 -05:00
layout := C . gtk_layout_new ( nil , nil )
2014-04-09 11:04:04 -05:00
makeTransparent ( layout )
2014-03-15 13:27:18 -05:00
scrollarea := C . gtk_scrolled_window_new ( ( * C . GtkAdjustment ) ( nil ) , ( * C . GtkAdjustment ) ( nil ) )
C . gtk_container_add ( ( * C . GtkContainer ) ( unsafe . Pointer ( scrollarea ) ) , layout )
// never show scrollbars; we're just doing this to allow arbitrary resizes
C . gtk_scrolled_window_set_policy ( ( * C . GtkScrolledWindow ) ( unsafe . Pointer ( scrollarea ) ) ,
C . GTK_POLICY_NEVER , C . GTK_POLICY_NEVER )
2014-04-01 15:30:38 -05:00
return scrollarea
2014-02-16 14:55:51 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_container_add ( container * C . GtkWidget , widget * C . GtkWidget ) {
C . gtk_container_add ( togtkcontainer ( container ) , widget )
2014-02-16 14:55:51 -06:00
}
2014-04-01 15:30:38 -05:00
func gtkAddWidgetToLayout ( container * C . GtkWidget , widget * C . GtkWidget ) {
2014-03-15 13:27:18 -05:00
layout := C . gtk_bin_get_child ( ( * C . GtkBin ) ( unsafe . Pointer ( container ) ) )
2014-04-01 15:30:38 -05:00
C . gtk_container_add ( ( * C . GtkContainer ) ( unsafe . Pointer ( layout ) ) , widget )
2014-03-15 13:27:18 -05:00
}
2014-04-01 15:30:38 -05:00
func gtkMoveWidgetInLayout ( container * C . GtkWidget , widget * C . GtkWidget , x int , y int ) {
2014-03-15 13:27:18 -05:00
layout := C . gtk_bin_get_child ( ( * C . GtkBin ) ( unsafe . Pointer ( container ) ) )
2014-04-01 15:30:38 -05:00
C . gtk_layout_move ( ( * C . GtkLayout ) ( unsafe . Pointer ( layout ) ) , widget ,
2014-02-16 14:55:51 -06:00
C . gint ( x ) , C . gint ( y ) )
}
2014-04-01 15:30:38 -05:00
func gtk_widget_set_size_request ( widget * C . GtkWidget , width int , height int ) {
C . gtk_widget_set_size_request ( widget , C . gint ( width ) , C . gint ( height ) )
2014-02-16 14:55:51 -06:00
}
2014-02-16 16:30:58 -06:00
2014-04-01 15:30:38 -05:00
func gtk_button_new ( ) * C . GtkWidget {
return C . gtk_button_new ( )
2014-02-16 16:30:58 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_button_set_label ( button * C . GtkWidget , label string ) {
2014-02-16 16:30:58 -06:00
clabel := C . CString ( label )
defer C . free ( unsafe . Pointer ( clabel ) )
2014-04-26 21:55:43 -05:00
C . gtk_button_set_label ( togtkbutton ( button ) , togstr ( clabel ) )
2014-02-16 16:30:58 -06:00
}
2014-02-16 17:41:29 -06:00
2014-04-01 15:30:38 -05:00
func gtk_button_get_label ( button * C . GtkWidget ) string {
2014-04-26 21:55:43 -05:00
return fromgstr ( C . gtk_button_get_label ( togtkbutton ( button ) ) )
2014-02-16 17:57:50 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_check_button_new ( ) * C . GtkWidget {
return C . gtk_check_button_new ( )
2014-02-16 17:41:29 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_toggle_button_get_active ( widget * C . GtkWidget ) bool {
2014-02-17 14:45:26 -06:00
return fromgbool ( C . gtk_toggle_button_get_active ( togtktogglebutton ( widget ) ) )
2014-02-16 17:41:29 -06:00
}
2014-02-16 18:50:52 -06:00
2014-04-01 15:30:38 -05:00
func gtk_combo_box_text_new ( ) * C . GtkWidget {
return C . gtk_combo_box_text_new ( )
2014-02-16 18:50:52 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_combo_box_text_new_with_entry ( ) * C . GtkWidget {
return C . gtk_combo_box_text_new_with_entry ( )
2014-02-16 18:50:52 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_combo_box_text_get_active_text ( widget * C . GtkWidget ) string {
2014-04-26 21:55:43 -05:00
return fromgstr ( C . gtk_combo_box_text_get_active_text ( togtkcombobox ( widget ) ) )
2014-02-16 18:50:52 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_combo_box_text_append_text ( widget * C . GtkWidget , text string ) {
2014-02-16 18:50:52 -06:00
ctext := C . CString ( text )
defer C . free ( unsafe . Pointer ( ctext ) )
2014-04-26 21:55:43 -05:00
C . gtk_combo_box_text_append_text ( togtkcombobox ( widget ) , togstr ( ctext ) )
2014-02-16 18:50:52 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_combo_box_text_insert_text ( widget * C . GtkWidget , index int , text string ) {
2014-02-16 18:50:52 -06:00
ctext := C . CString ( text )
defer C . free ( unsafe . Pointer ( ctext ) )
2014-04-26 21:55:43 -05:00
C . gtk_combo_box_text_insert_text ( togtkcombobox ( widget ) , C . gint ( index ) , togstr ( ctext ) )
2014-02-16 18:50:52 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_combo_box_get_active ( widget * C . GtkWidget ) int {
2014-02-17 14:45:26 -06:00
cb := ( * C . GtkComboBox ) ( unsafe . Pointer ( widget ) )
return int ( C . gtk_combo_box_get_active ( cb ) )
2014-02-16 18:50:52 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_combo_box_text_remove ( widget * C . GtkWidget , index int ) {
2014-02-17 14:45:26 -06:00
C . gtk_combo_box_text_remove ( togtkcombobox ( widget ) , C . gint ( index ) )
2014-02-16 18:50:52 -06:00
}
2014-02-16 20:40:59 -06:00
2014-04-01 15:30:38 -05:00
func gtkComboBoxLen ( widget * C . GtkWidget ) int {
2014-03-08 15:42:57 -06:00
cb := ( * C . GtkComboBox ) ( unsafe . Pointer ( widget ) )
model := C . gtk_combo_box_get_model ( cb )
// this is the same as with a Listbox so
return gtkTreeModelListLen ( model )
}
2014-04-01 15:30:38 -05:00
func gtk_entry_new ( ) * C . GtkWidget {
return C . gtk_entry_new ( )
2014-02-16 20:40:59 -06:00
}
2014-04-01 15:30:38 -05:00
func gtkPasswordEntryNew ( ) * C . GtkWidget {
2014-02-25 14:06:51 -06:00
e := gtk_entry_new ( )
C . gtk_entry_set_visibility ( togtkentry ( e ) , C . FALSE )
return e
}
2014-04-01 15:30:38 -05:00
func gtk_entry_set_text ( widget * C . GtkWidget , text string ) {
2014-02-16 20:40:59 -06:00
ctext := C . CString ( text )
defer C . free ( unsafe . Pointer ( ctext ) )
2014-04-26 21:55:43 -05:00
C . gtk_entry_set_text ( togtkentry ( widget ) , togstr ( ctext ) )
2014-02-16 20:40:59 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_entry_get_text ( widget * C . GtkWidget ) string {
2014-04-26 21:55:43 -05:00
return fromgstr ( C . gtk_entry_get_text ( togtkentry ( widget ) ) )
2014-02-16 20:40:59 -06:00
}
2014-02-16 21:03:14 -06:00
var _emptystring = [ 1 ] C . gchar { 0 }
var emptystring = & _emptystring [ 0 ]
2014-04-01 15:30:38 -05:00
func gtk_label_new ( ) * C . GtkWidget {
2014-04-13 17:05:07 -05:00
label := C . gtk_label_new ( emptystring )
C . gtk_label_set_line_wrap ( togtklabel ( label ) , C . FALSE )
// TODO explicitly set line wrap mode as well?
// TODO explicitly disable ellipsizing
return label
2014-02-16 21:03:14 -06:00
// TODO left-justify?
}
2014-04-01 15:30:38 -05:00
func gtk_label_set_text ( widget * C . GtkWidget , text string ) {
2014-02-16 21:03:14 -06:00
ctext := C . CString ( text )
defer C . free ( unsafe . Pointer ( ctext ) )
2014-04-26 21:55:43 -05:00
C . gtk_label_set_text ( togtklabel ( widget ) , togstr ( ctext ) )
2014-02-16 21:03:14 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_label_get_text ( widget * C . GtkWidget ) string {
2014-04-26 21:55:43 -05:00
return fromgstr ( C . gtk_label_get_text ( togtklabel ( widget ) ) )
2014-02-16 21:03:14 -06:00
}
2014-02-23 19:04:33 -06:00
2014-04-01 15:30:38 -05:00
func gtk_widget_get_preferred_size ( widget * C . GtkWidget ) ( minWidth int , minHeight int , natWidth int , natHeight int ) {
2014-02-23 19:04:33 -06:00
var minimum , natural C . GtkRequisition
2014-04-01 15:30:38 -05:00
C . gtk_widget_get_preferred_size ( widget , & minimum , & natural )
2014-02-23 19:04:33 -06:00
return int ( minimum . width ) , int ( minimum . height ) ,
int ( natural . width ) , int ( natural . height )
}
2014-02-24 23:48:23 -06:00
2014-04-01 15:30:38 -05:00
func gtk_progress_bar_new ( ) * C . GtkWidget {
return C . gtk_progress_bar_new ( )
2014-02-24 23:48:23 -06:00
}
2014-04-01 15:30:38 -05:00
func gtk_progress_bar_set_fraction ( w * C . GtkWidget , percent int ) {
2014-02-24 23:48:23 -06:00
p := C . gdouble ( percent ) / 100
C . gtk_progress_bar_set_fraction ( togtkprogressbar ( w ) , p )
}
2014-03-12 16:31:13 -05:00
2014-04-01 15:30:38 -05:00
func gtk_progress_bar_pulse ( w * C . GtkWidget ) {
2014-03-12 16:31:13 -05:00
C . gtk_progress_bar_pulse ( togtkprogressbar ( w ) )
}