📄 scope_vert.c
字号:
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, must restart it */ prepare_scope_restart(); } invalidate_channel(chan_num); dialog_select_source(chan_num); channel_changed();}static char search_target[HAL_NAME_LEN+1];static guint32 search_time = 0;static int search_row = -1;#define SEARCH_RESET_TIME 1000 /* ms */static void selection_made_common(GtkWidget *clist, gint row, dialog_generic_t *dptr) { gint n, listnum; gchar *name; int rv, chan_num; scope_vert_t *vert; /* 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, 0, &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 gboolean search_for_entry(GtkWidget *widget, GdkEventKey *event, dialog_generic_t *dptr){ GtkCList *clist = GTK_CLIST(widget); int z, wrapped; if(event->keyval == GDK_Return) { selection_made_common(widget, clist->focus_row, dptr); } if(!isprint(event->string[0])) { strcpy(search_target, ""); search_row = clist->focus_row; return 0; } if(event->time - search_time > SEARCH_RESET_TIME) { strcpy(search_target, ""); search_row = clist->focus_row; } search_time = event->time; if(strcmp(event->string, " ") == 0) { char *text; search_row = search_row + 1; if(!gtk_clist_get_text(clist, search_row, 0, &text)) search_row = 0; printf("next search: %d\n", search_row); } else { strcat(search_target, event->string); } for(z = search_row, wrapped=0; z != search_row || !wrapped; z ++) { char *text; printf("search: %d (wrapped=%d)\n", z, wrapped); if(!gtk_clist_get_text(clist, z, 0, &text)) { if(wrapped) break; // wrapped second time (why?) z = 0; wrapped = 1; } if(strstr(text, search_target)) { double pos = (z+.5) / (clist->rows-1); if(pos > 1) pos = 1; GTK_CLIST_GET_CLASS(clist)->scroll_vertical(clist, GTK_SCROLL_JUMP, pos); gtk_clist_select_row(clist, z, 0); search_row = z; return 1; } } return 0;}static gboolean change_page(GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer user_data) { scope_vert_t *vert; vert = &(ctrl_usr->vert); if(page_num >= 0 && page_num < 3) gtk_widget_grab_focus(GTK_WIDGET(vert->lists[page_num])); return 0;}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); gtk_signal_connect(GTK_OBJECT(notebk), "switch-page", GTK_SIGNAL_FUNC(change_page), &dialog); /* 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); gtk_signal_connect(GTK_OBJECT(vert->lists[n]), "key-press-event", GTK_SIGNAL_FUNC(search_for_entry), &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 clicked a row in the list. */static void selection_made(GtkWidget * clist, gint row, gint column, GdkEventButton * event, dialog_generic_t * dptr){ GdkEventType type; 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; } selection_made_common(clist, row, dptr);}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 { if(chan->ac_offset) { snprintf(buf1, BUFLEN, "(AC)"); } 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);}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); if(chan->ac_offset) { fprintf(fp, "VAC %e\n", chan->vert_offset); } else { fprintf(fp, "VOFF %e\n", chan->vert_offset); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -