|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 9938 (0x26d2)
Types: TextFile
Names: »piemenu_track.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/Sun/Sdi/piemenu_track.c«
#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, ¢er_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);
}