mirror of
https://github.com/eddyem/fitsview-hartmann.git
synced 2025-12-06 02:35:18 +03:00
1205 lines
37 KiB
C
1205 lines
37 KiB
C
// gtk.c - main funtions to work with windows
|
|
//
|
|
// Copyright 2011 Edward V. Emelianoff <eddy@sao.ru>
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
// MA 02110-1301, USA.
|
|
#include "gtk.h"
|
|
#include "tracking.h"
|
|
#include "opengl.h"
|
|
#include "ui.h"
|
|
#include "imtools.h"
|
|
#include "contours.h"
|
|
#include "fits.h"
|
|
#include "open_dialog.h"
|
|
#include "fitsheaders.h"
|
|
#include "terrain.h"
|
|
#include "filelist.h"
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
Window *mainWindow;
|
|
|
|
double X0, Y0, lX0, lY0; // started coordinates of click, layer coordinates at click
|
|
// the longer key is pressed, the larger value of key_acceleration (3D moving):
|
|
double key_acceleration = 1.;
|
|
// multipliers for zoom in/out
|
|
const double ZOOM_NEAR = 1.1, ZOOM_FAR = 1./1.1;
|
|
|
|
void run_modal_window(GtkWindow *w, Window *parent){
|
|
gtk_window_set_transient_for(w, GTK_WINDOW(parent->window));
|
|
gtk_window_set_modal(w, TRUE);
|
|
gtk_window_set_position(w, GTK_WIN_POS_MOUSE);
|
|
gtk_widget_show_all(GTK_WIDGET(w));
|
|
}
|
|
|
|
gint run_modal_dialog(GtkDialog *dialog, Window *parent){
|
|
run_modal_window(GTK_WINDOW(dialog), parent);
|
|
return gtk_dialog_run(GTK_DIALOG(dialog));
|
|
}
|
|
|
|
/*
|
|
* Error messages output
|
|
* text - message text
|
|
*/
|
|
void g_err(gchar *text){
|
|
GtkMessageDialog *dialog;
|
|
g_printerr(_("Error: %s\n"), text);
|
|
dialog = GTK_MESSAGE_DIALOG(gtk_message_dialog_new(NULL,
|
|
GTK_DIALOG_MODAL,
|
|
GTK_MESSAGE_ERROR,
|
|
GTK_BUTTONS_CLOSE,
|
|
"%s", text));
|
|
run_modal_dialog(GTK_DIALOG(dialog), mainWindow);
|
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
|
}
|
|
|
|
void show_about_dialog(){
|
|
GtkAboutDialog *about = GTK_ABOUT_DIALOG(gtk_about_dialog_new());
|
|
const gchar *author[] = { "Edward V. Emelianov <eddy@sao.ru>, <edward.emelianoof@gmail.com>", NULL };
|
|
gtk_about_dialog_set_program_name(about, "FITS view & Hartman data reduction");
|
|
gtk_about_dialog_set_version(about, PACKAGE_VERSION);
|
|
gtk_about_dialog_set_copyright(about, "Copyright 2012 Edward V. Emelianov");
|
|
gtk_about_dialog_set_website(about, "http://eddyem.narod.ru");
|
|
gtk_about_dialog_set_authors(about, author);
|
|
run_modal_dialog(GTK_DIALOG(about), mainWindow);
|
|
gtk_widget_destroy(GTK_WIDGET(about));
|
|
}
|
|
|
|
/*
|
|
* exit
|
|
*/
|
|
void chk_quit(){
|
|
gtk_main_quit();
|
|
// uncomment next, when autosaving of settings will be released
|
|
/*GtkMessageDialog *dialog;
|
|
dialog = GTK_MESSAGE_DIALOG(gtk_message_dialog_new(NULL,
|
|
GTK_DIALOG_MODAL,
|
|
GTK_MESSAGE_QUESTION,
|
|
GTK_BUTTONS_YES_NO,
|
|
_("You sure, you want exit?")));
|
|
gint ans = run_modal_dialog(GTK_DIALOG(dialog), mainWindow);
|
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
|
if(ans == GTK_RESPONSE_YES){
|
|
gtk_main_quit();
|
|
}*/
|
|
}
|
|
|
|
void change_window_filename(gchar *filename, Window *window){
|
|
gchar *title, *bsnm;
|
|
if(!filename) return;
|
|
g_free(window->image->filename);
|
|
bsnm = g_path_get_basename(filename);
|
|
if(window == mainWindow)
|
|
title = g_strdup_printf("%s (main) - %s", PRGNAME, bsnm);
|
|
else
|
|
title = g_strdup_printf("%s - %s", PRGNAME, bsnm);
|
|
gtk_window_set_title(GTK_WINDOW(window->window), title);
|
|
window->image->filename = bsnm;
|
|
g_free(title);
|
|
}
|
|
|
|
void change_image(gchar *filename, Window *window){
|
|
if(!filename) return;
|
|
if(try_open_file(filename, window->image)){
|
|
change_window_filename(filename, window);
|
|
}else
|
|
change_window_filename("", window);
|
|
window->context->current_image = window->image;
|
|
gen_texture(window->image, window, FALSE);
|
|
window->context->transformMask = TRANS_NONE;
|
|
}
|
|
|
|
// "save as" filename choosing dialog
|
|
gchar *get_save_filename(Window *window){
|
|
FNAME();
|
|
GtkFileChooser *dialog;
|
|
gchar *filename = NULL, *retfilename = NULL;
|
|
gint response;
|
|
dialog = GTK_FILE_CHOOSER(
|
|
gtk_file_chooser_dialog_new("Save File", NULL,
|
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
|
NULL));
|
|
if(saved_path)
|
|
gtk_file_chooser_set_current_folder(dialog, saved_path);
|
|
gtk_file_chooser_set_current_name(dialog, "new_fits_file.fit");
|
|
gtk_file_chooser_set_do_overwrite_confirmation(dialog, TRUE);
|
|
response = run_modal_dialog(GTK_DIALOG(dialog), window);
|
|
if(response == GTK_RESPONSE_ACCEPT){
|
|
filename = gtk_file_chooser_get_filename(dialog);
|
|
}
|
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
|
if(filename){
|
|
if(!get_ext(filename)) // There wasn't .fit suffix
|
|
retfilename = g_strdup_printf("!%s.fit", filename); // to rewrite file, if needed
|
|
else
|
|
retfilename = g_strdup_printf("!%s", filename);
|
|
g_free(filename);
|
|
}
|
|
return retfilename;
|
|
}
|
|
|
|
// get choosed filename to open and fills filelist of current directory
|
|
gchar *get_open_filename(Window *window){
|
|
FNAME();
|
|
GtkFileChooser *dialog;
|
|
gchar *filename = NULL;
|
|
gint response;
|
|
dialog = open_fits_dialog();
|
|
response = run_modal_dialog(GTK_DIALOG(dialog), window);
|
|
g_free(saved_path);
|
|
saved_path = gtk_file_chooser_get_current_folder(dialog);
|
|
if(response == GTK_RESPONSE_ACCEPT){
|
|
filename = gtk_file_chooser_get_filename(dialog);
|
|
DBG("open file %s", filename);
|
|
gint nfiles = fill_filelist(filename, window);
|
|
DBG("found %d files", nfiles);
|
|
g_free(filename); filename = NULL;
|
|
if(nfiles > 0 && window->files.list_current)
|
|
filename = window->files.list_current->data;
|
|
else
|
|
g_err(_("Can't read fits file"));
|
|
}
|
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
|
return filename;
|
|
}
|
|
|
|
void save_as(Window *window){
|
|
gchar *filename = NULL;
|
|
if((filename = get_save_filename(window))){
|
|
change_window_filename(filename, window);
|
|
if(!writefits(filename, window->image))
|
|
g_err(_("Can't save file"));
|
|
g_free(filename);
|
|
}
|
|
}
|
|
void open_file(Window *window){
|
|
gchar *filename;
|
|
if((filename = get_open_filename(window)))
|
|
change_image(filename, window);
|
|
}
|
|
void open_in_new(Window *window){
|
|
gchar *filename;
|
|
Window *newwin = init_window(window, OPENGL_WINDOW);
|
|
if(!(filename = get_open_filename(newwin)))
|
|
destroy_window(newwin);
|
|
else
|
|
change_image(filename, newwin);
|
|
}
|
|
void open_in_3D(Window *window){
|
|
Window *terra = init_window(window, GL3D_WINDOW);
|
|
terrain_3D(terra, 0.,0.,0.,0., TRUE);
|
|
}
|
|
|
|
void close_subwindow(Window *w){
|
|
gtk_widget_hide(w->window);
|
|
}
|
|
|
|
// Refreshing State fields of status bar
|
|
void refresh_state(Window *window){
|
|
//FNAME();
|
|
Context *c = window->context;
|
|
gchar buf[32];
|
|
gchar draw[] = {'T', 'S', 'Q'};
|
|
gchar track[] = {'A', 'V', 'H', 'D'};
|
|
gchar graph[] = {'G', 'H'};
|
|
if(window->id != GRAPH_WINDOW){
|
|
g_sprintf(buf, "dX=%.1f, dY=%.1f", window->move.x, window->move.y);
|
|
set_status_text(StatusAdd, buf, window);
|
|
g_sprintf(buf, "%c %c %s (%.1f%%) Z=%.1f",
|
|
draw[c->drawingMode], track[c->trackingMode],
|
|
(c->transformMask ? "tr" : ""),
|
|
100./window->Daspect*window->Zoom, window->Zoom);
|
|
set_status_text(StatusState, buf, window);
|
|
}else{
|
|
g_sprintf(buf, "%c %s",
|
|
graph[c->graphMode], (isYlog(window) ? "log" : "lin"));
|
|
set_status_text(StatusState, buf, window);
|
|
}
|
|
}
|
|
|
|
void set_status_text(guint barName, gchar *text, Window *window){
|
|
if(!window || barName >= window->statusBlocks) return;
|
|
gtk_entry_set_text(window->SBars[barName], text);
|
|
}
|
|
|
|
/*
|
|
* This three short functions need to have ability to change scale
|
|
* of axe Y from menu
|
|
*/
|
|
gboolean redraw_D(Window *window){
|
|
Gconfigure(window);
|
|
gdk_window_invalidate_rect(window->drawingArea->window, NULL, FALSE);
|
|
refresh_state(window);
|
|
return TRUE;
|
|
}
|
|
gboolean log_scale(Window *window){ // press 'e' in graph window
|
|
window->context->graphYaxis |=
|
|
(window->context->graphMode == GR_GRAPH) ? Y_LOGGRAPH : Y_LOGHIST;
|
|
redraw_D(window);
|
|
return TRUE;
|
|
}
|
|
gboolean lin_scale(Window *window){ // press 'l' in graph window
|
|
window->context->graphYaxis &= (window->context->graphMode == GR_GRAPH) ?
|
|
~Y_LOGGRAPH : ~Y_LOGHIST;
|
|
redraw_D(window);
|
|
return TRUE;
|
|
}
|
|
|
|
// Show histogram in chart window
|
|
void show_histogram(Window *window){
|
|
IMAGE *ima;
|
|
if(!window->context->current_image || !window->context->current_image->data){
|
|
window->context->current_image = window->image;
|
|
if(!window->image || !window->image->data) return;
|
|
}
|
|
ima = window->context->current_image;
|
|
if(!ima->stat.histogram.data)
|
|
if(!make_histogram(ima))
|
|
return;
|
|
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(window->graphWindow->LinLogMenu[isYlog(window)]), TRUE);
|
|
gtk_widget_show_all(window->graphWindow->window);
|
|
do_histogram(window);
|
|
}
|
|
|
|
void correct_zoom_by_move(Window *window, double Zoom_factor, double *x, double *y){
|
|
double xx, yy, Xc, Yc, ZZ;
|
|
if(!x) xx = (double)window->drawingArea->allocation.width / 2.;
|
|
else xx = *x;
|
|
if(!y) yy = (double)window->drawingArea->allocation.height / 2.;
|
|
else yy = *y;
|
|
//DBG("x=%g, y=%g",xx,yy);
|
|
conv_mouse_to_image_coords(xx, yy, &Xc, &Yc, window);
|
|
Xc -= window->texture->w / 2.; Yc -= window->texture->h / 2.;
|
|
//DBG("Xc=%g, Yc=%g, ZF=%g",Xc, Yc, Zoom_factor);
|
|
// It's amazing (if U don't know what float is), but Zoom*(Zoom_factor - 1) isn't the same
|
|
ZZ = window->Zoom*Zoom_factor - window->Zoom;
|
|
window->move.x -= Xc * ZZ;
|
|
window->move.y -= Yc * ZZ;
|
|
//DBG("moveX=%g, moveY=%g\n", window->move.x, window->move.y);
|
|
window->Zoom *= Zoom_factor;
|
|
}
|
|
|
|
void zoom_near(Window *window){ // run for '+' key
|
|
correct_zoom_by_move(window, ZOOM_NEAR, NULL, NULL);
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void zoom_far(Window *window){ // run for '-' key
|
|
correct_zoom_by_move(window, ZOOM_FAR, NULL, NULL);
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
|
|
void zoom_selection(Window *window){ // function called after frame selection
|
|
double x0,y0, x,y, zX, zY, ZF;
|
|
get_sel_region(&x0, &y0, &x, &y);
|
|
zX = (double)window->drawingArea->allocation.width / abs(x-x0);
|
|
zY = (double)window->drawingArea->allocation.height / abs(y-y0);
|
|
ZF = (zX < zY) ? zX : zY;
|
|
x = (x + x0) / 2.;
|
|
y = (y + y0) / 2.;
|
|
correct_zoom_by_move(window, ZF, &x, &y);
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
|
|
void show_3D_terrain(Window *window){
|
|
double imX0, imY0, imX, imY;
|
|
double x0,y0, x,y;
|
|
get_sel_region(&imX0, &imY0, &imX, &imY);
|
|
conv_mouse_to_image_coords(imX0, imY0, &x0, &y0, window);
|
|
conv_mouse_to_image_coords(imX, imY, &x, &y, window);
|
|
Window *terra = init_window(window, GL3D_WINDOW);
|
|
terrain_3D(terra, x0,y0, x,y, FALSE);
|
|
}
|
|
|
|
void full_3D_terrain(Window *window){
|
|
Window *terra = init_window(window, GL3D_WINDOW);
|
|
terrain_3D(terra, 0,0, window->image->width,window->image->height, FALSE);
|
|
}
|
|
|
|
gboolean is_tracking = FALSE; // TRUE is cutting mode
|
|
gboolean zoom_frame = FALSE; // TRUE is zoom frame mode
|
|
gboolean select_3D = FALSE; // TRUE is 3D frame selection mode
|
|
/*
|
|
* Processing of mouse button press event
|
|
* 1. Main window
|
|
*/
|
|
gboolean press_main_mbtn(Window *window, GdkEventButton *event){
|
|
Context *c = window->context;
|
|
switch(event->button){
|
|
case 1: // Left button? Start cutting
|
|
// Redraw window to delete old garbage
|
|
if(!window->image->data) break;
|
|
switch(c->drawingMode){
|
|
case DRAW_TRACK:
|
|
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(window->graphWindow->LinLogMenu[isYlog(window)]), TRUE);
|
|
gtk_widget_show_all(window->graphWindow->window);
|
|
c->graphMode = GR_GRAPH;
|
|
if(event->state & GDK_CONTROL_MASK)
|
|
c->trackingMode = TRACK_DIAG;
|
|
else if(event->state & GDK_SHIFT_MASK)
|
|
c->trackingMode = TRACK_VERT;
|
|
else if(event->state & GDK_MOD1_MASK)
|
|
c->trackingMode = TRACK_HORIZ;
|
|
else
|
|
c->trackingMode = TRACK_ANY;
|
|
case DRAW_QUAD: // There's no break here and it's not an error!
|
|
is_tracking = TRUE;
|
|
do_tracking(event->x, event->y, TRUE, window);
|
|
break;
|
|
case DRAW_SELECTION:
|
|
if(window->image->imagetype == HOUGH){
|
|
double R, phi;
|
|
get_houg_line(window, event->x, event->y, &phi, &R);
|
|
gchar *text = g_strdup_printf("%s: R=%.0f, phi=%.1f",
|
|
_("Selected line"), R, phi);
|
|
set_status_text(StatusText, text, window);
|
|
g_free(text);
|
|
}
|
|
else
|
|
pickRegion(event->x, event->y);
|
|
break;
|
|
}
|
|
gdk_window_invalidate_rect(window->drawingArea->window,
|
|
&window->drawingArea->allocation, FALSE);
|
|
break;
|
|
case 2: // Middle button moves an picture
|
|
X0 = event->x; Y0 = event->y;
|
|
lX0 = window->move.x; lY0 = window->move.y;
|
|
break;
|
|
case 3:
|
|
break;
|
|
}
|
|
refresh_state(window);
|
|
return FALSE;
|
|
}
|
|
// 2. Auxiliary window
|
|
gboolean press_sub_mbtn(Window *window, GdkEventButton * event){
|
|
switch(event->button){
|
|
case 1:
|
|
is_tracking = graph_mouse_btn((int)event->x, window);
|
|
break;
|
|
case 2:
|
|
break;
|
|
case 3:
|
|
break;
|
|
}
|
|
refresh_state(window);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Reaction for button release
|
|
* 1. Main window
|
|
*/
|
|
gboolean release_main_mbtn(Window *window, GdkEventButton * event){
|
|
switch(event->button){
|
|
case 1:
|
|
// there was something selected by frame
|
|
if(is_tracking && window->context->drawingMode == DRAW_QUAD){
|
|
if(zoom_frame){ // It was a zoom selection
|
|
zoom_selection(window);
|
|
}else if(select_3D){
|
|
show_3D_terrain(window);
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
break;
|
|
case 3:
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// 2. Auxiliary window
|
|
gboolean release_sub_mbtn(Window *window, GdkEventButton * event){
|
|
switch(event->button){
|
|
case 1:
|
|
switch(window->context->graphMode){
|
|
case GR_GRAPH:
|
|
break;
|
|
case GR_HISTOGRAM:
|
|
gen_tres_texture(window->parent);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Functions of menus processing
|
|
*/
|
|
void show_hist(Window *window){ // 'h' in main window
|
|
window->context->graphMode = GR_HISTOGRAM;
|
|
show_histogram(window);
|
|
}
|
|
void spots_coords(Window *window){ // 'c'
|
|
get_spots_coords(window, window->image_transformed);
|
|
}
|
|
|
|
void set_spots_parameters(Window *window){ // 'alt+s'
|
|
GtkBuilder *builder;
|
|
GError *err = NULL;
|
|
GtkWidget *dialog, *btn;
|
|
void getval(GtkSpinButton *spin_button, int *val){
|
|
*val = gtk_spin_button_get_value_as_int(spin_button);
|
|
DBG("val = %d", *val);
|
|
}
|
|
void chk_tres_vals(GtkWidget *wnd){
|
|
GtkMessageDialog *dialog;
|
|
gchar *text;
|
|
gboolean W, H;
|
|
H = (Global->maxSpotH > Global->minSpotH);
|
|
W = (Global->maxSpotW > Global->minSpotW);
|
|
if(H && W){ // OK
|
|
gtk_widget_destroy(wnd);
|
|
return;
|
|
}
|
|
if(!(H || W))
|
|
text = _("Both max values are less than min");
|
|
else{
|
|
if(!H)
|
|
text = _("Max height value less than min");
|
|
else
|
|
text = _("Max width value less than min");
|
|
}
|
|
dialog = GTK_MESSAGE_DIALOG(gtk_message_dialog_new(NULL,
|
|
GTK_DIALOG_MODAL,
|
|
GTK_MESSAGE_ERROR,
|
|
GTK_BUTTONS_CLOSE,
|
|
text));
|
|
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(wnd));
|
|
gtk_dialog_run(GTK_DIALOG(dialog));
|
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
|
}
|
|
void conn_sig(gchar *object, int *val){
|
|
GtkAdjustment *adj;
|
|
GtkWidget *spin = GTK_WIDGET(gtk_builder_get_object(builder, object));
|
|
g_signal_connect(spin, "value-changed", G_CALLBACK(getval), val);
|
|
adj = (GtkAdjustment*) gtk_adjustment_new(*val, 1.0, 4000.0, 1.0, 0.0, 0.0);
|
|
gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(spin), adj);
|
|
}
|
|
builder = gtk_builder_new();
|
|
if(!gtk_builder_add_from_string(builder, ui, -1, &err)){
|
|
g_warning("%d, %s\n", err->code, err->message);
|
|
exit(-1);
|
|
}
|
|
dialog = GTK_WIDGET(gtk_builder_get_object(builder, "TresWindow"));
|
|
conn_sig("MinWidth", &Global->minSpotW);
|
|
conn_sig("MaxWidth", &Global->maxSpotW);
|
|
conn_sig("MinHeight", &Global->minSpotH);
|
|
conn_sig("MaxHeight", &Global->maxSpotH);
|
|
btn = GTK_WIDGET(gtk_builder_get_object(builder, "TresCancel"));
|
|
g_signal_connect_swapped(btn, "clicked",
|
|
G_CALLBACK(gtk_widget_destroy), dialog);
|
|
btn = GTK_WIDGET(gtk_builder_get_object(builder, "TresOK"));
|
|
g_signal_connect_swapped(btn, "clicked",
|
|
G_CALLBACK(chk_tres_vals), dialog);
|
|
run_modal_window(GTK_WINDOW(dialog), window);
|
|
}
|
|
|
|
void circle_params(Window *window){ // 'x'
|
|
get_circles_params(window, window->image_transformed);
|
|
}
|
|
void spot_ident(Window *window){ // 's'
|
|
window->context->visualMode |= SHOW_POTSELECT;
|
|
window->context->drawingMode = DRAW_SELECTION;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void save_spots(Window *window){
|
|
if(!window->spots){
|
|
g_err(_("No recognized spots"));
|
|
return;
|
|
}
|
|
GtkFileChooser *dialog;
|
|
gchar *filename = NULL, *tmp = NULL;
|
|
gint response;
|
|
dialog = GTK_FILE_CHOOSER(
|
|
gtk_file_chooser_dialog_new("Save File", NULL,
|
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
|
NULL));
|
|
if(saved_path)
|
|
gtk_file_chooser_set_current_folder(dialog, saved_path);
|
|
filename = g_strdup_printf("%s", window->image->filename);
|
|
DBG("saved path: %s; filename: %s", saved_path, filename);
|
|
if( (tmp = strrchr(filename, '.')) ) *tmp = 0;
|
|
tmp = g_strdup_printf("%s.spotlist", filename);
|
|
gtk_file_chooser_set_current_name(dialog, tmp);
|
|
g_free(tmp);
|
|
g_free(filename); filename = NULL;
|
|
gtk_file_chooser_set_do_overwrite_confirmation(dialog, TRUE);
|
|
response = run_modal_dialog(GTK_DIALOG(dialog), window);
|
|
if(response == GTK_RESPONSE_ACCEPT){
|
|
filename = gtk_file_chooser_get_filename(dialog);
|
|
}
|
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
|
if(!filename) return;
|
|
spots_save(window->spots, filename);
|
|
g_print("%s saved", filename);
|
|
tmp = g_path_get_basename(filename);
|
|
g_free(filename);
|
|
filename = g_strdup_printf("%s saved", tmp);
|
|
set_status_text(StatusText, filename, window);
|
|
g_free(filename); g_free(tmp);
|
|
}
|
|
void draw_tracks(Window *window){ // 't'
|
|
window->context->drawingMode = DRAW_TRACK;
|
|
window->context->visualMode &= ~SHOW_POTSELECT;
|
|
}
|
|
void zoom_restore(Window *window){ // '0'
|
|
window->Zoom = 1.;
|
|
window->move.x = 0.;
|
|
window->move.y = 0.;
|
|
window->Zangle = 0.;
|
|
window->Xangle = 0.;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void zooom_qframe(Window *window){ // 'z'
|
|
window->context->drawingMode = DRAW_QUAD;
|
|
zoom_frame = TRUE;
|
|
}
|
|
void select_terrain(Window *window){ // '3'
|
|
window->context->drawingMode = DRAW_QUAD;
|
|
select_3D = TRUE;
|
|
}
|
|
void filter(Window *window){ // 'f'
|
|
/* Filter *f;
|
|
INIT(f, Filter);*/
|
|
/* f->FilterType = MEDIAN;
|
|
f->sx=f->sy=9.;
|
|
f->w = f->h = 3;
|
|
filter_image(window, f);*/
|
|
/* f->FilterType = SIMPLEGRAD;
|
|
filter_image(window, f);
|
|
*/
|
|
find_contours(window, 16, LOG);
|
|
/* f->FilterType = STEP;
|
|
f->w = 16;
|
|
f->h = LOG;
|
|
filter_image(window, f);*/
|
|
/*f->FilterType = LAPGAUSS;
|
|
f->w = f->h = 256;
|
|
f->sx = f->sy = 5.f;
|
|
filter_image(window, f);*/
|
|
}
|
|
|
|
/*
|
|
* Processing of a key pressing events
|
|
* 1. Main window
|
|
*/
|
|
gboolean press_main_key(Window *window, GdkEventKey * event){
|
|
//FNAME();
|
|
gboolean ret = TRUE;
|
|
if(event->keyval == GDK_Escape){
|
|
if(zoom_frame || select_3D){
|
|
window->context->drawingMode = DRAW_TRACK;
|
|
zoom_frame = FALSE; // ESC cansels zoom
|
|
select_3D = FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
if(event->state & (GDK_CONTROL_MASK)){ // with ctrl
|
|
switch(event->keyval){
|
|
default: ret = FALSE;
|
|
}
|
|
}
|
|
else{
|
|
switch(event->keyval){
|
|
case GDK_Page_Up: case GDK_Up: case GDK_Left:
|
|
if(window->files.list_length > 1)
|
|
change_image(get_filename(PREVIOUS, window), window);
|
|
break;
|
|
case GDK_Page_Down: case GDK_Down: case GDK_Right:
|
|
if(window->files.list_length > 1)
|
|
change_image(get_filename(NEXT, window), window);
|
|
break;
|
|
case GDK_Home:
|
|
if(window->files.list_length > 1)
|
|
change_image(get_filename(FIRST, window), window);
|
|
break;
|
|
case GDK_End:
|
|
if(window->files.list_length > 1)
|
|
change_image(get_filename(LAST, window), window);
|
|
break;
|
|
default: ret = FALSE;
|
|
}
|
|
}
|
|
//refresh_state(window);
|
|
return ret;
|
|
}
|
|
// 2. Auxiliary window
|
|
/*
|
|
gboolean press_sub_key(Window *window, GdkEventKey * event){
|
|
//FNAME();
|
|
gboolean ret = TRUE;
|
|
switch(event->keyval){
|
|
default: ret = FALSE;
|
|
}
|
|
return ret;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
gboolean release_key(GtkWidget * none, GdkEventKey * event){
|
|
//DBG("Release key %d\n", event->keyval);
|
|
return FALSE;
|
|
}*/
|
|
|
|
// Scroll
|
|
gboolean main_scroll(Window *window, GdkEventScroll *event){
|
|
gboolean ret = FALSE;
|
|
if(event->state & (GDK_CONTROL_MASK)){
|
|
switch(event->direction){
|
|
case GDK_SCROLL_UP:
|
|
zoom_far(window);
|
|
ret = TRUE;
|
|
break;
|
|
case GDK_SCROLL_DOWN:
|
|
zoom_near(window);
|
|
ret = TRUE;
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Mouse move events
|
|
* 1. Main window
|
|
*/
|
|
gboolean main_motion(Window *window, GdkEventMotion * event){
|
|
double x,y;
|
|
gchar buf[40];
|
|
conv_mouse_to_image_coords(event->x, event->y, &x, &y, window);
|
|
g_snprintf(buf, 39, "(%.1f, %.1f)", x, y);
|
|
set_status_text(StatusCoords, buf, window);
|
|
if(event->state & GDK_BUTTON1_MASK){
|
|
switch(window->context->drawingMode){
|
|
case DRAW_TRACK: // In tracking mode show track
|
|
case DRAW_QUAD: // the same in frame selection mode
|
|
if(is_tracking) do_tracking(event->x, event->y, FALSE, window);
|
|
break;
|
|
}
|
|
}
|
|
else if(event->state & GDK_BUTTON2_MASK){
|
|
window->move.x = lX0 + (event->x - X0) * window->Daspect;
|
|
window->move.y = lY0 + (Y0 - event->y) * window->Daspect;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
else if(event->state & GDK_BUTTON3_MASK){
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// 2. Auxiliary window
|
|
gboolean sub_motion(Window *window, GdkEventMotion * event){
|
|
double x = event->x / xScale;
|
|
double y = gYmax - event->y/yScale;
|
|
double xx, yy;
|
|
gchar buf[40];
|
|
get_image_crds(x, &xx, &yy);
|
|
if(isYlog(window)) y = exp(y);
|
|
g_snprintf(buf, 39, "(%.3f, %.3f) I(%.1f, %.1f)", x, y, xx, yy);
|
|
set_status_text(StatusCoords, buf, window);
|
|
if(event->state & GDK_BUTTON1_MASK){
|
|
if(is_tracking) graph_mouse_btn((int)event->x, window);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// 3. OpenGL window
|
|
void open3D(Window *window){
|
|
terrain_3D(window, 0.,0.,0.,0., TRUE); // Show open dialog & load new picture
|
|
}
|
|
void rotXp(Window *window){
|
|
window->Xangle += key_acceleration;
|
|
if(window->Xangle > 360.) window->Xangle -= 360.;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void rotXm(Window *window){
|
|
window->Xangle -= key_acceleration;
|
|
if(window->Xangle < 0.) window->Xangle += 360.;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void rotZp(Window *window){
|
|
window->Zangle += key_acceleration;
|
|
if(window->Zangle > 360.) window->Zangle -= 360.;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void rotZm(Window *window){
|
|
window->Zangle -= key_acceleration;
|
|
if(window->Zangle < 0.) window->Zangle += 360.;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void moveXp(Window *window){
|
|
window->move.x += key_acceleration;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void moveXm(Window *window){
|
|
window->move.x -= key_acceleration;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void moveYp(Window *window){
|
|
window->move.y += key_acceleration;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void moveYm(Window *window){
|
|
window->move.y -= key_acceleration;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void game_move(Window *window, double where){
|
|
double lx, ly, lz, za = window->Zangle, xa = window->Xangle;
|
|
lx = cos(za)*sin(xa);
|
|
ly = -sin(za);
|
|
lz = -cos(za)*cos(xa);
|
|
double delta = where * key_acceleration;
|
|
window->move.x += delta*lx;
|
|
window->move.y += delta*ly;
|
|
window->Zoom += delta*lz/window->image->height;
|
|
}
|
|
void moveZp(Window *window){
|
|
if(window->context->drawingMode == GAME_MODE)
|
|
game_move(window, 1.);
|
|
else
|
|
window->Zoom *= 1.1;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void moveZm(Window *window){
|
|
if(window->context->drawingMode == GAME_MODE)
|
|
game_move(window, -1.);
|
|
else
|
|
window->Zoom /= 1.1;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
void game_mode(Window *window){
|
|
if(window->context->drawingMode == GAME_MODE){
|
|
window->context->drawingMode = DRAW_TRACK;
|
|
gdk_pointer_ungrab(GDK_CURRENT_TIME);
|
|
gtk_window_unfullscreen(GTK_WINDOW(window->window));
|
|
gdk_window_set_cursor(GDK_WINDOW(window->drawingArea->window), NULL);
|
|
}
|
|
else{
|
|
window->context->drawingMode = GAME_MODE;
|
|
gdk_pointer_grab(window->drawingArea->window, TRUE, 0,
|
|
window->drawingArea->window, NULL,
|
|
GDK_CURRENT_TIME);
|
|
gtk_window_fullscreen(GTK_WINDOW(window->window));
|
|
GdkCursor *cursor = gdk_cursor_new(GDK_BLANK_CURSOR);
|
|
gdk_window_set_cursor(GDK_WINDOW(window->drawingArea->window), cursor);
|
|
}
|
|
zoom_restore(window);
|
|
}
|
|
gfloat oldXbtn, oldYbtn;
|
|
gint oldXscreen, oldYscreen;
|
|
gboolean CursorWasMoved = TRUE;
|
|
gboolean press_ogl_mbtn(Window *window, GdkEventButton *event){
|
|
if(window->context->drawingMode == GAME_MODE &&
|
|
event->button == 1){
|
|
GdkDisplay *disp = gdk_display_get_default();
|
|
GdkScreen* screen = gdk_display_get_default_screen(disp);
|
|
oldXscreen = gdk_screen_get_width(screen) / 2;
|
|
oldYscreen = gdk_screen_get_height(screen) / 2;
|
|
gdk_display_warp_pointer(disp, screen,
|
|
oldXscreen, oldYscreen);
|
|
CursorWasMoved = TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
gboolean release_ogl_mbtn(Window *window __attribute__((unused)),
|
|
GdkEventButton *event __attribute__((unused))){
|
|
return FALSE;
|
|
}
|
|
/*
|
|
* Move mouse in 3D mode
|
|
* !!! In game mode angles measures in radians, not degrees !!!
|
|
*/
|
|
gboolean ogl_motion(Window *window, GdkEventMotion * event){
|
|
if(window->context->drawingMode == GAME_MODE
|
|
&& event->state & GDK_BUTTON1_MASK){
|
|
if(CursorWasMoved){
|
|
CursorWasMoved = FALSE;
|
|
oldXbtn = event->x;
|
|
oldYbtn = event->y;
|
|
return FALSE;
|
|
}
|
|
window->Xangle += (event->x - oldXbtn)/1000.;
|
|
window->Zangle += (event->y - oldYbtn)/1000.;
|
|
GdkDisplay *disp = gdk_display_get_default();
|
|
gdk_display_warp_pointer(disp, gdk_display_get_default_screen(disp),
|
|
oldXscreen, oldYscreen);
|
|
CursorWasMoved = TRUE;
|
|
force_redraw(window->drawingArea);
|
|
}
|
|
return FALSE;
|
|
}
|
|
gboolean reset_accel(){
|
|
key_acceleration = 1.;
|
|
return FALSE;
|
|
}
|
|
gboolean press_ogl_key(Window *window, GdkEventKey * event){
|
|
static gint tag = 0;
|
|
if(tag) gtk_timeout_remove(tag);
|
|
tag = gtk_timeout_add(100, reset_accel, NULL);
|
|
key_acceleration += 1.;
|
|
switch(event->keyval){
|
|
case GDK_Left:
|
|
moveXp(window); // Move left - picture moves to the right
|
|
break;
|
|
case GDK_Right:
|
|
moveXm(window);
|
|
break;
|
|
case GDK_Up:
|
|
moveZp(window);
|
|
break;
|
|
case GDK_Down:
|
|
moveZm(window);
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
gboolean release_ogl_key(Window *window __attribute__((unused)),
|
|
GdkEventKey *event __attribute__((unused))){
|
|
return FALSE;
|
|
}
|
|
gboolean ogl_scroll(Window *window __attribute__((unused)),
|
|
GdkEventScroll *event __attribute__((unused))){
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Redefine rulers limits, x0 & xm are the limits of horizontal ruler
|
|
* y0 & ym - vertical
|
|
* hrule, vrule - appropriate rulers
|
|
*/
|
|
void set_rules(double x0, double y0, double xm, double ym,
|
|
GtkWidget *hrule, GtkWidget *vrule){
|
|
double yy = (y0 < 0.) ? 0 : y0;
|
|
gtk_ruler_set_range(GTK_RULER (hrule), x0, xm, 0., xm);
|
|
gtk_ruler_set_range(GTK_RULER (vrule), y0, ym, yy, ym);
|
|
}
|
|
void set_Drulers(double x0, double y0, double xm, double ym, Window *window){
|
|
set_rules(-x0, ym, xm, -y0, window->hRule, window->vRule);
|
|
}
|
|
void set_Grulers(double y0, double xm, double ym, Window *window){
|
|
//DBG("gXm=%g, gY0=%g, gYm=%g\n", xm, y0, ym);
|
|
set_rules(0., ym, xm, y0, window->hRule, window->vRule);
|
|
}
|
|
|
|
void destroy_window(Window* window){
|
|
FNAME();
|
|
if(!window) return;
|
|
if(window->id == GRAPH_WINDOW)
|
|
window->parent->graphWindow = NULL;
|
|
else{
|
|
destroy_window(window->graphWindow);
|
|
_FREE(window->context);
|
|
}
|
|
if(window->id == GL3D_WINDOW)
|
|
freeGLmemory(window);
|
|
if(window->image){
|
|
if(window->id == GL3D_WINDOW){
|
|
window->image->cLevels = NULL;
|
|
}
|
|
destroy_image(window->image);
|
|
}
|
|
if(window->image_transformed)
|
|
destroy_image(window->image_transformed);
|
|
_FREE(window->texture);
|
|
spots_free(&window->spots);
|
|
free_filelist(window);
|
|
gtk_widget_destroy(window->window);
|
|
free(window);
|
|
}
|
|
|
|
/*
|
|
* Signal handler structure definition
|
|
* array Sighandler[] should end by NULL element
|
|
*/
|
|
typedef struct{
|
|
gchar *elementName; // name of element
|
|
gchar *sigName; // signal name
|
|
GCallback sigHandler; // function - handler, a kind of void f(Window* w)
|
|
} Sighandler;
|
|
// Signals for graph window
|
|
Sighandler graphSigHandler[] = {
|
|
{"graphCloseMenuItem", "activate", G_CALLBACK(close_subwindow)},
|
|
{"graphGaussMenuItem", "activate", G_CALLBACK(fit_gaussian)},
|
|
{"graphLinMenuItem", "activate", G_CALLBACK(lin_scale)},
|
|
{"graphLogMenuItem", "activate", G_CALLBACK(log_scale)},
|
|
{"graphArea", "expose-event", G_CALLBACK(Gexpose)},
|
|
{"graphArea", "configure-event", G_CALLBACK(Gconfigure)},
|
|
{NULL, "button-press-event", G_CALLBACK(press_sub_mbtn)},
|
|
{NULL, "button-release-event", G_CALLBACK(release_sub_mbtn)},
|
|
{NULL, "motion-notify-event", G_CALLBACK(sub_motion)},
|
|
// {NULL, "key-press-event", G_CALLBACK(press_sub_key)},
|
|
{NULL, NULL, NULL}
|
|
};
|
|
// Signals for window with picture
|
|
Sighandler mainSigHandler[] = {
|
|
{"mainOpenMenuItem", "activate", G_CALLBACK(open_file)},
|
|
{"mainSaveAsMenuItem", "activate", G_CALLBACK(save_as)},
|
|
{"mainOpenInNewMenuItem", "activate", G_CALLBACK(open_in_new)},
|
|
{"mainOpenIn3DMenuItem", "activate", G_CALLBACK(open_in_3D)},
|
|
{"mainHistMenuItem", "activate", G_CALLBACK(show_hist)},
|
|
{"mainHeadersMenuItem", "activate", G_CALLBACK(edit_headers)},
|
|
{"mainSpotsidentMenuItem", "activate", G_CALLBACK(spot_ident)},
|
|
{"mainSaveSpotsMenuItem", "activate", G_CALLBACK(save_spots)},
|
|
{"mainTrackMenuItem", "activate", G_CALLBACK(draw_tracks)},
|
|
{"main3DviewFrameMenuItem", "activate", G_CALLBACK(select_terrain)},
|
|
{"main3DviewFullMenuItem", "activate", G_CALLBACK(full_3D_terrain)},
|
|
{"mainZoomframeMenuItem", "activate", G_CALLBACK(zooom_qframe)},
|
|
{"mainZoomrestoreMenuItem", "activate", G_CALLBACK(zoom_restore)},
|
|
{"mainZoomnearMenuItem", "activate", G_CALLBACK(zoom_near)},
|
|
{"mainZoomfarMenuItem", "activate", G_CALLBACK(zoom_far)},
|
|
{"mainSpotsParamMenuItem", "activate", G_CALLBACK(set_spots_parameters)},
|
|
{"mainFindSpotsMenuItem", "activate", G_CALLBACK(spots_coords)},
|
|
{"mainHartmannMenuItem", "activate", G_CALLBACK(hartmann_spots)},
|
|
{"mainCirclesMenuItem", "activate", G_CALLBACK(circle_params)},
|
|
{"mainHoughMenuItem", "activate", G_CALLBACK(hough_lines)},
|
|
{"mainFilterMenuItem", "activate", G_CALLBACK(filter)},
|
|
// {"", "activate", G_CALLBACK()},
|
|
{NULL, "button-press-event", G_CALLBACK(press_main_mbtn)},
|
|
{NULL, "button-release-event", G_CALLBACK(release_main_mbtn)},
|
|
{NULL, "motion-notify-event", G_CALLBACK(main_motion)},
|
|
{NULL, "key-press-event", G_CALLBACK(press_main_key)},
|
|
{NULL, "scroll-event", G_CALLBACK(main_scroll)},
|
|
{NULL, NULL, NULL}
|
|
};
|
|
// Signals for 3D window
|
|
Sighandler oglSigHandler[] = {
|
|
{"oglOpenMenuItem", "activate", G_CALLBACK(open3D)},
|
|
{"oglCloseMenuItem", "activate", G_CALLBACK(destroy_window)},
|
|
{"oglZoomrestoreMenuItem", "activate", G_CALLBACK(zoom_restore)},
|
|
{"oglXAplusMenuItem", "activate", G_CALLBACK(rotXp)},
|
|
{"oglXAminusMenuItem", "activate", G_CALLBACK(rotXm)},
|
|
{"oglZAplusMenuItem", "activate", G_CALLBACK(rotZp)},
|
|
{"oglZAminusMenuItem", "activate", G_CALLBACK(rotZm)},
|
|
{"oglXplusMenuItem", "activate", G_CALLBACK(moveXp)},
|
|
{"oglXminusMenuItem", "activate", G_CALLBACK(moveXm)},
|
|
{"oglYplusMenuItem", "activate", G_CALLBACK(moveYp)},
|
|
{"oglYminusMenuItem", "activate", G_CALLBACK(moveYm)},
|
|
{"oglZplusMenuItem", "activate", G_CALLBACK(moveZp)},
|
|
{"oglZminusMenuItem", "activate", G_CALLBACK(moveZm)},
|
|
{"oglGameModeMenuItem", "toggled", G_CALLBACK(game_mode)},
|
|
{NULL, "button-press-event", G_CALLBACK(press_ogl_mbtn)},
|
|
{NULL, "button-release-event", G_CALLBACK(release_ogl_mbtn)},
|
|
{NULL, "motion-notify-event", G_CALLBACK(ogl_motion)},
|
|
{NULL, "key-press-event", G_CALLBACK(press_ogl_key)},
|
|
{NULL, "key-release-event", G_CALLBACK(release_ogl_key)},
|
|
{NULL, "scroll-event", G_CALLBACK(ogl_scroll)},
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
inline GtkWidget *initA(gchar *prefix, GtkBuilder *builder){
|
|
gchar text[32];
|
|
g_sprintf(text, "%sArea", prefix);
|
|
GtkWidget *A = GTK_WIDGET(gtk_builder_get_object(builder, text));
|
|
gtk_widget_set_events(A, GDK_EXPOSURE_MASK |
|
|
GDK_BUTTON_PRESS_MASK |
|
|
GDK_POINTER_MOTION_MASK |
|
|
GDK_POINTER_MOTION_HINT_MASK|
|
|
GDK_BUTTON_RELEASE_MASK);
|
|
return A;
|
|
}
|
|
inline GtkWidget *initR(GtkWidget *area, gchar *name, GtkBuilder *builder){
|
|
GtkWidget *R = GTK_WIDGET(gtk_builder_get_object(builder, name));
|
|
g_signal_connect_swapped(area, "motion-notify-event",
|
|
G_CALLBACK(EVENT_METHOD(R, motion_notify_event)), R);
|
|
return R;
|
|
}
|
|
|
|
/*
|
|
* Window initialisation
|
|
* parent - parent window
|
|
* handlers - array of signal handlers
|
|
* prefix - window name prefix (main, graph, ...)
|
|
* nBlocks - amount of blocks in status bar
|
|
*/
|
|
Window *init_window(Window *parent, int winId){
|
|
FNAME();
|
|
guint i;
|
|
GtkBuilder *builder;
|
|
Window *window;
|
|
Sighandler *handlers = NULL;
|
|
gchar *prefix = NULL, *title = NULL;
|
|
guint nBlocks = 0;
|
|
GError *err = NULL;
|
|
gchar text[32];
|
|
builder = gtk_builder_new();
|
|
if(!gtk_builder_add_from_string(builder, ui, -1, &err)){
|
|
g_warning("%d, %s\n", err->code, err->message);
|
|
exit(-1);
|
|
}
|
|
INIT(window, Window);
|
|
window->id = winId;
|
|
if(parent){
|
|
window->parent = parent;
|
|
if(winId == GRAPH_WINDOW) // if window is graph context equal to parent's
|
|
window->context = parent->context;
|
|
else{
|
|
window->context = COPY(parent->context, Context);
|
|
window->context->visualMode = SHOW_ONLY_IMAGE;
|
|
}
|
|
}else
|
|
INIT(window->context, Context);
|
|
switch(winId){
|
|
case MAIN_WINDOW:
|
|
case OPENGL_WINDOW:
|
|
prefix = "main";
|
|
handlers = mainSigHandler;
|
|
nBlocks = 4;
|
|
break;
|
|
case GRAPH_WINDOW:
|
|
prefix = "graph";
|
|
handlers = graphSigHandler;
|
|
nBlocks = 3;
|
|
break;
|
|
case GL3D_WINDOW:
|
|
prefix = "ogl";
|
|
handlers = oglSigHandler;
|
|
break;
|
|
}
|
|
g_sprintf(text, "%sWindow", prefix);
|
|
window->window = GTK_WIDGET(gtk_builder_get_object(builder, text));
|
|
if(winId == MAIN_WINDOW || winId == OPENGL_WINDOW){
|
|
GtkAction *quit = GTK_ACTION(gtk_builder_get_object(builder, "mainQuitMenuItem"));
|
|
gtk_action_disconnect_accelerator(quit);
|
|
if(winId == MAIN_WINDOW){
|
|
g_signal_connect(quit, "activate", chk_quit, NULL);
|
|
gtk_action_set_icon_name(quit, "application-exit");
|
|
gtk_action_set_accel_path(quit, "<Main>/quit");
|
|
gtk_action_set_label(quit, _("Quit"));
|
|
}else{
|
|
gtk_action_set_accel_path(quit, "<Main>/close");
|
|
gtk_action_set_label(quit, _("Close"));
|
|
g_signal_connect_swapped(quit, "activate",
|
|
G_CALLBACK(destroy_window), window);
|
|
gtk_action_set_icon_name (quit, "window-close");
|
|
}
|
|
gtk_action_connect_accelerator(quit);
|
|
}
|
|
window->drawingArea = initA(prefix, builder);
|
|
if(winId != GL3D_WINDOW){
|
|
g_sprintf(text, "%sHruler", prefix);
|
|
window->hRule = initR(window->drawingArea, text, builder);
|
|
g_sprintf(text, "%sVruler", prefix);
|
|
window->vRule = initR(window->drawingArea, text, builder);
|
|
}
|
|
for(i = 0; i < nBlocks; i++){
|
|
g_sprintf(text, "%sStatusBar%d", prefix, i);
|
|
window->SBars[i] = GTK_ENTRY(gtk_builder_get_object(builder, text));
|
|
#ifdef EBUG
|
|
set_status_text(i, text, window);
|
|
#endif
|
|
}
|
|
window->statusBlocks = nBlocks;
|
|
if(winId != GRAPH_WINDOW){
|
|
INIT(window->image, IMAGE);
|
|
INIT(window->image_transformed, IMAGE);
|
|
initGl(window->drawingArea);
|
|
}else{
|
|
window->LinLogMenu[0] = GTK_RADIO_ACTION(gtk_builder_get_object(builder, "graphLinMenuItem"));
|
|
window->LinLogMenu[1] = GTK_RADIO_ACTION(gtk_builder_get_object(builder, "graphLogMenuItem"));
|
|
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(window->LinLogMenu[0]), TRUE);
|
|
}
|
|
while(handlers->sigHandler){
|
|
void *element;
|
|
if(handlers->elementName)
|
|
element = (void*)gtk_builder_get_object(builder, handlers->elementName);
|
|
else
|
|
element = (void*)window->window;
|
|
g_signal_connect_swapped(element, handlers->sigName,
|
|
handlers->sigHandler, window);
|
|
handlers++;
|
|
}
|
|
gtk_builder_connect_signals(builder, NULL);
|
|
g_object_unref(G_OBJECT(builder));
|
|
if(winId != GRAPH_WINDOW){
|
|
if(winId == MAIN_WINDOW || winId == OPENGL_WINDOW)
|
|
window->graphWindow = init_window(window, GRAPH_WINDOW);
|
|
gtk_widget_show_all(window->window);
|
|
}
|
|
window->Daspect = 1.; window->Zoom = 1.;
|
|
if(winId != OPENGL_WINDOW)
|
|
title = g_strdup_printf("%s (%s)", PRGNAME, prefix);
|
|
else
|
|
title = g_strdup_printf("%s", PRGNAME);
|
|
gtk_window_set_title(GTK_WINDOW(window->window), title);
|
|
g_free(title);
|
|
return window;
|
|
}
|
|
|
|
void init_main_window(int *argc, char ***argv){
|
|
gtk_init(argc, argv);
|
|
gtk_gl_init(argc, argv);
|
|
gtk_accel_map_add_entry("<Main>/close", GDK_w, GDK_CONTROL_MASK);
|
|
gtk_accel_map_add_entry("<Main>/quit", GDK_q, GDK_CONTROL_MASK);
|
|
mainWindow = init_window(NULL, MAIN_WINDOW);
|
|
}
|
|
|
|
/*
|
|
* *prefocal = TRUE if image is prefocal, FALSE otherwisw
|
|
* (Ask user, this function calls only if there's a problems to find VAL_F in FITS keys)
|
|
*/
|
|
void get_prefocal(Window *window, gboolean *prefocal){
|
|
double foc;
|
|
GtkWidget *dialog, *btn, *focus, *radio;
|
|
void ch_val_f(GtkEntry *e){
|
|
char *eptr = NULL;
|
|
errno = 0;
|
|
foc = strtod(gtk_entry_get_text(e), &eptr);
|
|
if((eptr && *eptr) || errno == ERANGE){
|
|
gchar *txt = g_strdup_printf("%g", foc);
|
|
gtk_entry_set_text(e, txt);
|
|
g_free(txt);
|
|
}
|
|
DBG("F: %g", foc);
|
|
}
|
|
void ch_vals(GtkWidget *w){
|
|
*prefocal = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio));
|
|
DBG("prefocal: %d\n", *prefocal);
|
|
window->image->val_f = foc;
|
|
gtk_widget_destroy(w);
|
|
}
|
|
GtkBuilder *builder;
|
|
GError *err = NULL;
|
|
gchar *text;
|
|
if(!window || !window->image) return;
|
|
if(window->image->val_f > 0.) text = g_strdup_printf("%.3f", window->image->val_f);
|
|
else text = g_strdup_printf("0.000");
|
|
builder = gtk_builder_new();
|
|
if(!gtk_builder_add_from_string(builder, ui, -1, &err)){
|
|
g_warning("%d, %s\n", err->code, err->message);
|
|
exit(-1);
|
|
}
|
|
dialog = GTK_WIDGET(gtk_builder_get_object(builder, "FocalWindow"));
|
|
radio = GTK_WIDGET(gtk_builder_get_object(builder, "FocalPostRadioBtn"));
|
|
focus = GTK_WIDGET(gtk_builder_get_object(builder, "FocFocusEntry"));
|
|
g_signal_connect(focus, "changed", G_CALLBACK(ch_val_f), NULL);
|
|
gtk_entry_set_text(GTK_ENTRY(focus), text);
|
|
btn = GTK_WIDGET(gtk_builder_get_object(builder, "FocalOK"));
|
|
g_signal_connect_swapped(btn, "clicked",
|
|
G_CALLBACK(ch_vals), dialog);
|
|
run_modal_dialog(GTK_DIALOG(dialog), window);
|
|
g_free(text);
|
|
}
|