GTK+/Kalkulator

Z Wikibooks, biblioteki wolnych podręczników.

Ten przykład pokazuje jak użyć biblioteki GTK+ w w miarę funkcjonalnym programie, który realizuje jakieś zadania, niekoniecznie przydatne tylko w edukacji (np. obliczanie delty). Program będzie rozwijany w kolejnych rozdziałach, wykorzystując możliwości biblioteki GTK+.



Kalkulator posiada podstawowe funkcje, dodawanie, odejmowanie, mnożenie, dzielenie. Wspiera intuicyjną obsługę, tzn. posiada ograniczenia zabezpieczające przed użyciem funkcji, których nie można użyć w danym momencie. Przyciski działań (jakie obsługuje kalkulator) w zależności od sytuacji przejmują zadania przycisku sumującego (=). Pozwala to na dodawanie, mnożenie itd. szeregu liczb bez używania przycisku sumy (=) z jednoczesnym wyświetlaniem wyniku.
Założenia te, oraz kilka innych, nieco skomplikowały sam program. Wciąż jednak jest to tylko obsługa (niepełna, rzeczy do zrobienia zostały wymienione w TODO:) minimalnych funkcji jakie powinien realizować prawdziwy kalkulator. Z czasem program zostanie rozbudowany, na razie jego rozwój został zatrzymany, ponieważ kod obsługi samych mechanizmów zaczął za bardzo przesłaniać samo użycie biblioteki GTK+. Niemniej jednak rozbudowany program uczy więcej.

Oto krótka charakterystyka założeń dotyczących kodu:

  • Program składa się z dwóch plików: kalkulator.c oraz kalkulator.h. Można podzielić pierwszy z nich tak, aby funkcje zwrotne GTK+ tzw. callback oraz funkcje niezwiązane z interfejsem graficznym zostały przeniesione do innych plików, np. callback.c oraz corefunction.c. Nie wprowadzono tego, ze względu na łatwiejsze analizowanie kodu z jednego pliku.
  • Niektóre funkcje np. obsługi cyfr oraz działań zawierają taki sam kod obsługi zdarzenia, możliwe jest skrócenie kodu poprzez napisanie uogólnionych funkcji (ze względu analizy kodu zostanie to wprowadzone w następnych wersjach programu)
  • Program został wyposażony w strukturę dane organizującą niezbędne działanie kalkulatora oraz ich wymianą między wieloma funkcjami zwrotnymi.
  • Program został uzbrojony w funkcje debugującą oraz w dyrektywy do ich aktywowania. Stało się to konieczne podczas pewnego poziomu rozwoju programu. Możesz jej użyć do podglądania jakie zmiany zachodzą we wewnętrznej strukturze danych.
  • Program został napisany wyłącznie do celów edukacyjnych (oraz dla zabawy), więc wiele rozwiązań w nim zawartych może nie być optymalnymi (np. konwersja napisów na liczby i vice versa). Wszelkie uwagi, błędy oraz propozycje proszę kierować na mój adres e-mail dostępny w (Gk180984).

Kod programu[edytuj]

Analiza kodu znajduję się w następnym temacie tego rozdziału.

kalkulator.h

struct _Kalkulator {
	
      // pamięć zarządzana przez GTK+
	GtkWidget 	*window;
	GtkWidget 	*table;
	GtkWidget 	*entry;

	// pamiec zarządzana przez nas
	GString		*value1;
	GString		*value2;
	
	// numer operacji - działania
	// 1 + 
	// 2 -
	// 3 * 
	// 4 /
	gshort		 operation;
	// stan kalkulatora
	gboolean 	 is_value1;
	gboolean 	 is_value2;
	gboolean	 is_result;
	// ostatnio wciśnięty przycisk
	// 1  1
	// 2  2
	// ...
	// 9  9
	// 0  0
	// 10 +
	// 11 -
	// 12 *
	// 13 /
	// 14 =
	// 15 ,
	// 16 <-
	// 17 C
	gint8        prev_button;
};

typedef struct _Kalkulator Kalkulator;


kalkulator.c

/* 
 * Autor: Grzegorz Kuczyński 
 * Data:  6 kwietnia 2009
 * kompilacja: gcc -Wall -g  kalkulator.c -o kalkulator `pkg-config --cflags --libs gtk+-2.0`
 *
 * TODO
 *  - sposób wyświetlania wyniku
 *  - obsługa przecinka (spr błędów)
 *  - reakcja na backspace - obcinanie końcówki liczby (przycisk <-)
 *  - sterowanie za pomocą klawiatury numerycznej
 *  - komunikat dot. dzielenia przez 0
 */

#include <gtk/gtk.h>
#include "kalkulator.h"
#include <stdlib.h>
#include <string.h>

//#define DEBUG


// funkcja debugująca
void info (Kalkulator * pkalkulator, gchar* event)
{
	Kalkulator *kalkulator = pkalkulator;

	printf ("\n =============\n %s\n - - - - -\nStruktura:\n \
		value1: %s \n \
		value2: %s \n \
		is_value1: %d \n \
		is_operatn2: %d \n \
		is_result: %d \n \
		prev_button: %d \n - - - - -\n",
		event,
		kalkulator->is_value1 == TRUE? kalkulator->value1->str :"",
		kalkulator->is_value2 == TRUE? kalkulator->value2->str :"",
		kalkulator->is_value1,
		kalkulator->is_value2,
		kalkulator->is_result,
		kalkulator->prev_button);

}

// funkcja odpowiadająca za właściwe wykonywanie obliczeń na 2 wartościach
void licz(Kalkulator *kalkulator)
{
	double  d_value1, d_value2, result;
	char    s_result[50];

	d_value1 = strtod( (char*)g_string_free (kalkulator->value1, FALSE),
						NULL );
	d_value2 = strtod( (char*)g_string_free (kalkulator->value2, FALSE), 
						NULL );
	#ifdef DEBUG
	printf ("liczby to %f , %f \n",d_value1,d_value2);
	#endif

	switch (kalkulator->operation)
	{
	case 1:
		result = d_value1 + d_value2;
		break;
	case 2:
		result = d_value1 - d_value2;
		break;
	case 3:
		result = d_value1 * d_value2;
		break;
	case 4:
		if ( d_value2 >= 1 )
			result = d_value1 / d_value2;
		else
			result = d_value1;
		break;
	}
	sprintf (s_result,"%f",result);
	kalkulator->value1 = g_string_new (s_result);
	/*
	kalkulator->value1 (wynik)
	kalkulator->value2 (puste)
	*/
}

//==========================================
// obsługa zdarzeń przycisków numerycznych
static void btn_1_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 1\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}
	
	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"1");
	kalkulator->prev_button = 1;
}

static void btn_2_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 2\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}
	
	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"2");
	kalkulator->prev_button = 2;
}

static void btn_3_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 3\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}
	
	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"3");
	kalkulator->prev_button = 3;
}

static void btn_4_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 4\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}
	
	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"4");
	kalkulator->prev_button = 4;
}

static void btn_5_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 5\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}

	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"5");
	kalkulator->prev_button = 5;
}

static void btn_6_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 6\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}
	
	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"6");
	kalkulator->prev_button = 6;
}

static void btn_7_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 7\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}
	
	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"7");
	kalkulator->prev_button = 7;
}

static void btn_8_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 8\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}
	
	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"8");
	kalkulator->prev_button = 8;
}

static void btn_9_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 9\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}
	
	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"9");
	kalkulator->prev_button = 9;
}

static void btn_0_clicked( GtkWidget *widget,
			   gpointer   pkalkulator )
{
	g_print ("clicked: 0\n");
	Kalkulator *kalkulator = pkalkulator;
	
	if ( kalkulator->is_result )
	{
		gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
		kalkulator->is_result = FALSE;
	}

	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),"0");
	kalkulator->prev_button = 0;
}

// obsługa zdarzeń przycisków funkcyjnych
static void btn_comma_clicked( GtkWidget *widget,
	  		       gpointer   pkalkulator )
{
	g_print ("clicked: ,\n");
	Kalkulator *kalkulator = pkalkulator;
	gtk_entry_append_text ( GTK_ENTRY(kalkulator->entry),",");
	kalkulator->prev_button = 15;
}

static void btn_back_clicked( GtkWidget *widget,
			      gpointer   pkalkulator )
{
	g_print ("clicked: <-\n");
	Kalkulator *kalkulator = pkalkulator;
	GString *tmp=NULL;
	
	tmp = g_string_new (
			gtk_entry_get_text (GTK_ENTRY(kalkulator->entry)));
	tmp = g_string_truncate ( tmp, tmp->len - 1 );
	gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ), 
			     g_string_free( tmp, FALSE ) );
	kalkulator->prev_button = 16;
}

static void btn_clear_clicked( GtkWidget *widget,
			       gpointer   pkalkulator )
{
	g_print ("clicked: C\n");
	Kalkulator *kalkulator = pkalkulator;
	
	kalkulator->operation = 0;

	if (kalkulator->is_value1 == TRUE)
	{
		g_string_free (kalkulator->value1,TRUE); 
		kalkulator->value1 = g_string_new (NULL); 
	}
	if (kalkulator->is_value2 == TRUE)
	{
		g_string_free (kalkulator->value2,TRUE); 
		kalkulator->value2 = g_string_new (NULL); 
	}
	
	kalkulator->is_value1 = FALSE;
	kalkulator->is_value2 = FALSE;
	kalkulator->is_result   = FALSE;
	
	gtk_entry_set_text ( GTK_ENTRY(kalkulator->entry),"");

	#ifdef DEBUG
	info(kalkulator,"clear");
	#endif
	kalkulator->prev_button = 17;
}

// opsługa zdarzeń przycisków działań
static void btn_add_clicked( GtkWidget *widget,
			     gpointer   pkalkulator )
{
	g_print ("clicked: +\n");
	Kalkulator *kalkulator = pkalkulator;
	gint8 test = 0;
	gchar * text_entry = GTK_ENTRY(kalkulator->entry)->text;
	
	// +
	kalkulator->operation = 1;
	#ifdef DEBUG
	info(kalkulator,"w funkcji +");
	#endif

	// test
	if ( kalkulator->is_value1 == FALSE && 
	     kalkulator->is_value2 == FALSE &&
	     strlen (text_entry) > 0 )
	{
		// nalezy ustawić value1
		test = 1;
	}
	if ( kalkulator->is_value1 == TRUE && 
	     kalkulator->is_value2 == FALSE &&
	     strlen (text_entry) > 0 &&
	     kalkulator->prev_button != 10 && // +
	     kalkulator->prev_button != 11 && // -
	     kalkulator->prev_button != 12 && // *
	     kalkulator->prev_button != 13 && // /
	     kalkulator->prev_button != 14 && // =
	     kalkulator->prev_button != 15  ) // ,
	{
		// ustawic value2 i obliczyć wynik
		test = 2;
	}

	switch (test)
	{
		case 1:
			kalkulator->value1 = g_string_new ( 
					gtk_entry_get_text(GTK_ENTRY(kalkulator->entry)));
			kalkulator->is_value1 = TRUE;
			gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
			break;

		case 2:
			kalkulator->value2 = g_string_new (
					gtk_entry_get_text(GTK_ENTRY(kalkulator->entry)));
   		 	kalkulator->is_value2 = TRUE;
			licz (kalkulator);
			gtk_entry_set_text (GTK_ENTRY (kalkulator->entry),
				 	    (gchar*)kalkulator->value1->str);
			kalkulator->is_value1 = TRUE;
			kalkulator->is_value2 = FALSE;
			kalkulator->is_result = TRUE;
			break;
	}

	#ifdef DEBUG
	info(kalkulator,"koniec funkcji +");	
	#endif
	kalkulator->prev_button = 10;
}

static void btn_sub_clicked( GtkWidget *widget,
			     gpointer   pkalkulator )
{
	g_print ("clicked: -\n");
	Kalkulator *kalkulator = pkalkulator;
	gint8 test = 0;
	gchar * text_entry = GTK_ENTRY(kalkulator->entry)->text;
	
	// -
	kalkulator->operation = 2;
	#ifdef DEBUG
	info(kalkulator,"w funkcji -");
	#endif

	// test
	if ( kalkulator->is_value1 == FALSE && 
	     kalkulator->is_value2 == FALSE &&
	     strlen (text_entry) > 0 )
	{
		// nalezy ustawić value1
		test = 1;
	}
	if ( kalkulator->is_value1 == TRUE && 
	     kalkulator->is_value2 == FALSE &&
	     strlen (text_entry) > 0 &&
	     kalkulator->prev_button != 10 &&
	     kalkulator->prev_button != 11 &&
	     kalkulator->prev_button != 12 &&
	     kalkulator->prev_button != 13 &&
	     kalkulator->prev_button != 14 &&
	     kalkulator->prev_button != 15  ) 
	{
		// ustawic value2 i obliczyć wynik
		test = 2;
	}

	switch (test)
	{
		case 1:
			kalkulator->value1 = g_string_new (
					gtk_entry_get_text (GTK_ENTRY(kalkulator->entry)));
			kalkulator->is_value1 = TRUE;
			gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
			break;

		case 2:
			kalkulator->value2 = g_string_new (
					gtk_entry_get_text (GTK_ENTRY(kalkulator->entry)));
			kalkulator->is_value2 = TRUE;
			licz (kalkulator);
			gtk_entry_set_text (GTK_ENTRY (kalkulator->entry),
					    (gchar*)kalkulator->value1->str);
			kalkulator->is_value1 = TRUE;
			kalkulator->is_value2 = FALSE;
			kalkulator->is_result = TRUE;
			break;
	}

	#ifdef DEBUG
	info(kalkulator,"koniec funkcji -");	
	#endif
	kalkulator->prev_button = 11;
}

static void btn_multi_clicked( GtkWidget *widget,
			       gpointer   pkalkulator )
{
	g_print ("clicked: *\n");
	Kalkulator *kalkulator = pkalkulator;
	gint8 test = 0;
	gchar * text_entry = GTK_ENTRY(kalkulator->entry)->text;
	
	// *
	kalkulator->operation = 3;
	#ifdef DEBUG
	info(kalkulator,"w funkcji *");
	#endif

	// test
	if ( kalkulator->is_value1 == FALSE && 
	     kalkulator->is_value2 == FALSE &&
	     strlen (text_entry) > 0 )
	{
		// nalezy ustawić value1
		test = 1;
	}
	if ( kalkulator->is_value1 == TRUE && 
	     kalkulator->is_value2 == FALSE &&
	     strlen (text_entry) > 0 &&
	     kalkulator->prev_button != 10 &&
	     kalkulator->prev_button != 11 &&
	     kalkulator->prev_button != 12 &&
	     kalkulator->prev_button != 13 &&
	     kalkulator->prev_button != 14 &&
	     kalkulator->prev_button != 15  ) 
	{
		// ustawic value2 i obliczyć wynik
		test = 2;
	}

	switch (test)
	{
		case 1:
			kalkulator->value1 = g_string_new (
					gtk_entry_get_text (GTK_ENTRY(kalkulator->entry)));
			kalkulator->is_value1 = TRUE;
			gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
			break;

		case 2:
			kalkulator->value2 = g_string_new (
					gtk_entry_get_text(GTK_ENTRY(kalkulator->entry)));
			kalkulator->is_value2 = TRUE;
			licz (kalkulator);
			gtk_entry_set_text (GTK_ENTRY (kalkulator->entry),
					    (gchar*)kalkulator->value1->str);
			kalkulator->is_value1 = TRUE;
			kalkulator->is_value2 = FALSE;
			kalkulator->is_result = TRUE;
			break;
	}

	#ifdef DEBUG
	info(kalkulator,"koniec funkcji *");	
	#endif
	kalkulator->prev_button = 12;
}

static void btn_div_clicked( GtkWidget *widget,
			     gpointer   pkalkulator )
{
	g_print ("clicked: /\n");
	Kalkulator *kalkulator = pkalkulator;
	gint8 test = 0;
	gchar * text_entry = GTK_ENTRY(kalkulator->entry)->text;
	
	// /
	kalkulator->operation = 4;
	#ifdef DEBUG
	info(kalkulator,"w funkcji /");
	#endif

	// test
	if ( kalkulator->is_value1 == FALSE && 
	     kalkulator->is_value2 == FALSE &&
	     strlen (text_entry) > 0 )
	{
		// nalezy ustawić value1
		test = 1;
	}
	if ( kalkulator->is_value1 == TRUE && 
	     kalkulator->is_value2 == FALSE &&
	     strlen (text_entry) > 0 &&
	     kalkulator->prev_button != 10 &&
	     kalkulator->prev_button != 11 &&
	     kalkulator->prev_button != 12 &&
	     kalkulator->prev_button != 13 &&
	     kalkulator->prev_button != 14 &&
	     kalkulator->prev_button != 15  ) 
	{
		// ustawic value2 i obliczyć wynik
		test = 2;
	}

	switch (test)
	{
		case 1:
			kalkulator->value1 = g_string_new (
					gtk_entry_get_text(GTK_ENTRY(kalkulator->entry)));
			kalkulator->is_value1 = TRUE;
			gtk_entry_set_text ( GTK_ENTRY( kalkulator->entry ),"");
			break;

		case 2:
			kalkulator->value2 = g_string_new (
					gtk_entry_get_text (GTK_ENTRY(kalkulator->entry)));
			kalkulator->is_value2 = TRUE;
			licz (kalkulator);
			gtk_entry_set_text (GTK_ENTRY (kalkulator->entry),
					    (gchar*)kalkulator->value1->str);
			kalkulator->is_value1 = TRUE;
			kalkulator->is_value2 = FALSE;
			kalkulator->is_result = TRUE;
			break;
	}

	#ifdef DEBUG
	info(kalkulator,"koniec funkcji /");	
	#endif
	kalkulator->prev_button = 13;
}

static void btn_result_clicked( GtkWidget *widget,
				gpointer   pkalkulator )
{
	g_print ("clicked: =\n");
	Kalkulator *kalkulator = pkalkulator;
	// zamiast:    ((Kalkulator*)pkalkulator)->operation 

	gchar * text_entry = GTK_ENTRY(kalkulator->entry)->text;
	
	#ifdef DEBUG
	info(kalkulator,"w funkcji =");
	#endif

	if ( kalkulator->is_value1 == TRUE && 
	     kalkulator->is_value2 == FALSE &&
	     strlen (text_entry) > 0 &&
	     kalkulator->prev_button != 10 &&
	     kalkulator->prev_button != 11 &&
	     kalkulator->prev_button != 12 &&
	     kalkulator->prev_button != 13 &&
	     kalkulator->prev_button != 14 &&
	     kalkulator->prev_button != 15  ) 
	{
		kalkulator->value2 = g_string_new (
				     gtk_entry_get_text (GTK_ENTRY(kalkulator->entry))
                                                 );
		kalkulator->is_value2 = TRUE;
		licz (kalkulator);
		gtk_entry_set_text (GTK_ENTRY (kalkulator->entry),
				    (gchar*)kalkulator->value1->str);
		kalkulator->is_value1 = TRUE;
		kalkulator->is_value2 = FALSE;
		kalkulator->is_result = TRUE;
	}
	
	#ifdef DEBUG
	info(kalkulator,"koniec funkcji =");	
	#endif
	kalkulator->prev_button = 14;
}

// obsługa zdarzeń emitowanych podczas zamykania programu
static gboolean delete_event( GtkWidget *widget,
			      GdkEvent  *event,
			      gpointer   data )
{
	g_print("delete_event: FALSE\n");
	return FALSE;
}
 
static void destroy( GtkWidget *widget,
		     gpointer  pkalkulator )
{
	g_print("destroy: gtk_main_quit | g_free\n");
	Kalkulator *kalkulator = pkalkulator;
	
	gtk_main_quit ();
	
	if (kalkulator->is_value1 == TRUE)
	{
		g_string_free (kalkulator->value1,TRUE); 
	}
	if (kalkulator->is_value2 == TRUE)
	{
		g_string_free (kalkulator->value2,TRUE); 
	}
	g_free ( kalkulator );
}

int main( int argc, char *argv[] )
{
	Kalkulator *kalkulator;
	kalkulator = g_malloc ( sizeof( Kalkulator ) );
	kalkulator->operation = -1;
	kalkulator->is_value1 = FALSE;
	kalkulator->is_value2 = FALSE;
	kalkulator->is_result = FALSE;
	GtkWidget *tmp;
 
	gtk_init (&argc, &argv);
	// okno i jego podstawowe właściwości 
	kalkulator->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
	g_signal_connect (G_OBJECT (kalkulator->window), "delete_event",
			  G_CALLBACK (delete_event), NULL);
 
	g_signal_connect (G_OBJECT (kalkulator->window), "destroy",
			  G_CALLBACK (destroy), kalkulator);
 
	gtk_container_set_border_width (GTK_CONTAINER (kalkulator->window), 5);
	gtk_window_set_title (GTK_WINDOW (kalkulator->window), "kalkulator");
	gtk_window_set_resizable ( GTK_WINDOW (kalkulator->window), FALSE );

	// tabela
	/*
 	     0/0 - 1 - 2 - 3 - 4 - 5 - 6
 	     1 | _ | _ | _ | _ | _ | _ |
 	     2 | _ | _ | _ | _ | _ | _ |
 	     3 | _ | _ | _ | _ | _ | _ |
 	     4 | _ | _ | _ | _ | _ | _ |
 	*/
	kalkulator->table = gtk_table_new (4, 6, TRUE);
	gtk_container_add ( GTK_CONTAINER (kalkulator->window),
			    kalkulator->table);

	// entry
	kalkulator->entry = gtk_entry_new ( );
	gtk_entry_set_alignment ( GTK_ENTRY( kalkulator->entry ), 1);
	gtk_entry_set_editable ( GTK_ENTRY( kalkulator->entry ), FALSE);
	// 0,6 - szerokość od 0 do 6
	// 0,1 - wysokość od 0 do 1
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    kalkulator->entry, 0, 6, 0, 1 );
	
	// przyciski 1
	// 0,1 - szerokość od 0 do 1
	// 1,2 - wysokość od 1 do 2
	tmp = gtk_button_new_with_label ("1");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_1_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 0, 1, 1, 2);
	
	// przyciski 2
	tmp = gtk_button_new_with_label ("2");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		   	  G_CALLBACK (btn_2_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 1, 2, 1, 2);
	
	// przyciski 3
	tmp = gtk_button_new_with_label ("3");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		 	  G_CALLBACK (btn_3_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 2, 3, 1, 2);
	
	// drugi wiersz
	// przyciski 4
	tmp = gtk_button_new_with_label ("4");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_4_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 0, 1, 2, 3);
	
	// przyciski 5
	tmp = gtk_button_new_with_label ("5");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_5_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 1, 2, 2, 3);
	
	// przyciski 6
	tmp = gtk_button_new_with_label ("6");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_6_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 2, 3, 2, 3);
	
	// trzeci wiersz
	// przyciski 7
	tmp = gtk_button_new_with_label ("7");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_7_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 0, 1, 3, 4);
	
	// przyciski 8
	tmp = gtk_button_new_with_label ("8");
	g_signal_connect (G_OBJECT (tmp), "clicked",
			  G_CALLBACK (btn_8_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 1, 2, 3, 4);
	
	// przyciski 9
	tmp = gtk_button_new_with_label ("9");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_9_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 2, 3, 3, 4);
	
	// przyciski 0
	tmp = gtk_button_new_with_label ("0");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_0_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 3, 4, 3, 4);
	
	// przyciski <-
	tmp = gtk_button_new_with_label ("<-");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_back_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 3, 4, 2, 3);
	
	// przyciski C
	tmp = gtk_button_new_with_label ("C");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_clear_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 3, 4, 1, 2);
	
	// przyciski +
	tmp = gtk_button_new_with_label ("+");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_add_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 4, 5, 1, 2);
	
	// przyciski -
	tmp = gtk_button_new_with_label ("-");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_sub_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 4, 5, 2, 3);
	
	// przyciski *
	tmp = gtk_button_new_with_label ("*");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_multi_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 4, 5, 3, 4);
	
	// przyciski /
	tmp = gtk_button_new_with_label ("/");
	g_signal_connect (G_OBJECT (tmp), "clicked",
		          G_CALLBACK (btn_div_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 5, 6, 1, 2);
	 
	// przyciski =
	tmp = gtk_button_new_with_label ("=");
	g_signal_connect (G_OBJECT (tmp), "clicked",
			  G_CALLBACK (btn_result_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 5, 6, 3, 4);
	
        // przyciski ,
	tmp = gtk_button_new_with_label (",");
	g_signal_connect (G_OBJECT (tmp), "clicked",
			  G_CALLBACK (btn_comma_clicked), kalkulator);
	gtk_table_attach_defaults ( GTK_TABLE (kalkulator->table),
				    tmp, 5, 6, 2, 3);

	gtk_widget_show_all (kalkulator->window);
	
	#ifdef DEBUG
	info(kalkulator,"przed gatk_main");
	#endif
	gtk_main ();

	return 0;
}