DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T p

⟦4070d33fc⟧ TextFile

    Length: 9938 (0x26d2)
    Types: TextFile
    Names: »piemenu_track.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/Sun/Sdi/piemenu_track.c« 

TextFile

#include <pixrect/pixrect_hs.h>
#include <sunwindow/notify.h>
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <math.h>
#include "walkmenu_impl.h"
#include "image_impl.h"
#undef min
#undef max
#undef fabs

/*
 * Copyright 1987 by Mark Weiser.
 * Permission to reproduce and use in any manner whatsoever on Suns is granted
 * so long as this copyright and other identifying marks of authorship
 * in the code and the game remain intact and visible.  Use of this code
 * in other products is reserved to me--I'm working on Mac and IBM versions.
 */


/*
 * Preliminary implementation of pie menus (Patent Applied for.)
 */

#ifndef M_PI
#define M_PI	3.14159265358979323846
#endif

static short pie_cursor_array[] = {
#include "pie_generic_cursor.h"
};
mpr_static(pie_generic_cursor, 16, 16, 1, pie_cursor_array);

double fabs();

int dead_zone = 5;	/* this is not used consistently. */

static Notify_value main_event_proc();

double angle, fabs(), fmin(), fmax();

struct menu_item *menu_track_helper();

static int done;
static caddr_t done_val;
static Frame mainframe;
static Canvas maincanvas;
static int (*return_proc)();

struct menu_item *
pie_menu(m, event, x, y, w, f, s)
struct menu *m;
Event *event;
Window w;
int (*f)();
char *s;
{
	struct menu_item *value;

	construct_pie_frame(w, x, y, m, s);

	window_set(mainframe, WIN_SHOW, TRUE, 0);

	return_proc = f;
}

construct_pie_frame(w, x, y, m, s)
Window w;
struct menu *m;
char *s;
{
	int width, height;
	int max_len;
	Pixwin *pw;
	if (m->default_image.font == NULL)
		m->default_image.font = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.b.12");
	if (m->default_image.font == NULL)
		m->default_image.font = pf_default();

	max_len = pie_process_args(m);
	m->default_image.width = m->default_image.height = 3.5*(float)max_len+dead_zone + 1;

	mainframe = window_create(w, FRAME,
		FRAME_LABEL, s,
		FRAME_SHOW_LABEL, TRUE,
		FRAME_NO_CONFIRM, TRUE,
		0);

	maincanvas = window_create(mainframe, CANVAS,
		WIN_WIDTH, m->default_image.width,
		WIN_HEIGHT, m->default_image.height,
		WIN_CLIENT_DATA, m,
#ifndef SUNOS3_0
		WIN_GRAB_ALL_INPUT, TRUE,
#endif
		WIN_CONSUME_PICK_EVENT, WIN_IN_TRANSIT_EVENTS, 0,
		0);
	window_set(maincanvas,
		WIN_EVENT_PROC, main_event_proc,
		0);
	window_fit(mainframe);
	(Pixwin *)m->default_image.pr = pw = canvas_pixwin(maincanvas);
	(Canvas)m->dynamic_info = maincanvas;

	window_set(mainframe, 
		WIN_X, x - m->default_image.width/2,
		WIN_Y, y - m->default_image.height/2,
		0);

	init_pies(m, pw);
	new_cursor(0.0, -1);
}

#define DESELECT_ON_EXIT

static Notify_value
main_event_proc(win, event, arg)
Window win;
Event *event;
caddr_t arg;
{
	struct menu *m = (struct menu *)window_get(win, WIN_CLIENT_DATA);
	Pixwin *pw = (Pixwin *)m->default_image.pr;
	int id = event_id(event);
	int x = event_x(event);
	int y = event_y(event);
	int x_inc, y_inc;
	double theta;
	double inc = 2.0*M_PI/m->nitems;
	int i;
	int pie_x = m->default_image.width/2;
	int pie_y = m->default_image.height/2;
	static outside_window = 0;

	if (id == WIN_RESIZE) {
		window_set(win, WIN_MOUSE_XY, pie_x, pie_y, 0);
	}

	
	if ((!outside_window && (id == LOC_MOVE || event_is_button(event)))
		|| id == LOC_WINENTER || id == LOC_RGNENTER) {
		outside_window = 0;
		x_inc = pie_x - x;
		y_inc = pie_y - y;
		if (abs(x_inc) > dead_zone || abs(y_inc) > dead_zone ||
			(int)sqrt((double)(x_inc*x_inc + y_inc*y_inc)) > dead_zone) {
			/* Found an item */
			theta = M_PI + atan2((double)x_inc, (double)y_inc);
			i = ((theta+inc)/inc) - 1;
			if (i >= m->nitems)
				i = m->nitems - 1;
			if (i != m->selected_position) {
				/* Remove old highlighting, if any */
				if (m->selected_position != -1) 
					draw_item(pw, m, PIX_SRC, m->selected_position );
				/* Highlight new selection */
				m->selected_position = i;
				draw_item(pw, m, PIX_NOT(PIX_SRC), m->selected_position);
			}
		} else if (m->selected_position != -1) {
			/* Remove old highlighting */
			draw_item(pw, m, PIX_SRC, m->selected_position);
			m->selected_position = -1;
		}
	}
	else if (id == LOC_WINEXIT || id == LOC_RGNEXIT) {
#ifdef SUNOS3_0
#ifdef DESELECT_ON_EXIT
#undef DESELECT_ON_EXIT
#endif
#define DESELECT_ON_EXIT
#endif
#ifdef DESELECT_ON_EXIT
		outside_window = 1;
		if (m->selected_position != -1) {
			/* Remove old highlighting */
			draw_item(pw, m, PIX_SRC, m->selected_position);
			m->selected_position = -1;
		}
		m->selected_position = -1;
#else SELECT_ON_EXIT
		if (m->selected_position == -1) {
			pie_window_return(NULL, event, m);
		} else {
			pie_window_return(m->item_list[m->selected_position], event,m);
		}
#endif
	}
	if (event_is_up(event) && event_is_button(event)) {
		/* Selecting an item */
		Frame owner = (Frame)window_get(m->dynamic_info, WIN_OWNER);
		if (m->selected_position == -1) {
			if (m->parent) {
				/* finished a subwindow without a selection */
				window_set(win, WIN_CLIENT_DATA, m->parent->parent, 0);
				/* this breaks: window_done(owner); */
				/* and for some reason, this leaves the window visible: */
				window_set(owner, WIN_SHOW, FALSE, 0);
			} else {
				/* this is the top */
				pie_window_return(NULL, event,m);
			}
		} else if (! m->item_list[m->selected_position]->pullright) {
			pie_window_return(m->item_list[m->selected_position], event,m);
		} else {
/*	nesting temporarily disabled
			Frame newframe;
			struct menu *newm = (struct menu *)m->item_list[m->selected_position]->value;
			newframe = construct_pie_frame(x+window_get(owner, WIN_X),
				y+window_get(owner, WIN_Y), newm, 0);
			window_set(win, WIN_CLIENT_DATA, newm, 0);
			window_set(newframe, WIN_SHOW, TRUE, 0);
*/
		}
	}
	new_cursor(m->selected_position*inc+(inc/2.0), m->selected_position);
	return NOTIFY_DONE;
}

static int
pie_process_args(m)
struct menu *m;
{
	int itemnum = 0;
	struct menu_item **argv = m->item_list;
	struct pr_size size;
	int max_len = 0;
	while (itemnum++ < m->nitems) {
		struct image *im = (*argv)->image;
		if (im->pr) {
			/* got an image */
			size = im->pr->pr_size;
		} else {
			if (! im->string) {
				im->string = "(null)";
			}
			size = pf_textwidth(strlen(im->string), m->default_image.font, im->string);
		}
		im->width = size.x;
		im->height = size.y;
		if (size.x > max_len)
			max_len = size.x;
		if (size.y > max_len)
			max_len = size.y;
		argv++;
	}
	return max_len;
}

/* center for 5 bit radius deadzone */
short center_data[] = {
#include "center.h"
};
mpr_static(center_pr, 11, 11, 1, center_data);

/* Serious abuse of the image structure here.
   'left_margin' is used to store the x position
   'right_margin' is used to store the y position
*/

init_pies(m, pw)
struct menu *m;
Pixwin *pw;
{
	struct menu_item **pies = m->item_list;
	double diameter = (double)m->default_image.width;
	double fr = diameter/2;
	double fr2 = fr/2.0;
	int i;
	double inc = 2.0*M_PI/(double)m->nitems;
	double theta = inc/2.0;
	for(i = 0; i < m->nitems; i++) {
		/* compute x position of upper lefthand corner */
		pies[i]->image->left_margin = fmax(0.0, 
			fmin((double)(diameter-pies[i]->image->width+2), 
				fmax(2.0,
					fr*sin(theta) + fr - pies[i]->image->width/2)));
		/* compute y position of upper lefthand corner */
		pies[i]->image->right_margin = fmax(0.0,
			fmin((double)(diameter-pies[i]->image->height-2),
				fmax(2.0,
					fr*cos(theta) + fr - pies[i]->image->height/2)));
		theta += inc;
		draw_item(pw, m, PIX_SRC, i);
	}
	pw_rop(pw, m->default_image.width/2-5, m->default_image.height/2-5, 11, 11, PIX_SRC, &center_pr, 0, 0);
}

static min(x,y)
{
return x < y ? x : y;
}

static max(x,y)
{
return x < y ? y : x;
}

double
fabs(x)
double x;
{
	return x < 0 ? -x : x;
}

double
fmin(x,y)
double x, y;
{
return x < y ? x : y;
}

double
fmax(x,y)
double x, y;
{
return x < y ? y : x;
}

draw_item(pw, m, op, item)
Pixwin *pw;
struct menu *m;
int item;
{
	struct image *im = m->item_list[item]->image;
	if (im->pr) {
		pw_rop(pw,
			im->left_margin,
			im->right_margin,
			im->width,
			im->height,
			op, im->pr, 0, 0);
	} else {
		pw_text(pw,
			im->left_margin,
			im->right_margin + im->height, /* text posn is from baseline */
			op, m->default_image.font, im->string);
	}
}

/* Why all the extra levels of function calls?  Well, at one time
   they all added value.  But as the organization changed, more
   and action got pressed into the event_procs, and hollow shells
   were left up here.  They could be removed...
*/
struct menu_item *
menu_track(m, w, event, f, s)
struct menu *m;
Event *event;
Window w;
int (*f)();
{
	struct menu_item *rval;
	rval = pie_menu(m, event, event_x(event), event_y(event), w, f, s);
	return rval;
}

pie_window_return(rval,e,m)
caddr_t rval;
Event *e;
struct menu *m;
{
	caddr_t real_rval;
	window_set(mainframe, FRAME_NO_CONFIRM, TRUE, 0);
	window_destroy(mainframe);
	if (rval == NULL)
		real_rval = (caddr_t)rval;
	if (! m->notify_proc) {
		real_rval = (caddr_t)MENU_DEFAULT_NOTIFY_PROC(m, rval);
	} else {
		real_rval = (caddr_t)(m->notify_proc)(m, rval);
	}
	(*return_proc)(real_rval, e);
}

#define PIN(x) (max(0,min((x),15)))

new_cursor(theta, item_num)
double theta;
int item_num;
{
	int headx, heady;
	Cursor cursor = window_get(maincanvas, WIN_CURSOR);
	struct pixrect *pr = (struct pixrect *)cursor_get(cursor, CURSOR_IMAGE);
	if (item_num == -1) {
		pr_rop(pr, 0, 0, 16, 16, PIX_SRC, &pie_generic_cursor, 0, 0);
		cursor_set(cursor, CURSOR_XHOT, 8, CURSOR_YHOT, 8, 0);
	} else {
		pr_rop(pr, 0, 0, 16, 16, PIX_SRC, NULL, 0, 0);
		pr_vector(pr, 8+(int)(sin(theta)*(double)20.0), 8+(int)(cos(theta)*(double)20.0),
			8+(int)(sin(theta)*(double)(-20.0)), 8+(int)(cos(theta)*(double)(-20.0)),
			PIX_SRC, 1);
		headx = PIN(7+(int)(sin(theta)*(double)8.0));
		heady = PIN(7+(int)(cos(theta)*(double)8.0));
		pr_rop(pr, headx, heady, 3, 3, PIX_NOT(PIX_SRC), NULL, 0, 0);
		cursor_set(cursor, CURSOR_XHOT, headx, CURSOR_YHOT, heady, 0);
	}
	cursor_set(cursor, CURSOR_IMAGE, pr, 0);
	window_set(maincanvas, WIN_CURSOR, cursor, 0);
}