#include <iostream>
#include <gui/ScanDialog.h>
#include <gui/gtkutils.h>
std::string get_a_string(const std::string &title, const std::string &prompt);
enum {
VAR_COL,
NPTS_COL,
STEP_COL,
FROM_COL,
TO_COL,
TYPE_COL,
N_VAR_COL
};
static ScanVar get_var(GtkTreeModel *model,GtkTreeIter *row) {
int type;
double step;
double first,last;
gtk_tree_model_get(model,row,
TO_COL,&last,
STEP_COL,&step,
FROM_COL,&first,
TYPE_COL,&type,
-1
);
ScanVar var( (ScanVar::ScanType)(type),first,last,step,first );
return var;
}
gchar *ScanDialog::get_scan_name() {
GtkWidget *w = gtk_menu_get_active(GTK_MENU(GTK_OPTION_MENU(get_widget("comboScanList"))->menu));
gchar *scan_name=(gchar *)g_object_get_data(G_OBJECT(w),"scan");
if (scan_name==0)
return 0;
else
return g_strdup(scan_name);
}
gboolean ScanDialog::findTest(GtkTreeModel **m, GtkTreeIter *it, int *tp) {
gboolean found=FALSE;
GtkTreeView *cl;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean valid;
int type,type_selected;
if ( !current )
return found;
// Get type of selected test
cl = GTK_TREE_VIEW(get_widget("lstVariables"));
model = gtk_tree_view_get_model(cl);
gtk_tree_model_get(model,current,1,&type_selected,-1);
cl = GTK_TREE_VIEW(get_widget("clistScan"));
model = gtk_tree_view_get_model(cl);
if (model==0) {
*m = model;
*tp = type_selected;
return false;
}
valid= gtk_tree_model_get_iter_first(model, &iter);
while (valid) {
gtk_tree_model_get(model,&iter,TYPE_COL,&type,-1);
if (type==type_selected) {
found=TRUE;
break;
}
valid = gtk_tree_model_iter_next(model, &iter);
}
if (found) {
*m = model;
*it = iter;
}
*tp = type_selected;
return found;
}
ScanDialog::ScanDialog(int n, const ScanList &s)
: do_scan(false),_time(false),nevts(n),sc0(s),scl(s),current(NULL)
{
ScanList::iterator ip = scl.begin();
if (ip!=scl.end())
sc = ip->second;
}
void ScanDialog::auto_connect() {
SET_CONNECT( on_OK );
SET_CONNECT( on_Cancel );
SET_CONNECT( on_Help );
SET_CONNECT( on_SaveScan );
SET_CONNECT( on_AddScan );
SET_CONNECT( on_DeleteScan );
SET_CONNECT( on_Delete );
SET_CONNECT( on_Add );
SET_CONNECT( on_Up );
SET_CONNECT( on_Down );
SET_CONNECT( on_doScan );
SET_CONNECT( on_toggleBurst );
SET_CONNECT( on_toggleTime );
SET_CONNECT( on_Delay );
SET_CONNECT( on_Rate );
}
void ScanDialog::user_init() {
GtkListStore *store;
GtkTreeIter iter;
GtkTreeSelection *selection;
GtkTreeView *cl;
int i;
/**
* Number of events per scan
*/
int2entry("txtNevtPerPoint",nevts);
//---------------------------------------------------------------------
// Fill the lists and trees
//---------------------------------------------------------------------
// List of scan types
//---------------------------------------------------------------------
store = gtk_list_store_new (2,G_TYPE_STRING,G_TYPE_INT);
for (i=0;i<ScanVar::get_n_names();i++) {
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
0,const_cast<char *>(ScanVar::get_name(i).c_str()),
1,i,
-1);
}
cl = GTK_TREE_VIEW( get_widget("lstVariables") );
gtk_tree_view_set_model( cl, GTK_TREE_MODEL(store));
g_object_unref(store);
gtk_tree_view_insert_column_with_attributes (cl,-1,
"Test",
gtk_cell_renderer_text_new (),
"text",0,
NULL);
selection = gtk_tree_view_get_selection(cl);
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
g_signal_connect(G_OBJECT(selection),"changed",
G_CALLBACK(on_ScanType),
this);
//---------------------------------------------------------------------
// List of scan variables
//---------------------------------------------------------------------
cl = GTK_TREE_VIEW( get_widget("clistScan") );
store = gtk_list_store_new (N_VAR_COL,
G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_DOUBLE,
G_TYPE_DOUBLE,
G_TYPE_DOUBLE,
G_TYPE_INT);
gtk_tree_view_set_model( cl, GTK_TREE_MODEL(store));
g_object_unref(store);
gtk_tree_view_insert_column_with_attributes(cl,-1,
"Test",
gtk_cell_renderer_text_new (),
"text",
VAR_COL,
NULL);
gtk_tree_view_insert_column_with_attributes(cl,-1,
"n. points",
gtk_cell_renderer_text_new (),
"text",
NPTS_COL,
NULL);
gtk_tree_view_insert_column_with_attributes(cl,-1,
"step",
gtk_cell_renderer_text_new (),
"text",
STEP_COL,
NULL);
gtk_tree_view_insert_column_with_attributes(cl,-1,
"from",
gtk_cell_renderer_text_new (),
"text",
FROM_COL,
NULL);
gtk_tree_view_insert_column_with_attributes(cl,-1,
"to",
gtk_cell_renderer_text_new (),
"text",
TO_COL,
NULL);
selection = gtk_tree_view_get_selection(cl);
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
g_signal_connect(G_OBJECT(selection),"changed",G_CALLBACK(on_Select),this);
//---------------------------------------------------------------------
// List of available scans
//---------------------------------------------------------------------
const char *scn = sc.get_name().empty() ? 0 : sc.get_name().c_str();
updateScanList(scn);
//---------------------------------------------------------------------
// Scan button
//---------------------------------------------------------------------
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(get_widget("btnDoScan")),do_scan ? TRUE : FALSE);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(get_widget("btnBurst")),do_burst ? TRUE : FALSE);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(get_widget("btnTime")),_time ? TRUE : FALSE);
gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(get_widget("spinDelay")),
gtk_range_get_adjustment(GTK_RANGE(get_widget("scaleDelay")))
);
gtk_range_set_value(GTK_RANGE(get_widget("scaleDelay")),_delay);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(get_widget("spinRate")),_rate);
}
void ScanDialog::set_scan_point(const std::string &s) {
ScanList::iterator ip = scl.find(s);
if (ip!=scl.end())
sc = ip->second;
}
void ScanDialog::set_values(int npts, double stp, double frm, double to) {
block_signals();
int2entry("txtNpoints",npts);
double2entry("txtStep",stp);
double2entry("txtFrom",frm);
double2entry("txtTo",to);
unblock_signals();
}
void ScanDialog::get_values(int &npts, double &stp, double &frm, double &to) {
npts = entry2int("txtNpoints",10);
stp = entry2double("txtStep",1.);
frm = entry2double("txtFrom",0.);
to = entry2double("txtTo",10.);
}
/*
This is called when one variable is selected in the list of
variables. It will set current to the current selection. current is
used in other routines.
*/
void
ScanDialog::on_ScanType(GtkTreeSelection *selection, ScanDialog *sc)
{
GtkTreeModel *model;
GtkTreeIter iter;
int row;
if ( gtk_tree_selection_get_selected (selection, &model, &iter)) {
gtk_tree_model_get(model,&iter,1,&row,-1);
if ( sc->current )
gtk_tree_iter_free( sc->current );
sc->current = gtk_tree_iter_copy(&iter);
}
else
return;
std::vector<ScanVar>::iterator ip =
sc->sc.find_type( (ScanVar::ScanType)row );
if ( ip == sc->sc.end() ) {
ScanVar var( (ScanVar::ScanType)0,0.,10.,1.,0.);
sc->set_values(var.n_points(),var.step(),var.first(),var.last());
}
else {
sc->set_values(ip->n_points(),ip->step(),ip->first(),ip->last());
}
}
/*
This routine is called when a variable is selected in the
ScanVar description list.
*/
void
ScanDialog::on_Select(GtkTreeSelection *selection, ScanDialog *sc)
{
GtkTreeView *cl = GTK_TREE_VIEW(sc->get_widget("lstVariables"));
GtkTreeIter iter;
GtkTreeModel *model;
if ( gtk_tree_selection_get_selected (selection, &model, &iter)) {
int type;
gtk_tree_model_get(model,&iter,TYPE_COL,&type,-1);
// Loop on valid tests
GtkTreeIter it;
GtkTreeModel *m = gtk_tree_view_get_model(cl);
gboolean valid= gtk_tree_model_get_iter_first(m, &it);
while (valid) {
int tp;
gtk_tree_model_get(m,&it,1,&tp,-1);
if (tp==type) {
GtkTreeSelection *sel = gtk_tree_view_get_selection (cl);
gtk_tree_selection_select_iter (sel,&it);
break;
}
valid = gtk_tree_model_iter_next(m, &it);
}
}
}
/**
Called when we change the scan in the option menu
*/
void
ScanDialog::on_ScanChanged(GtkWidget *w, ScanDialog *sc)
{
// First save whatever we have in the current scan
ScanList::iterator ips = sc->scl.find(sc->sc.get_name());
if (ips==sc->scl.end()) {
std::cout << "Current scan is not in the scan list" << std::endl
<< "... this should not happen" << std::endl;
}
else {
sc->scl[sc->sc.get_name()] = sc->sc;
}
// now put the data of the selected one
gchar *sname = sc->get_scan_name();
if (!sname)
return;
std::string name = sname;
GtkTreeView *cl = GTK_TREE_VIEW( sc->get_widget("clistScan") );
GtkListStore *store;
GtkTreeIter iter;
g_free(sname);
store = gtk_list_store_new (N_VAR_COL,
G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_DOUBLE,
G_TYPE_DOUBLE,
G_TYPE_DOUBLE,
G_TYPE_INT);
ips = sc->scl.find( name );
if (ips==sc->scl.end())
return;
// copy the new one into the current scanpoint
sc->sc = ips->second;
// Add the variables in the scan
std::vector<ScanVar>::iterator ip;
for (ip=sc->sc.begin();ip!=sc->sc.end();++ip) {
gtk_list_store_append( store, &iter );
gtk_list_store_set (
store, &iter,
VAR_COL,const_cast<char *>(ScanVar::get_name(ip->type()).c_str()),
NPTS_COL,ip->n_points(),
STEP_COL,ip->step(),
FROM_COL,ip->first(),
TO_COL,ip->last(),
TYPE_COL,int(ip->type()),
-1);
}
gtk_tree_view_set_model( cl, GTK_TREE_MODEL(store));
g_object_unref(store);
// Now select the first variable in the list
cl = GTK_TREE_VIEW( sc->get_widget("lstVariables") );
GtkTreeSelection *selection = gtk_tree_view_get_selection(cl);
GtkTreeModel *model = gtk_tree_view_get_model(cl);
gtk_tree_model_get_iter_first(model,&iter);
gtk_tree_selection_select_iter(selection,&iter);
}
void
ScanDialog::updateScanList(const char *which)
{
GtkOptionMenu *combo = GTK_OPTION_MENU(get_widget("comboScanList"));
GtkWidget *item,*menu;
ScanList::iterator its;
int active=-1;
gtk_option_menu_remove_menu(combo);
menu = gtk_menu_new();
if (scl.empty()) {
active=0;
item = gtk_menu_item_new_with_label("None");
gtk_widget_show(item);
g_object_set_data(G_OBJECT(item),"scan",NULL);
gtk_menu_append(GTK_MENU(menu), item);
}
else {
active=-1;
int ipos=0;
for (its=scl.begin();its!=scl.end();++its,ipos++) {
const char *str = its->first.c_str();
item = gtk_menu_item_new_with_label(str);
gtk_widget_show(item);
if (which && !strcmp(str,which))
active=ipos;
g_object_set_data(G_OBJECT(item),"scan",
g_strdup(its->first.c_str())
);
gtk_menu_append(GTK_MENU(menu), item);
}
if (active<0)
active=0;
}
gtk_option_menu_set_menu(combo, menu);
if (active>=0) {
gtk_menu_set_active(GTK_MENU(menu),active);
gtk_option_menu_set_history(combo,active);
on_ScanChanged(menu,this);
}
g_signal_connect(G_OBJECT(menu),
"selection_done",
G_CALLBACK(on_ScanChanged),
this);
}
void ScanDialog::process_text(const std::string &s, GtkWidget *w) {
if ( s=="txtNevtPerPoint" ) {
nevts = entry2int("txtNevtPerPoint",10);
return;
}
int npts;
double step,first,last;
get_values(npts,step,first,last);
ScanVar var((ScanVar::ScanType)0,first,last,step);
set_values(var.n_points(),var.step(),var.first(),var.last());
}
void
ScanDialog::on_Help(GtkWidget *w, ScanDialog *sc)
{
gtk_help_display("scan-runs");
}
void
ScanDialog::on_OK(GtkWidget *w, ScanDialog *sc)
{
// ScanDialog::on_Cancel(w,sc);
}
void
ScanDialog::on_Cancel(GtkWidget *w, ScanDialog *sc)
{
// gtk_widget_hide( sc->get_main_window() );
// gtk_widget_destroy( sc->get_main_window() );
}
void
ScanDialog::on_SaveScan(GtkWidget *w, ScanDialog *sc)
{
gchar *name = sc->get_scan_name();
if (!name)
return;
sc->scl[name] = sc->sc;
g_free(name);
}
void
ScanDialog::on_AddScan(GtkWidget *w, ScanDialog *sc)
{
std::string out = get_a_string("New scan name",
"Type the name for the new scan");
sc->sc.set_name(out);
sc->scl[out] = sc->sc;
sc->updateScanList(out.c_str());
}
void
ScanDialog::on_DeleteScan(GtkWidget *w, ScanDialog *sc)
{
gchar *name = sc->get_scan_name();
if (!name)
return;
ScanList::iterator ip = sc->scl.find( name );
if (ip!=sc->scl.end())
sc->scl.erase(ip);
sc->updateScanList();
GtkOptionMenu *opm = GTK_OPTION_MENU(sc->get_widget("comboScanList"));
gtk_option_menu_set_history(opm,0);
ScanDialog::on_ScanChanged(opm->menu,sc);
g_free(name);
}
void
ScanDialog::on_Delete(GtkWidget *w, ScanDialog *sc)
{
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreeView *cl = GTK_TREE_VIEW( sc->get_widget("clistScan") );
GtkTreeSelection *selection = gtk_tree_view_get_selection(cl);
if ( gtk_tree_selection_get_selected (selection, &model, &iter)) {
int type;
gtk_tree_model_get(model,&iter,TYPE_COL,&type,-1);
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
sc->sc.remove_var( (ScanVar::ScanType)type );
}
}
void
ScanDialog::on_Add(GtkWidget *w, ScanDialog *sc)
{
GtkTreeModel *model;
GtkTreeIter iter;
int npts,type;
double step,from,to;
gboolean modify;
modify= sc->findTest(&model,&iter,&type);
sc->get_values(npts,step,from,to);
if (!modify) {
GtkTreeView *cl = GTK_TREE_VIEW(sc->get_widget("clistScan"));
model = gtk_tree_view_get_model(cl);
gtk_list_store_append (GTK_LIST_STORE(model), &iter);
gtk_list_store_set ( GTK_LIST_STORE(model), &iter,
VAR_COL,const_cast<char *>(ScanVar::get_name(type).c_str()),
NPTS_COL,npts,
STEP_COL,step,
FROM_COL,from,
TO_COL,to,
TYPE_COL,type,
-1);
}
else {
gtk_list_store_set(GTK_LIST_STORE(model),&iter,
NPTS_COL,npts,
STEP_COL,step,
FROM_COL,from,
TO_COL,to,
-1);
}
// Add the point into the copy of ScanPoint
ScanVar var ( (ScanVar::ScanType)(type),from,to,step,from );
sc->sc.add_var(var);
}
void
ScanDialog::on_Up(GtkWidget *w, ScanDialog *sc)
{
sc->moveRow(TRUE);
}
void
ScanDialog::on_Down(GtkWidget *w, ScanDialog *sc)
{
sc->moveRow(FALSE);
}
void
ScanDialog::on_doScan(GtkWidget *w, ScanDialog *sc)
{
sc->do_scan = sc->btn_active("btnDoScan");
}
void
ScanDialog::moveRow(gboolean up) {
GtkTreeView *cl = GTK_TREE_VIEW(get_widget("clistScan"));
GtkTreeModel *model;
GtkTreeIter iter,iter1;
GtkTreeSelection *selection = gtk_tree_view_get_selection(cl);
if ( gtk_tree_selection_get_selected (selection, &model, &iter)) {
GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
if ( up )
gtk_tree_path_prev (path);
else
gtk_tree_path_next (path);
if ( gtk_tree_model_get_iter (model,&iter1,path) ) {
gtk_list_store_swap( GTK_LIST_STORE(model),&iter,&iter1);
}
}
// Now order properly the vector
gboolean valid;
model = gtk_tree_view_get_model(cl);
valid= gtk_tree_model_get_iter_first(model, &iter);
sc.reset();
while (valid) {
ScanVar v = get_var(model,&iter);
sc.add_var( v );
valid = gtk_tree_model_iter_next(model, &iter);
}
}
std::string get_a_string(const std::string &title, const std::string &prompt)
{
std::string out;
GtkWidget *dialog = gtk_dialog_new_with_buttons (
title.c_str(),
(GtkWindow *)0,
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
NULL);
GtkWidget *vbox = gtk_vbox_new( FALSE, 2 );
gtk_container_set_border_width( GTK_CONTAINER(vbox), 5 );
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),vbox,FALSE,FALSE,0);
GtkWidget *label = gtk_label_new(prompt.c_str());
gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0);
GtkWidget *answ = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(vbox),answ,FALSE,FALSE,0);
gtk_button_box_set_layout( GTK_BUTTON_BOX(GTK_DIALOG(dialog)->action_area),
GTK_BUTTONBOX_END);
gtk_widget_show_all( dialog );
if ( gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_ACCEPT ) {
out = gtk_entry_get_text(GTK_ENTRY(answ));
}
gtk_widget_hide(dialog);
gtk_widget_destroy(dialog);
return out;
}
void ScanDialog::on_toggleTime(GtkWidget *w, ScanDialog *sc)
{
sc->_time = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
}
void ScanDialog::on_toggleBurst(GtkWidget *w, ScanDialog *sc)
{
sc->do_burst = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
}
void ScanDialog::on_Delay(GtkWidget *w, ScanDialog *sc)
{
sc->delay( gtk_range_get_value( GTK_RANGE(w) ) );
}
void ScanDialog::on_Rate(GtkWidget *w, ScanDialog *sc)
{
sc->rate( gtk_spin_button_get_value( GTK_SPIN_BUTTON(w) ) );
}