GTK+/Kalkulator 0.0.1 - gui.cpp

Z Wikibooks, biblioteki wolnych podręczników.
#include "gui.hpp"
#include <string.h>
#include <gdk/gdkkeysyms.h>

//#define DEBUG
//#define INFO


GUIKalkulator::GUIKalkulator()
{
  #ifdef INFO 
  __debug("GUIKalkulator konstruktor",false);
  #endif
  combocount = 0;
}

GUIKalkulator::~GUIKalkulator()
{
  #ifdef INFO 
  __debug("GUIKalkulator destruktor",false);
  #endif
}

void GUIKalkulator::init(int argc, char** argv)
{
  #ifdef INFO 
  __debug("GUIKalkulator init()",false);
  #endif
  gtk_init(&argc, &argv);
}

void GUIKalkulator::build()
{
  #ifdef INFO 
  __debug("GUIKalkulator bulid()",false);
  #endif
  mainwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
  g_signal_connect(G_OBJECT(mainwindow),"delete_event",G_CALLBACK(delete_event),this);
  g_signal_connect(G_OBJECT(mainwindow),"destroy",G_CALLBACK(destroy),this);
  gtk_widget_set_events (mainwindow, GDK_KEY_PRESS_MASK);
  g_signal_connect (G_OBJECT (mainwindow),"key_press_event",G_CALLBACK(mainwindow_key_press_event),this);
 
  gtk_window_set_title(GTK_WINDOW(mainwindow),"Kalkulator");
  gtk_window_set_resizable(GTK_WINDOW(mainwindow),FALSE);
  
  // tabela
  /*
        0/0 - 1 - 2 - 3 - 4 - 5 - 6
        1 | _ | _ | _ | _ | _ | _ |
        2 | _ | _ | _ | _ | _ | _ |
        3 | _ | _ | _ | _ | _ | _ |
        4 | _ | _ | _ | _ | _ | _ |
        5 | _ | _ | _ | _ | _ | _ | Add
   */
  table = gtk_table_new(5,6,TRUE);
  gtk_container_set_border_width(GTK_CONTAINER(table),5);
  //gtk_container_add(GTK_CONTAINER(mainwindow),table);

  // entry
  entry = gtk_entry_new();
  gtk_entry_set_alignment(GTK_ENTRY(entry),1);
  GdkColor entry_color; // kolor
  gdk_color_parse("#eaf8d9",&entry_color);
  gtk_widget_modify_base(entry,GTK_STATE_NORMAL,&entry_color);
  // 0,6 - szerokość od 0 do 6
  // 0,1 - wysokość od 0 do 1
  gtk_table_attach_defaults(GTK_TABLE(table),entry,0,6,0,1);
  gtk_widget_set_size_request(entry,-1,30);
  //czcionka
  pangofont = pango_font_description_new();
  pango_font_description_set_size(pangofont,17 * PANGO_SCALE );
  pango_font_description_set_weight(pangofont,PANGO_WEIGHT_BOLD);
  gtk_widget_modify_font(entry,pangofont);
  pango_font_description_free(pangofont);
  //bez zaznaczania
  gtk_editable_set_editable(GTK_EDITABLE(entry),false);
  
  // przyciski 1
  // 0,1 - szerokość od 0 do 1
  // 1,2 - wysokość od 1 do 2
  button1 = gtk_button_new_with_label("1");
  g_signal_connect(G_OBJECT(button1),"clicked",G_CALLBACK(btn_1_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button1,0,1,1,2);
  
  // przyciski 2
  button2 = gtk_button_new_with_label("2");
  g_signal_connect(G_OBJECT(button2),"clicked",G_CALLBACK(btn_2_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button2,1,2,1,2);
  
  // przyciski 3
  button3 = gtk_button_new_with_label("3");
  g_signal_connect(G_OBJECT(button3),"clicked",G_CALLBACK(btn_3_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button3,2,3,1,2);
  
  // drugi wiersz
  // przyciski 4
  button4 = gtk_button_new_with_label("4");
  g_signal_connect(G_OBJECT(button4),"clicked",G_CALLBACK(btn_4_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button4,0,1,2,3);
  
  // przyciski 5
  button5 = gtk_button_new_with_label("5");
  g_signal_connect(G_OBJECT(button5),"clicked",G_CALLBACK(btn_5_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button5,1,2,2,3);
  
  // przyciski 6
  button6 = gtk_button_new_with_label("6");
  g_signal_connect(G_OBJECT(button6),"clicked",G_CALLBACK(btn_6_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button6,2,3,2,3);
  
  // trzeci wiersz
  // przyciski 7
  button7 = gtk_button_new_with_label("7");
  g_signal_connect(G_OBJECT(button7),"clicked",G_CALLBACK(btn_7_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button7,0,1,3,4);
  
  // przyciski 8
  button8 = gtk_button_new_with_label("8");
  g_signal_connect(G_OBJECT(button8),"clicked",G_CALLBACK(btn_8_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button8,1,2,3,4);
  
  // przyciski 9
  button9 = gtk_button_new_with_label("9");
  g_signal_connect(G_OBJECT(button9),"clicked",G_CALLBACK(btn_9_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button9,2,3,3,4);
  
  // przyciski 0
  button0 = gtk_button_new_with_label("0");
  g_signal_connect(G_OBJECT(button0),"clicked",G_CALLBACK(btn_0_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),button0,3,4,3,4);
  
  // przyciski <-
  buttonback = gtk_button_new_with_label("<-");
  g_signal_connect(G_OBJECT(buttonback),"clicked",G_CALLBACK(btn_back_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttonback,3,4,2,3);
  
  // przyciski AC
  buttonclear = gtk_button_new_with_label("AC");
  g_signal_connect(G_OBJECT(buttonclear),"clicked",G_CALLBACK(btn_clear_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttonclear,3,4,1,2);
  
  // przyciski +
  buttonadd = gtk_button_new_with_label("+");
  g_signal_connect(G_OBJECT(buttonadd),"clicked",G_CALLBACK(btn_add_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttonadd,4,5,1,2);
  
  // przyciski -
  buttonsub = gtk_button_new_with_label("-");
  g_signal_connect(G_OBJECT(buttonsub),"clicked",G_CALLBACK(btn_sub_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttonsub,4,5,2,3);
  
  // przyciski *
  buttonmulti = gtk_button_new_with_label("*");
  g_signal_connect(G_OBJECT(buttonmulti),"clicked",G_CALLBACK(btn_multi_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttonmulti,4,5,3,4);
  
  // przyciski /
  buttondiv = gtk_button_new_with_label("/");
  g_signal_connect(G_OBJECT(buttondiv),"clicked",G_CALLBACK(btn_div_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttondiv,5,6,1,2);
   
  // przyciski =
  buttonresult = gtk_button_new_with_label("=");
  g_signal_connect(G_OBJECT(buttonresult),"clicked",G_CALLBACK(btn_result_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttonresult,5,6,3,4);

  // przyciski ,
  buttoncomma = gtk_button_new_with_label(",");
  g_signal_connect(G_OBJECT(buttoncomma),"clicked",G_CALLBACK(btn_comma_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttoncomma,5,6,2,3);
  
  // przyciski -/+
  buttonsigned = gtk_button_new_with_label("-/+");
  g_signal_connect(G_OBJECT(buttonsigned),"clicked",G_CALLBACK(btn_signed_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttonsigned,0,1,4,5);
 
  // przyciski M+
  buttonaddmem = gtk_button_new_with_label("M+");
  g_signal_connect(G_OBJECT(buttonaddmem),"clicked",G_CALLBACK(btn_addmem_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttonaddmem,1,2,4,5);
  
  // lista z zapamietanymi liczbami
  comboreadmem = gtk_combo_box_new_text();
  gtk_table_attach_defaults(GTK_TABLE(table),comboreadmem,2,5,4,5);
  gtk_combo_box_append_text(GTK_COMBO_BOX(comboreadmem),"Czytaj z pamięci");
  combocount++;
  gtk_combo_box_set_active(GTK_COMBO_BOX(comboreadmem),0);
  g_signal_connect(G_OBJECT(comboreadmem),"changed",G_CALLBACK(btn_readmem_clicked),this);
  gtk_widget_set_sensitive(comboreadmem,FALSE);
  atk_object_set_name(
        gtk_widget_get_accessible(comboreadmem),
        "Zapamietane liczby"); 
  atk_object_set_description(
        gtk_widget_get_accessible(comboreadmem),
        "Ustaw poziom efektu kontrast"); 
  
  // przyciski MC
  buttonclearmem = gtk_button_new_with_label("MC");
  g_signal_connect(G_OBJECT(buttonclearmem),"clicked",G_CALLBACK(btn_clearmem_clicked),this);
  gtk_table_attach_defaults(GTK_TABLE(table),buttonclearmem,5,6,4,5);
  gtk_widget_set_sensitive(buttonclearmem,FALSE);
  
  /*
        GtkMenuBar
            GtkMenuItem
                GtkMenu
                    GtkImageMenuItem
                    GtkMenuItem
            GtkMenuItem
                GtkMenu
                    GtkMenuItem
                    GtkMenuItem
            GtkMenuItem
                GtkMenu
                    GtkMenuItem
  */
  menubar = gtk_menu_bar_new();

  menu_kalkulator = gtk_menu_new();
  menuitem_close = gtk_menu_item_new_with_label("Zamknij");
  gtk_menu_shell_append(GTK_MENU_SHELL(menu_kalkulator),menuitem_close);
  g_signal_connect(G_OBJECT(menuitem_close),"activate",G_CALLBACK(menu_item_close),this);

  menu_help = gtk_menu_new();
  menuitem_help = gtk_menu_item_new_with_label("Pomoc");
  gtk_menu_shell_append(GTK_MENU_SHELL(menu_help),menuitem_help);
  g_signal_connect(G_OBJECT(menuitem_help),"activate",G_CALLBACK(menu_item_help),this);
  
  menuitem_bar_kalkulator = gtk_menu_item_new_with_label("Kalkulator");
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem_bar_kalkulator),menu_kalkulator);
  gtk_menu_shell_append(GTK_MENU_SHELL(menubar),menuitem_bar_kalkulator);

  menuitem_bar_about = gtk_menu_item_new_with_label("O programie");
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem_bar_about),menu_help);
  gtk_menu_shell_append(GTK_MENU_SHELL(menubar),menuitem_bar_about);
  
  vbox_menu = gtk_vbox_new(FALSE,0);
  gtk_box_pack_start(GTK_BOX(vbox_menu),menubar,FALSE,TRUE,0);
  
  
  vbox = gtk_vbox_new(FALSE,0);
  gtk_box_pack_start(GTK_BOX(vbox),vbox_menu,FALSE,FALSE,0);
  gtk_box_pack_start(GTK_BOX(vbox),table,FALSE,FALSE,0);
  
  gtk_container_add(GTK_CONTAINER(mainwindow),vbox);
}

void GUIKalkulator::run()
{
  #ifdef INFO 
  __debug("GUIKalkulator run()",false);
  #endif
  gtk_widget_show_all(mainwindow);
  gtk_main();
}

gboolean GUIKalkulator::delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
  //GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  #ifdef INFO 
  //gui_kalkulator->__debug("GUIKalkulator delete_event()",false);
  static_cast<GUIKalkulator*>(data)->__debug("GUIKalkulator delete_event()",false);
  #endif
  return FALSE;
}

void GUIKalkulator::destroy(GtkWidget *widget, gpointer data)
{
  #ifdef INFO 
  static_cast<GUIKalkulator*>(data)->__debug("GUIKalkulator destroy(gtk_main_quit)",false);
  #endif
  gtk_main_quit();
}

void GUIKalkulator::_numeric_btn_clicked_event(btn_id button, GUIKalkulator* gui_kalkulator)
{
  const char *number = _btn_id_to_char(button);
  
  #ifdef INFO 
  __debug("GUIKalkulator _numeric_btn_clicked_event()",false);
  g_print("clicked: %s\n",number);
  #endif
  
  int len(0);
  gint8 test(0); 
  // 1 - poprzednio wciśnięto '=' na wyświetlaczu jest wynik, można na nim wynkonać nowe działania,
  //     ale wybrano nową cyfre, co sugeruje przerwanie dotychczasowego działania i
  //     rezpoczęcie nowego - wszystko jest zerowane podobnie jak podczas 'AC'
  // 2 - na wyswietlaczu jest wynik, np. po wywołaniu jednego z przycisków działań ('+'),
  //     wybrano nową cyfrę, więc definiujemy value2 - wyświetlacz jest czyszczony
  // 3 - na wyświetlaczu jest wynik, przed kolejnymi działaniami zostaje modyfikowany
  //     przez dodanie części ułamkowej, czyli wciśnięto przycisk ','
  // 4 - zaczynamy wprowadzań drugą wartość po przycisku działania
  
  if (get_is_result() && get_prev_button() == Button_result)
  {
    test = 1;
    #ifdef DEBUG 
    g_print("\ntest 1 ;)\n");
    #endif
  }
  else if (get_is_result() && 
           (get_prev_button() == Button_add   ||
            get_prev_button() == Button_sub   ||
            get_prev_button() == Button_multi ||
            get_prev_button() == Button_div)   )
  {
    test = 2;
    #ifdef DEBUG 
    g_print("\ntest 2 ;)\n");
    #endif
  }  
  else if (get_is_result() == false && 
           get_button_cache_comma() == Button_comma && 
           get_button_cache_result() == Button_result)
  {
    test = 3;
    #ifdef DEBUG 
    g_print("\ntest 3 ;)\n");
    #endif
  }
  else if (get_prev_button() == Button_add ||
           get_prev_button() == Button_sub ||
           get_prev_button() == Button_multi ||
           get_prev_button() == Button_div )
  {
    test = 4;
    #ifdef DEBUG 
    g_print("\ntest 4 ;)\n");
    #endif
  }
  
  switch (test)
  {
    case 1:
      if (get_is_value1())
        del_value1();
      if (get_is_value2())
        del_value2();
      
      set_operation(NoSelectOprt);
      set_prev_operation(NoSelectOprt);
      set_is_result(FALSE);
      set_prev_button(NoSelectBtn);
    
      gtk_entry_set_text(GTK_ENTRY(entry),"");
      len = strlen(GTK_ENTRY(entry)->text);
      gtk_editable_insert_text(GTK_EDITABLE(entry),number,1,&len);
      
      break;
    
    case 2:
      gtk_entry_set_text(GTK_ENTRY(entry),"");
      set_is_result(FALSE);
      
      len = strlen(GTK_ENTRY(entry)->text);
      gtk_editable_insert_text(GTK_EDITABLE(entry),number,1,&len);
      
      break;
    
    case 3:
      len = strlen(GTK_ENTRY(entry)->text);
      gtk_editable_insert_text(GTK_EDITABLE(entry),number,1,&len);
      
      set_value1(gtk_entry_get_text(GTK_ENTRY(entry)));
      
      break;
    
    case 4:
      gtk_entry_set_text(GTK_ENTRY(entry),"");
      
      len = strlen(GTK_ENTRY(entry)->text);
      gtk_editable_insert_text(GTK_EDITABLE(entry),number,1,&len);
      set_is_result(FALSE);
    
      break;
    
    default:
      len = strlen(GTK_ENTRY(entry)->text);
      gtk_editable_insert_text(GTK_EDITABLE(entry),number,1,&len);
  }
  
  set_prev_button(button);
  #ifdef DEBUG
  __debug("GUIKalkulator _numeric_btn_clicked_event()",true);
  #endif
}

void GUIKalkulator::_calculate_btn_clicked_event(operation_id operation)
{
  #ifdef INFO 
  __debug("GUIKalkulator _calculate_btn_clicked_event()",false);
  g_print("clicked: %s\n",_operation_id_to_char(operation));
  #endif
  
  gint8 test = 0,
        prev_operation_tmp = FALSE;
  gchar *text_entry = GTK_ENTRY(entry)->text;
  
  // +,-,*,/
  set_operation(operation);

  // test
  if (get_is_value1() == FALSE && 
      get_is_value2() == FALSE &&
      strlen(text_entry) > 0)
  {
    // nalezy ustawić value1
    test = 1;
    #ifdef DEBUG
    g_print("\ntest 1\n");
    #endif
  }
  else if (get_is_value1() == TRUE && 
           get_is_value2() == FALSE &&
           strlen(text_entry) > 0 &&
           get_prev_button() != Button_add &&
           get_prev_button() != Button_sub &&
           get_prev_button() != Button_multi &&
           get_prev_button() != Button_div &&
           get_prev_button() != Button_result &&
           get_prev_button() != Button_back && // po <- * zle!
           (get_button_cache_comma()!= Button_comma || get_button_cache_result() != Button_result) && // ,
           ((get_prev_button() == Button_signed && get_button_cache_result() != Button_result) ||     // -/+
            get_prev_button() != Button_signed)
          )
  {  
    test = 2;
    #ifdef DEBUG
    g_print("\ntest 2\n");
    #endif
  }
  else if (get_button_cache_result() == Button_result && 
           get_prev_button() == Button_back) 
  {
    set_value1(gtk_entry_get_text(GTK_ENTRY(entry)));
  }

  switch (test)
  {
    case 1:
      set_value1(gtk_entry_get_text(GTK_ENTRY(entry)));
      gtk_entry_set_text(GTK_ENTRY(entry),"");
      break;

    case 2:
      set_value2(gtk_entry_get_text(GTK_ENTRY(entry)));
      #ifdef DEBUG
      g_print("\nval1: %s",get_value1());
      g_print("\nval2: %s",get_value2());
      #endif
      // gdy po wielokrotnych operacji następuje zmiana
      // wynik obliczyć według poprzednio wybranej operacji
      // np. 5 + 5 (10)- 5 = 15
      if (get_operation() != get_prev_operation())
        prev_operation_tmp = TRUE;

      calculate(prev_operation_tmp);
      del_value2();
      /*
       *  kalkulator->value1 (wynik)
       *  kalkulator->value2 (puste)
       */
      set_is_result(true);
      gtk_entry_set_text(GTK_ENTRY(entry), get_value1());
      set_button_cache_result(Button_result);
      break;
  }

  set_prev_button(_operation_id_to_btn_id(operation));
  
  set_button_cache_comma(NoSelectBtn);
  set_button_cache_result(NoSelectBtn);
  
  // zabezpiecza nas przed tym: 
  // np. 1 + 5 * daje w wyniku 5 ponieważ wykonał rodzaj operacji 
  // domyślny dla obecnie (statnlio) wciśniętego przycisku, czyli *
  set_prev_operation(get_operation());
  
  #ifdef DEBUG
  __debug("GUIKalkulator _calculate_btn_clicked_event()",true);
  #endif
}

void GUIKalkulator::btn_1_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_1, NULL);
}

void GUIKalkulator::btn_2_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_2, NULL);
}

void GUIKalkulator::btn_3_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_3, NULL);
}

void GUIKalkulator::btn_4_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_4, NULL);
}

void GUIKalkulator::btn_5_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_5, NULL);
}

void GUIKalkulator::btn_6_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_6, NULL);
}

void GUIKalkulator::btn_7_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_7, NULL);
}

void GUIKalkulator::btn_8_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_8, NULL);
}

void GUIKalkulator::btn_9_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_9, NULL);
}

void GUIKalkulator::btn_0_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gui_kalkulator->_numeric_btn_clicked_event(Button_0, NULL);
}

void GUIKalkulator::btn_comma_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  int len(0);
  
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator clicked: ,",false);
  #endif
  bool cachecomma = false;
  
  if (gui_kalkulator->get_button_cache_comma()!= Button_comma)
  {
    if (strlen(GTK_ENTRY(gui_kalkulator->entry)->text) != 0)
    {
      len = strlen(GTK_ENTRY(gui_kalkulator->entry)->text);
      gtk_editable_insert_text(GTK_EDITABLE(gui_kalkulator->entry),",",1,&len);
      
      // synchronizacja wyniku (value1) ze zmianami na wyświetlaczu 
      if (gui_kalkulator->get_is_result() && 
          gui_kalkulator->get_prev_button() == Button_result)
      {
        gui_kalkulator->set_value1(gtk_entry_get_text(GTK_ENTRY(gui_kalkulator->entry)));
        gui_kalkulator->set_is_result(FALSE); // to już nie jest wynik, to nowa wartość! ale potrzebne aby poszło do value2
      }
      cachecomma = true;
    }
    else
    {
      gui_kalkulator->dialog = gtk_message_dialog_new(GTK_WINDOW(gui_kalkulator->mainwindow),
                                    GTK_DIALOG_MODAL,GTK_MESSAGE_WARNING,GTK_BUTTONS_OK,
                                    "Przecinek nie może być wprowadzony jako pierwszy!\nPowinien wystepować po liczbie.");
      gtk_dialog_run (GTK_DIALOG (gui_kalkulator->dialog));
      gtk_widget_destroy (gui_kalkulator->dialog);
    }
  }
  else
  {
    gui_kalkulator->dialog = gtk_message_dialog_new(GTK_WINDOW(gui_kalkulator->mainwindow),
                                    GTK_DIALOG_MODAL,GTK_MESSAGE_WARNING,GTK_BUTTONS_OK,
                                    "Wprowadzona liczba zawiera już przecinek!\nNie można wprowadzić przecinka drugi raz.");
    gtk_dialog_run (GTK_DIALOG (gui_kalkulator->dialog));
    gtk_widget_destroy (gui_kalkulator->dialog);
  }
  
  if (cachecomma)
    gui_kalkulator->set_button_cache_comma(Button_comma);
  
  gui_kalkulator->set_prev_button(Button_comma);
  #ifdef DEBUG
  gui_kalkulator->__debug("GUIKalkulator btn_comma_clicked()",true);
  #endif
}

void GUIKalkulator::btn_back_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  GString *tmp=NULL;
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator clicked: <-",false);
  #endif
  tmp = g_string_new(gtk_entry_get_text(GTK_ENTRY(gui_kalkulator->entry)));
  tmp = g_string_truncate(tmp,tmp->len-1);
  gtk_entry_set_text(GTK_ENTRY(gui_kalkulator->entry), g_string_free(tmp,FALSE));
  
  // synchronizacja wyniku (value1) ze zmianami na wyświetlaczu 
  if (gui_kalkulator->get_is_result())
  {
    gui_kalkulator->set_is_result(FALSE); // to już nie jest wynik, to nowa wartość!
  }
  
  gui_kalkulator->set_prev_button(Button_back);
}

void GUIKalkulator::btn_clear_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator clicked: C",false);
  #endif
  if (gui_kalkulator->get_is_value1())
    gui_kalkulator->del_value1(); 
  if (gui_kalkulator->get_is_value2())
    gui_kalkulator->del_value2(); 
  
  gui_kalkulator->set_operation(NoSelectOprt);
  gui_kalkulator->set_prev_operation(NoSelectOprt);
  gui_kalkulator->set_is_result(FALSE);
  gui_kalkulator->set_prev_button(NoSelectBtn);
  gui_kalkulator->set_button_cache_comma(NoSelectBtn);
  gui_kalkulator->set_button_cache_result(NoSelectBtn);
  
  gtk_entry_set_text(GTK_ENTRY(gui_kalkulator->entry),"");

  gui_kalkulator->set_prev_button(Button_clear);
  
  #ifdef DEBUG
  gui_kalkulator->__debug("GUIKalkulator clicked: C",true);
  #endif
}

void GUIKalkulator::btn_add_clicked(GtkWidget *widget, gpointer data)
{
  static_cast<GUIKalkulator*>(data)->_calculate_btn_clicked_event(Add);
}

void GUIKalkulator::btn_sub_clicked(GtkWidget *widget, gpointer data)
{
  static_cast<GUIKalkulator*>(data)->_calculate_btn_clicked_event(Sub);
}

void GUIKalkulator::btn_multi_clicked(GtkWidget *widget, gpointer data)
{
  static_cast<GUIKalkulator*>(data)->_calculate_btn_clicked_event(Multi);
}

void GUIKalkulator::btn_div_clicked(GtkWidget *widget, gpointer data)
{
  static_cast<GUIKalkulator*>(data)->_calculate_btn_clicked_event(Div);
}

void GUIKalkulator::btn_result_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  gchar *text_entry = GTK_ENTRY(gui_kalkulator->entry)->text;
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator clicked: =",false);
  #endif

  if (gui_kalkulator->get_is_value1() == TRUE && 
      gui_kalkulator->get_is_value2() == FALSE &&
      strlen (text_entry) > 0 &&
      gui_kalkulator->get_prev_button() != Button_add &&
      gui_kalkulator->get_prev_button() != Button_sub &&
      gui_kalkulator->get_prev_button() != Button_multi &&
      gui_kalkulator->get_prev_button() != Button_div &&
      gui_kalkulator->get_prev_button() != Button_result &&
      gui_kalkulator->get_prev_button() != Button_comma )
  {
    gui_kalkulator->set_value2(gtk_entry_get_text(GTK_ENTRY(gui_kalkulator->entry)));
    
    gui_kalkulator->calculate(FALSE);
    gui_kalkulator->del_value2();
    /*
     *  kalkulator->value1 (wynik)
     *  kalkulator->value2 (puste)
     */
    
    gtk_entry_set_text(GTK_ENTRY(gui_kalkulator->entry), gui_kalkulator->get_value1());
    gui_kalkulator->set_button_cache_result(Button_result);
  }
  
  gui_kalkulator->set_prev_button(Button_result);
  
  gui_kalkulator->set_button_cache_comma(NoSelectBtn);
  
  #ifdef DEBUG
  gui_kalkulator->__debug("GUIKalkulator clicked: =",true); 
  #endif
}

void GUIKalkulator::btn_signed_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  int *pos = new int(0);
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator clicked: -/+",false);
  #endif
  
  char *sig = gtk_editable_get_chars(GTK_EDITABLE(gui_kalkulator->entry),0,1);
  
  if (strcmp(sig,"-")) // 0 == equal
    gtk_editable_insert_text(GTK_EDITABLE(gui_kalkulator->entry),"-",1,pos);
  else
    gtk_editable_delete_text(GTK_EDITABLE(gui_kalkulator->entry),0,1);
  
  // synchronizacja wyniku (value1) ze zmianami na wyświetlaczu 
  //if (gui_kalkulator->get_is_result()) // checkit!
  {
    gui_kalkulator->set_value1(gtk_entry_get_text(GTK_ENTRY(gui_kalkulator->entry)));
  }

  g_free(sig);
  gui_kalkulator->set_prev_button(Button_signed);
  #ifdef DEBUG
  gui_kalkulator->__debug("GUIKalkulator clicked: -/+",true); 
  #endif
}

void GUIKalkulator::btn_addmem_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator clicked: M+",false);
  #endif
  
  if (strlen(GTK_ENTRY(gui_kalkulator->entry)->text) == 0)
  {
    gui_kalkulator->dialog = gtk_message_dialog_new(GTK_WINDOW(gui_kalkulator->mainwindow),
                                    GTK_DIALOG_MODAL,GTK_MESSAGE_WARNING,GTK_BUTTONS_OK,
                                    "Brak wartości do wprowadzenia!\nWyświetlacz jest pusty.");
    gtk_dialog_run (GTK_DIALOG (gui_kalkulator->dialog));
    gtk_widget_destroy (gui_kalkulator->dialog);
  }
  else
  {
    gui_kalkulator->add_to_memory(gtk_entry_get_text(GTK_ENTRY(gui_kalkulator->entry)));
    gtk_combo_box_append_text(GTK_COMBO_BOX(gui_kalkulator->comboreadmem),gtk_entry_get_text(GTK_ENTRY(gui_kalkulator->entry)));
    gui_kalkulator->combocount++;
    gtk_widget_set_sensitive(gui_kalkulator->buttonclearmem,TRUE);
    gtk_widget_set_sensitive(gui_kalkulator->comboreadmem,TRUE);
  }
    
  gui_kalkulator->set_prev_button(Button_addmem);
  #ifdef DEBUG
  gui_kalkulator->__debug("GUIKalkulator clicked: M+",true); 
  
  if (gui_kalkulator->memory_count() == gui_kalkulator->combocount-1) // -pierwsza pozycja nie bedąca liczbą
  {
    cout << "\nIlość elementów listy zgadza się z ilością elementów w combobox" << endl
         << "combocount: " << gui_kalkulator->combocount << endl
         << "memory_count(): " << gui_kalkulator->memory_count() << endl;
  }
  else
    cout << "\nIlość elementów listy NIE zgadza się z ilością elementów w combobox" << endl;
  
  #endif
}

void GUIKalkulator::btn_readmem_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator clicked: readmem",false);
  #endif
  gchar *select;
  select = gtk_combo_box_get_active_text(GTK_COMBO_BOX(gui_kalkulator->comboreadmem));
  if (select[0] != 'C' && select[1] != 'z' && select[2] != 'y')
  {
    if ((strlen(GTK_ENTRY(gui_kalkulator->entry)->text) == 0) ||
        (strlen(GTK_ENTRY(gui_kalkulator->entry)->text) != 0 &&
        (gui_kalkulator->get_prev_button() == Button_add ||
        gui_kalkulator->get_prev_button() == Button_sub ||
        gui_kalkulator->get_prev_button() == Button_multi ||
        gui_kalkulator->get_prev_button() == Button_div)))
    {
      gtk_entry_set_text(GTK_ENTRY(gui_kalkulator->entry),select);
      g_free(select);
      // umożliwia wybranie drugi raz tej samej liczby
      gtk_combo_box_set_active(GTK_COMBO_BOX(gui_kalkulator->comboreadmem),0);
      gtk_widget_set_sensitive(gui_kalkulator->comboreadmem,TRUE);
    }
    else
    {
      gui_kalkulator->dialog = gtk_message_dialog_new(GTK_WINDOW(gui_kalkulator->mainwindow),
                                    GTK_DIALOG_MODAL,GTK_MESSAGE_WARNING,GTK_BUTTONS_OK,
      "Wprowadzono już liczbę!\nJeżeli nie jest to kolejna liczba następująca po działaniu (+,-,*,/) wyświetlacz musi być pusty.");
      gtk_dialog_run (GTK_DIALOG (gui_kalkulator->dialog));
      gtk_widget_destroy (gui_kalkulator->dialog);
      // umożliwia wybranie drugi raz tej samej liczby
      gtk_combo_box_set_active(GTK_COMBO_BOX(gui_kalkulator->comboreadmem),0);
      gtk_widget_set_sensitive(gui_kalkulator->comboreadmem,TRUE);
    }
  }
  
  gui_kalkulator->set_prev_button(Button_readmem);
  #ifdef DEBUG
  gui_kalkulator->__debug("GUIKalkulator clicked: -/+",true); 
  #endif
}

void GUIKalkulator::btn_clearmem_clicked(GtkWidget *widget, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator clicked: MC",false);
  #endif
  
  gui_kalkulator->memory_free();
  // combocoun liczone od 1
  // index w funkcji od 0
  // dlatego pozwalamy sobie na natychmiastowe zmniejszenie --combocount
  gtk_combo_box_set_active(GTK_COMBO_BOX(gui_kalkulator->comboreadmem),0); 
  // zapobiega naruszeniu pamięci
  while(gui_kalkulator->combocount>1)
    gtk_combo_box_remove_text(GTK_COMBO_BOX(gui_kalkulator->comboreadmem),--gui_kalkulator->combocount);
  
  gtk_widget_set_sensitive(gui_kalkulator->buttonclearmem,FALSE);
  gtk_widget_set_sensitive(gui_kalkulator->comboreadmem,FALSE);
  
  gui_kalkulator->set_prev_button(Button_clearmem);
  #ifdef DEBUG
  gui_kalkulator->__debug("GUIKalkulator clicked: MC",true); 
  #endif
}

void GUIKalkulator::menu_item_close(GtkMenuItem *menuitem, gpointer data)
{
  //GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  #ifdef INFO 
  //gui_kalkulator->__debug("GUIKalkulator: MENU->close",false);
  static_cast<GUIKalkulator*>(data)->__debug("GUIKalkulator: MENU->close",false);
  #endif
  gtk_main_quit();
}

void GUIKalkulator::menu_item_help(GtkMenuItem *menuitem, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator: MENU->about",false);
  #endif
  
  static const gchar *authors = "Grzegorz Kuczyński <gk180984@interia.pl>";
  static const gchar comments[] = "Jest to program demonstracyjny, \nnapisany w celach edukacyjnych GTK+.\n\nPo prostu dla zabawy :)";
  static const gchar copyright[] = "Copyright \xc2\xa9 2009 Grzegorz Kuczyńśki\n";
  
  gui_kalkulator->dialog = gtk_about_dialog_new();
  gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(gui_kalkulator->dialog),"Kalkulator");
  gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(gui_kalkulator->dialog),"0.0.1");
  gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(gui_kalkulator->dialog),comments);
  gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(gui_kalkulator->dialog),&authors);
  gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(gui_kalkulator->dialog),copyright);
  gtk_dialog_run (GTK_DIALOG (gui_kalkulator->dialog));

  gtk_widget_destroy (gui_kalkulator->dialog);
}

gboolean GUIKalkulator::mainwindow_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
  GUIKalkulator *gui_kalkulator = static_cast<GUIKalkulator*>(data);
  #ifdef INFO 
  gui_kalkulator->__debug("GUIKalkulator: key press",false);
  #endif
  
  GdkEvent ev;
  ev.key.keyval = event->keyval;
  
  // Można by było tak...
  /**********************
  switch(event->keyval)
  {
    case GDK_KP_0: gui_kalkulator->_numeric_btn_clicked_event(Button_0,NULL); break;
    case GDK_KP_1: gui_kalkulator->_numeric_btn_clicked_event(Button_1,NULL); break;
    case GDK_KP_2: gui_kalkulator->_numeric_btn_clicked_event(Button_2,NULL); break;
    case GDK_KP_3: gui_kalkulator->_numeric_btn_clicked_event(Button_3,NULL); break;
    case GDK_KP_4: gui_kalkulator->_numeric_btn_clicked_event(Button_4,NULL); break;
    case GDK_KP_5: gui_kalkulator->_numeric_btn_clicked_event(Button_5,NULL); break;
    case GDK_KP_6: gui_kalkulator->_numeric_btn_clicked_event(Button_6,NULL); break;
    case GDK_KP_7: gui_kalkulator->_numeric_btn_clicked_event(Button_7,NULL); break;
    case GDK_KP_8: gui_kalkulator->_numeric_btn_clicked_event(Button_8,NULL); break;
    case GDK_KP_9: gui_kalkulator->_numeric_btn_clicked_event(Button_9,NULL); break;
    case GDK_KP_Add: gui_kalkulator->_calculate_btn_clicked_event(Add); break;
    case GDK_KP_Divide: gui_kalkulator->_calculate_btn_clicked_event(Div); break;
    case GDK_KP_Subtract: gui_kalkulator->_calculate_btn_clicked_event(Sub); break;
    case GDK_KP_Multiply: gui_kalkulator->_calculate_btn_clicked_event(Multi); break;
    case GDK_KP_Enter: gui_kalkulator->btn_result_clicked(gui_kalkulator->buttonresult,gui_kalkulator); break;
    case GDK_comma: gui_kalkulator->btn_comma_clicked(gui_kalkulator->buttoncomma,gui_kalkulator); break;
    case GDK_BackSpace: gui_kalkulator->btn_back_clicked(gui_kalkulator->buttonback,gui_kalkulator); break;
  }
  **********************/
  // ...ale trzeba by było w każdym wypadku ustawić wszystkie zmienne typu set_prev_button itp
  // ponieważ wszystkie obliczenia i sterowanie opiera się na informacjach zawartych
  // własnie w tych zmienneych.
  //
  // Tak jest lepiej ponieważ symulujemy wciśnięcie tych przycisków, tak jak byśmy je wciskali 
  // sami, więc nie trzeba się martwić przepływem sterowania.
  switch(event->keyval)
  {
    case GDK_KP_0: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button0),"clicked");break;
    case GDK_KP_1: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button1),"clicked");break;
    case GDK_KP_2: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button2),"clicked");break;
    case GDK_KP_3: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button3),"clicked");break;
    case GDK_KP_4: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button4),"clicked");break;
    case GDK_KP_5: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button5),"clicked");break;
    case GDK_KP_6: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button6),"clicked");break;
    case GDK_KP_7: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button7),"clicked");break;
    case GDK_KP_8: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button8),"clicked");break;
    case GDK_KP_9: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->button9),"clicked");break;
    case GDK_KP_Add: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->buttonadd),"clicked");break;
    case GDK_KP_Divide: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->buttondiv),"clicked");break;
    case GDK_KP_Subtract: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->buttonsub),"clicked");break;
    case GDK_KP_Multiply: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->buttonmulti),"clicked");break;
    case GDK_KP_Enter: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->buttonresult),"clicked");break;
    case GDK_KP_Separator: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->buttoncomma),"clicked");break;
    case GDK_BackSpace: g_signal_emit_by_name(G_OBJECT(gui_kalkulator->buttonback),"clicked");break;
  }
  
  return true;
}