/**************************************************************************** * D_popup(back_colr, text_colr, div_colr, top, left, percent_per_line, options) * int back_colr ; color of window * int text_color ; color of text and border * int div_color ; color of item divider lines * int left, top ; pixle coordinates of top-left corner * (Coordinate system is 0,0 lower left, * 100,100 upper right) * int percent_per_line ; percent of entire window per line of text * char *options[] ; array of text showing options. * The first entry is a title, not an option * * The bottom-right coordinates are calculated based on the top-left coors., * the percent_per_line, the number of options, and the longest option text * length. If necessary, the window is moved to make sure it is inside * the screen. * * - Current screen contents are stashed away in the area. * - Area is blanked with the background color and fringed with the * text color. * - Options are drawn using the current font. * - User uses the mouse to choose the desired option. * - Area is restored with the original contents. * - Number of this option is returned to the calling program. ***************************************************************************/ #include #include #include #include #include #define Y_BORDER 5 #define X_BORDER 5 /*! * \brief pop-up menu * * This routine provides a pop-up type menu * on the graphics screen. The bcolor specifies the background color. * The tcolor is the text color. The dcolor specifies the color * of the line used to divide the menu items. The top and left * specify the placement of the top left corner of the menu on the screen. 0,0 is * at the bottom left of the screen, and 100,100 is at the top right. The * size of the text is given as a percentage of the vertical size of the * screen. The options array is a NULL terminated array of character * strings. The first is a menu title and the rest are the menu options (i.e., * options[0] is the menu title, and options[1], options[2], etc., are the menu * options). The last option must be the NULL pointer. * The coordinates of the bottom right of the menu are calculated based on the * top left coordinates, the size, the number of * options, and the longest option text length. If necessary, the menu * coordinates are adjusted to make sure the menu is on the screen. * D_popup(~) does the following: *
  1. Current screen contents under the menu are saved.
  2. Area is blanked with the background color and fringed with the text color.
  3. Menu options are drawn using the current font.
  4. User uses the mouse to choose the desired option.
  5. Menu is erased and screen is restored with the original contents.
  6. Number of the selected option is returned to the calling module.
* * \param bcolor * \param tcolor * \param dcolor * \param top * \param left * \param size * \param options[] * \return int */ int D_popup( int back_colr,int text_colr,int div_colr, int top,int left,int percent_per_line, char *options[]) { int t, l, b, r ; int opt ; int x, y ; int button ; int text_size ; int text_raise ; int n_options ; int max_len ; int len ; char *panel ; int dots_per_line, dots_per_char, height, width ; /* Figure the number of options and the max length of options */ max_len = 0 ; for(n_options=0; options[n_options] != NULL; n_options++) { len = strlen(options[n_options]) ; if (max_len < len) max_len = len ; } /* Figure the dots per line and dots_per_char */ height = R_screen_bot() - R_screen_top(); width = R_screen_rite() - R_screen_left(); dots_per_line = height * percent_per_line / 100 ; dots_per_char = width / (max_len + 2); /* we want the box to fit into window horizontally */ t = R_screen_bot() - (R_screen_bot() - R_screen_top()) * top / 100 ; l = R_screen_left() + (R_screen_rite() - R_screen_left()) * left / 100 ; /* Figure the bottom and right of the window */ text_size = (int)(.8 * (float)dots_per_line) ; if(text_size > dots_per_char) text_size = dots_per_char; text_raise = (dots_per_line - text_size + 1) / 2; if (text_raise == 0) text_raise = 1; b = Y_BORDER + t + dots_per_line * n_options ; r = 2 * X_BORDER + l + text_size * max_len ; /* Adjust, if necessary, to make sure window is all on screen */ if (t < R_screen_top()) { b = b + (R_screen_top() - t) ; t = R_screen_top() ; } if (b > R_screen_bot()) { t = t - (b - R_screen_bot()) ; b = R_screen_bot() ; } if (t < R_screen_top()) G_fatal_error("popup window too big vertically\n") ; if (l < R_screen_left()) { r = r + (R_screen_left() - l) ; l = R_screen_left() ; } if (r > R_screen_rite()) { l = l - (r - R_screen_rite()) ; r = R_screen_rite() ; } if (l < R_screen_left()) { /* actually, this should never happen */ fprintf(stderr, "ERROR:\n") ; fprintf(stderr, "popup window too big horizontally\n"); fprintf(stderr,"to fit into the graphics window.\n"); fprintf(stderr, "Widen the graphics window.") ; fprintf(stderr, "\nExiting...\n") ; exit(1); } /* Make sure text is not drawn outside of window */ R_set_window(t, b, l, r) ; /* Save the panel in some name */ panel = G_tempfile() ; R_panel_save(panel, t, b, l, r) ; /* Clear the panel */ R_standard_color(back_colr) ; R_box_abs(l,t,r,b) ; /* Draw border */ R_standard_color(text_colr) ; R_move_abs(l+1, t+1) ; R_cont_abs(r-1, t+1) ; R_cont_abs(r-1, b-1) ; R_cont_abs(l+1, b-1) ; R_cont_abs(l+1, t+1) ; /* Prepare for text */ R_text_size(text_size, text_size) ; /* list the options */ for(opt=1; opt<=n_options; opt++) { if (opt != n_options) { R_standard_color(div_colr) ; R_move_abs(l+2, t + Y_BORDER + opt * dots_per_line) ; R_cont_rel (r-l-4, 0); } R_standard_color(text_colr) ; R_move_abs(l + X_BORDER, t + Y_BORDER + opt * dots_per_line - text_raise) ; R_text(options[opt-1]) ; } R_flush() ; x = (l + r) / 2 ; y = (t + b) / 2 ; while(1) { int n; R_get_location_with_pointer(&x, &y, &button) ; if (x > r || x < l || y < t + Y_BORDER + dots_per_line || y > b - Y_BORDER) continue ; n = y - t - Y_BORDER ; if (n % dots_per_line == 0) continue; R_panel_restore(panel) ; R_panel_delete(panel) ; return (n / dots_per_line) ; } }