{ Temperature.pas - allow the user to enter temperatures and convert them between Fahrenheit and Celsius } program temperature; {$mode objfpc} // use Delphi 2 extensions uses glib, gdk, gtk, sysutils; { Define a record type to represent our app's window and controls. This makes it easier to mainpulate it w/o using global variables. } Type TMainWindow = Record Window : pGtkWindow; // top-level window hBox, // main container for controls fahBox, // holds Fahrenheit label and text box celBox, // holds Celsius label and text box celButton, // C to F button fahButton, // F to C button celEntry, // Celsius text box fahEntry, // Fahrenheit text box celSlider, // Celsius slider fahSlider, // Fahrenheit slider celLabel, // label in Celsius box fahLabel : pGtkWidget; // label in Fahrenheit box celAdjust, // range for Celsius slider fahAdjust : pGtkObject; // range for Fahrenheit slider end; PMainWindow = ^TMainWindow; procedure quit_app (widget: pGtkWidget; Window: PMainWindow); cdecl; { Clean up and shut down GTK+ signal handling. } begin dispose(Window); gtk_main_quit; end; // procedure quit_app procedure scale_set_default_values( scale : pGtkScale); { Set default values for specified GtkScale widget. } begin gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_CONTINUOUS); gtk_scale_set_digits (scale, 1); gtk_scale_set_value_pos (scale, GTK_POS_BOTTOM); gtk_scale_set_draw_value (scale, TRUE); end; // procedure scale_set_default_values function FtoC(tempF: float):float; { Convert temp in Fahrenheit to Celsius. } begin Result := (tempF - 32) * (5/9); end; // function FtoC function CtoF(tempC: float): float; { Convert temp in Celsius to Fahrenheit. } begin Result := (tempC * (9/5) + 32); end; // function CtoF procedure SetSliderValue ( slider : pGtkAdjustment; value : float); { Position the specified GtkAdjustment widget to the value. } begin if (value < 0.0) and (value > 100.0) then value := 0.0; gtk_adjustment_set_value(slider, value); end; // procedure SetSliderValue procedure DisplayTemp( temperature : float; entry : pGtkEntry); { Put the temperature in the specified text box. } begin gtk_entry_set_text(entry, pchar(Format('%.1f', [temperature]))); end; // procedure DisplayTemp procedure buttonCtoF(widget: pGtkWidget; Window: PMainWindow); cdecl; { C to F button signal handler. Get Cel temp, convert it and display new Fah temp. } var textValue: pgchar; tempC, tempF: float; begin textValue := gtk_entry_get_text(pGtkEntry(Window^.celEntry)); if textValue <>'' then begin // Wrap StrToFloat in a try-except-end block in case letters were // typed into the text box. try tempC := StrToFloat(textValue); except on E:EConvertError do tempC := 0.0; end; // try-except tempF := CtoF(tempC); DisplayTemp(tempF, pGtkEntry(Window^.fahEntry)); SetSliderValue(pGtkAdjustment(Window^.fahAdjust), tempF); end; // procedure buttonCtoF end; procedure buttonFtoC(widget: pGtkWidget; Window: PMainWindow); cdecl; { F to C button signal handler. Get Fah temp, convert it and display new Cel temp. } var textValue: pgchar; tempC, tempF: float; begin textValue := gtk_entry_get_text(pGtkEntry(Window^.fahEntry)); if textValue <>'' then begin // Wrap StrToFloat in a try-except-end block in case letters were // typed into the text box. try tempF := StrToFloat(textValue); except on E:EConvertError do tempF := 0.0; end; // try-except tempC := FtoC(tempF); DisplayTemp(tempC, pGtkEntry(Window^.celEntry)); SetSliderValue(pGtkAdjustment(Window^.celAdjust), tempC); end; // if textValue <> '' end; // procedure buttonFtoC procedure FsliderChanged( widget : pGtkWidget; Window : PMainWindow); cdecl; { Fahrenheit slider has moved, display new value. } begin DisplayTemp(pGtkAdjustment(Window^.fahAdjust)^.value, pGtkEntry(Window^.fahEntry)); end; // procedure FsliderChanged procedure CsliderChanged( widget : pGtkWidget; Window : PMainWindow); cdecl; { Celsius slider has moved, display new value. } begin DisplayTemp(pGtkAdjustment(Window^.celAdjust)^.value, pGtkEntry(Window^.celEntry)); end; // procedure CsliderChanged function create_main_window : PMainWindow; { Create an instance of the main window and all its controls. } begin Result := New(PMainWindow); with Result^ do begin Window := pGtkWindow(gtk_window_new(GTK_WINDOW_TOPLEVEL)); gtk_window_set_title(Window, 'Temperature Conversion'); gtk_signal_connect(pGtkObject(Window), 'destroy', GTK_SIGNAL_FUNC (@quit_app), Result); hBox := gtk_hbox_new(false, 10); gtk_container_add(GTK_CONTAINER(Window), hBox); // Create vertical sliders whose ranges are controlled by a // gtk_adjustment widget, set signal handlers, and add them // to the application's window. fahAdjust := gtk_adjustment_new(0.0, 0.0, 101.0, 0.5, 10.0, 1.0); fahSlider := gtk_vscale_new(GTK_ADJUSTMENT(fahAdjust)); scale_set_default_values(GTK_SCALE(fahSlider)); gtk_signal_connect(GTK_OBJECT(fahAdjust), 'value_changed', GTK_SIGNAL_FUNC(@FsliderChanged), Result); gtk_box_pack_start(pGtkBox(hBox), pGtkWidget(fahSlider), False, False, 0); // Create a vertical box to hold the Fahrenheit label and text box. fahBox := gtk_vbox_new(false, 10); gtk_container_add(GTK_CONTAINER(hBox), fahBox); fahLabel := gtk_label_new('Fahrenheit'); gtk_box_pack_start(pGtkBox(fahBox), pGtkWidget(fahLabel), False, False, 0); fahEntry := gtk_entry_new(); gtk_box_pack_start(pGtkBox(fahBox), pGtkWidget(fahEntry), False, False, 0); fahButton := gtk_button_new_with_label('--F to C-->'); gtk_signal_connect(pGtkObject(fahButton), 'clicked', GTK_SIGNAL_FUNC(@buttonFtoC), Result); gtk_box_pack_start(pGtkBox(fahBox), pGtkWidget(fahButton), False, False, 5); // Create a vertical box to hold the Celsius label and text box. celBox := gtk_vbox_new(False, 10); gtk_container_add(GTK_CONTAINER(hBox), celBox); celLabel := gtk_label_new('Celsius'); celEntry := gtk_entry_new(); gtk_box_pack_start(pGtkBox(celBox), pGtkWidget(celLabel), False, False, 0); gtk_box_pack_start(pGtkBox(celBox), pGtkWidget(celEntry), False, False, 0); celButton := gtk_button_new_with_label('<--C to F--'); gtk_signal_connect(pGtkObject(celButton), 'clicked', GTK_SIGNAL_FUNC(@buttonCtoF), Result); gtk_box_pack_start(pGtkBox(celBox), pGtkWidget(celButton), False, False, 5); // Finally add the Celsius slider to the application window. celAdjust := gtk_adjustment_new(0.0, 0.0, 101.0, 0.5, 10.0, 1.0); celSlider := gtk_vscale_new(GTK_ADJUSTMENT(celAdjust)); scale_set_default_values(GTK_SCALE(celSlider)); gtk_signal_connect(GTK_OBJECT(celAdjust), 'value_changed', GTK_SIGNAL_FUNC(@CsliderChanged), Result); gtk_box_pack_start(pGtkBox(hBox), pGtkWidget(celSlider), False, False, 0); end; // with Result^ end; // function create_main_window var MainWindow : PMainWindow; begin // Initialize the GTK+ libraries. gtk_init(@argc, @argv); // Create and show the application's window. MainWindow:=create_main_window; gtk_widget_show_all(PGtkWidget(MainWindow^.Window)); // Start handling signals. gtk_main(); end.