📄 scope_vert.c
字号:
if (ignore_click != 0) { ignore_click = 0; return; } if (vert->chan_enabled[chan_num - 1] == 0 ) { /* channel is disabled, want to enable it */ if (ctrl_shm->state != IDLE) { /* acquisition in progress, 'push' the stop button */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctrl_usr-> rm_stop_button), TRUE); } count = 0; for (n = 0; n < 16; n++) { if (vert->chan_enabled[n]) { count++; } } if (count >= ctrl_shm->sample_len) { /* max number of channels already enabled */ /* force the button to pop back out */ ignore_click = 1; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE); title = "Too many channels"; msg = "You cannot add another channel.\n\n" "Either turn off one or more channels, or shorten\n" "the record length to allow for more channels"; dialog_generic_msg(ctrl_usr->main_win, title, msg, "OK", NULL, NULL, NULL); return; } if (chan->name == NULL) { /* need to assign a source */ if (dialog_select_source(chan_num) != TRUE) { /* user failed to assign a source */ /* force the button to pop back out */ ignore_click = 1; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE); return; } } vert->chan_enabled[chan_num - 1] = 1; } else { /* channel was already enabled, user wants to select it */ /* button should stay down, so we force it */ ignore_click = 1; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); } if (vert->selected != chan_num) { /* make chan_num the selected channel */ vert->selected = chan_num; channel_changed(); }}static void channel_off_button(GtkWidget * widget, gpointer gdata){ scope_vert_t *vert; int chan_num; vert = &(ctrl_usr->vert); chan_num = vert->selected; set_channel_off(chan_num); }static void change_source_button(GtkWidget * widget, gpointer gdata){ int chan_num; chan_num = ctrl_usr->vert.selected; if ((chan_num < 1) || (chan_num > 16)) { return; } if (ctrl_shm->state != IDLE) { /* acquisition in progress, 'push' the stop button */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctrl_usr-> rm_stop_button), TRUE); } invalidate_channel(chan_num); dialog_select_source(chan_num); channel_changed();}static gboolean dialog_select_source(int chan_num){ scope_vert_t *vert; scope_chan_t *chan; dialog_generic_t dialog; gchar *title, msg[BUFLEN]; int next, n, initial_page, row, initial_row, max_row; gchar *tab_label_text[3], *name; GtkWidget *hbox, *label, *notebk, *button; GtkAdjustment *adj; hal_pin_t *pin; hal_sig_t *sig; hal_param_t *param; vert = &(ctrl_usr->vert); chan = &(ctrl_usr->chan[chan_num - 1]); title = "Select Channel Source"; snprintf(msg, BUFLEN - 1, "Select a pin, signal, or parameter\n" "as the source for channel %d.", chan_num); /* create dialog window, disable resizing */ dialog.retval = 0; dialog.window = gtk_dialog_new(); dialog.app_data = &chan_num; /* set initial height of window */ gtk_widget_set_usize(GTK_WIDGET(dialog.window), -2, 300); /* allow user to grow but not shrink the window */ gtk_window_set_policy(GTK_WINDOW(dialog.window), FALSE, TRUE, FALSE); /* window should appear in center of screen */ gtk_window_set_position(GTK_WINDOW(dialog.window), GTK_WIN_POS_CENTER); /* set title */ gtk_window_set_title(GTK_WINDOW(dialog.window), title); /* display message */ label = gtk_label_new(msg); gtk_misc_set_padding(GTK_MISC(label), 15, 5); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->vbox), label, FALSE, TRUE, 0); /* a separator */ gtk_hseparator_new_in_box(GTK_DIALOG(dialog.window)->vbox, 0); /* create a notebook to hold pin, signal, and parameter lists */ notebk = gtk_notebook_new(); /* add the notebook to the dialog */ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->vbox), notebk, TRUE, TRUE, 0); /* set overall notebook parameters */ gtk_notebook_set_homogeneous_tabs(GTK_NOTEBOOK(notebk), TRUE); /* text for tab labels */ tab_label_text[0] = "Pins"; tab_label_text[1] = "Signals"; tab_label_text[2] = "Parameters"; /* loop to create three identical tabs */ for (n = 0; n < 3; n++) { /* Create a scrolled window to display the list */ vert->windows[n] = gtk_scrolled_window_new(NULL, NULL); vert->adjs[n] = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(vert->windows[n])); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vert->windows[n]), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_widget_show(vert->windows[n]); /* create a list to hold the data */ vert->lists[n] = gtk_clist_new(1); /* set up a callback for when the user selects a line */ gtk_signal_connect(GTK_OBJECT(vert->lists[n]), "select_row", GTK_SIGNAL_FUNC(selection_made), &dialog); /* It isn't necessary to shadow the border, but it looks nice :) */ gtk_clist_set_shadow_type(GTK_CLIST(vert->lists[n]), GTK_SHADOW_OUT); /* set list for single selection only */ gtk_clist_set_selection_mode(GTK_CLIST(vert->lists[n]), GTK_SELECTION_BROWSE); /* put the list into the scrolled window */ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW (vert->windows[n]), vert->lists[n]); /* another way to do it - not sure which is better gtk_container_add(GTK_CONTAINER(vert->windows[n]), vert->lists[n]); */ gtk_widget_show(vert->lists[n]); /* create a box for the tab label */ hbox = gtk_hbox_new(TRUE, 0); /* create a label for the page */ gtk_label_new_in_box(tab_label_text[n], hbox, TRUE, TRUE, 0); gtk_widget_show(hbox); /* add page to the notebook */ gtk_notebook_append_page(GTK_NOTEBOOK(notebk), vert->windows[n], hbox); /* set tab attributes */ gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(notebk), hbox, TRUE, TRUE, GTK_PACK_START); } /* determine initial page: pin, signal, or parameter */ if (( chan->data_source_type >= 0 ) && ( chan->data_source_type <= 2 )) { initial_page = chan->data_source_type; gtk_notebook_set_page(GTK_NOTEBOOK(notebk), initial_page); } else { initial_page = -1; gtk_notebook_set_page(GTK_NOTEBOOK(notebk), 0); } gtk_widget_show(notebk); /* populate the pin, signal, and parameter lists */ gtk_clist_clear(GTK_CLIST(vert->lists[0])); gtk_clist_clear(GTK_CLIST(vert->lists[1])); gtk_clist_clear(GTK_CLIST(vert->lists[2])); rtapi_mutex_get(&(hal_data->mutex)); next = hal_data->pin_list_ptr; row = -1; initial_row = -1; max_row = -1; while (next != 0) { pin = SHMPTR(next); name = pin->name; row = gtk_clist_append(GTK_CLIST(vert->lists[0]), &name); if ( initial_page == 0 ) { if ( strcmp(name, chan->name) == 0 ) { initial_row = row; } max_row = row; } next = pin->next_ptr; } next = hal_data->sig_list_ptr; while (next != 0) { sig = SHMPTR(next); name = sig->name; row = gtk_clist_append(GTK_CLIST(vert->lists[1]), &name); if ( initial_page == 1 ) { if ( strcmp(name, chan->name) == 0 ) { initial_row = row; } max_row = row; } next = sig->next_ptr; } next = hal_data->param_list_ptr; while (next != 0) { param = SHMPTR(next); name = param->name; row = gtk_clist_append(GTK_CLIST(vert->lists[2]), &name); if ( initial_page == 2 ) { if ( strcmp(name, chan->name) == 0 ) { initial_row = row; } max_row = row; } next = param->next_ptr; } rtapi_mutex_give(&(hal_data->mutex)); if ( initial_row >= 0 ) { /* highlight the currently selected name */ gtk_clist_select_row(GTK_CLIST(vert->lists[initial_page]), initial_row, -1); /* set scrolling window to show the highlighted name */ /* FIXME - I can't seem to get this to work */ adj = vert->adjs[initial_page]; adj->value = adj->lower + (adj->upper - adj->lower)*((float)(initial_row)/(float)(max_row+1)); gtk_adjustment_value_changed(vert->adjs[initial_page]); } /* set up a callback function when the window is destroyed */ gtk_signal_connect(GTK_OBJECT(dialog.window), "destroy", GTK_SIGNAL_FUNC(dialog_generic_destroyed), &dialog); /* make Cancel button */ button = gtk_button_new_with_label("Cancel"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->action_area), button, TRUE, TRUE, 4); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dialog_generic_button2), &dialog); /* make window transient and modal */ gtk_window_set_transient_for(GTK_WINDOW(dialog.window), GTK_WINDOW(ctrl_usr->main_win)); gtk_window_set_modal(GTK_WINDOW(dialog.window), TRUE); gtk_widget_show_all(dialog.window); gtk_main(); /* we get here when the user makes a selection, hits Cancel, or closes the window */ vert->lists[0] = NULL; vert->lists[1] = NULL; vert->lists[2] = NULL; if ((dialog.retval == 0) || (dialog.retval == 2)) { /* user either closed dialog, or hit cancel */ return FALSE; } /* user made a selection */ channel_changed(); return TRUE;}/* If we come here, then the user has selected a row in the list. */static void selection_made(GtkWidget * clist, gint row, gint column, GdkEventButton * event, dialog_generic_t * dptr){ scope_vert_t *vert; GdkEventType type; gint n, listnum; gchar *name; int rv, chan_num; if ((event == NULL) || (clist == NULL)) { /* We get spurious events when the lists are populated I don't know why. If either clist or event is null, it's a bad one! */ return; } type = event->type; if (type != 4) { /* We also get bad callbacks if you drag the mouse across the list with the button held down. They can be distinguished because their event type is 3, not 4. */ return; } /* If we get here, it should be a valid selection */ vert = &(ctrl_usr->vert); chan_num = *((int *)(dptr->app_data)); /* figure out which notebook tab it was */ listnum = -1; for (n = 0; n < 3; n++) { if (clist == vert->lists[n]) { listnum = n; } } /* Get the text from the list */ gtk_clist_get_text(GTK_CLIST(clist), row, column, &name); /* try to set up the new source */ rv = set_channel_source(chan_num, listnum, name); if ( rv == 0 ) { /* set return value of dialog to indicate success */ dptr->retval = 1; } else { /* new source invalid, return as if user hit cancel */ dptr->retval = 2; } /* destroy window to cause dialog_generic_destroyed() to be called */ gtk_widget_destroy(dptr->window); return;} static void channel_changed(void){ scope_vert_t *vert; scope_chan_t *chan; GtkAdjustment *adj; gchar *name; gchar buf1[BUFLEN + 1], buf2[BUFLEN + 1]; vert = &(ctrl_usr->vert); if ((vert->selected < 1) || (vert->selected > 16)) { gtk_label_set_text_if(vert->scale_label, "----"); gtk_label_set_text_if(vert->chan_num_label, "--"); gtk_label_set_text_if(vert->source_name_label, "------"); request_display_refresh(1); return; } chan = &(ctrl_usr->chan[vert->selected - 1]); /* set position slider based on new channel */ gtk_adjustment_set_value(GTK_ADJUSTMENT(vert->pos_adj), chan->position * VERT_POS_RESOLUTION); /* set scale slider based on new channel */ adj = GTK_ADJUSTMENT(vert->scale_adj); adj->lower = chan->min_index; adj->upper = chan->max_index; adj->value = chan->scale_index; gtk_adjustment_changed(adj); gtk_adjustment_value_changed(adj); /* update the channel number and name display */ snprintf(buf1, BUFLEN, "%2d", vert->selected); name = chan->name; gtk_label_set_text_if(vert->chan_num_label, buf1); gtk_label_set_text_if(vert->source_name_label, name); /* update the offset display */ if (chan->data_type == HAL_BIT) { snprintf(buf1, BUFLEN, "----"); } else { format_signal_value(buf1, BUFLEN, chan->vert_offset); } snprintf(buf2, BUFLEN, "Offset\n%s", buf1); gtk_label_set_text_if(vert->offset_label, buf2); request_display_refresh(1);}static void format_scale_value(char *buf, int buflen, float value){ char *units; char symbols[] = "pnum KMGT"; if (value < 0.9e-12) { /* less than pico units, shouldn't happen */ snprintf(buf, buflen, "tiny"); return; } if (value > 1.1e+12) { /* greater than tera-units, shouldn't happen */ snprintf(buf, buflen, "huge"); return; } units = &(symbols[4]); while (value < 1.0) { value *= 1000.0; units--; } while (value >= 999.99) { value *= 0.001; units++; } snprintf(buf, buflen, "%0.0f%c/div", value, *units);}static void write_chan_config(FILE *fp, scope_chan_t *chan){ if ( chan->data_source_type == 0 ) { // pin fprintf(fp, "PIN %s\n", chan->name); } else if ( chan->data_source_type == 1 ) { // signal fprintf(fp, "SIG %s\n", chan->name); } else if ( chan->data_source_type == 2 ) { // pin fprintf(fp, "PARAM %s\n", chan->name); } else { // not configured return; } fprintf(fp, "VSCALE %d\n", chan->scale_index); fprintf(fp, "VPOS %f\n", chan->position); fprintf(fp, "VOFF %e\n", chan->vert_offset);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -