Files
2017-04-17 00:10:12 +02:00

291 lines
9.0 KiB
C

/* File graphevents.c */
/* This module contains a function to process the events from the graph window */
/****************************************************************
Topograph - A function browser
Copyright (C) 1996 Marc Culler
culler@math.uic.edu
Department of Mathematics (M/C 249)
University of Illinois at Chicago
851 S. Morgan St.
Chicago, IL 60607-7045
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
******************************************************************/
#include "Topograph.h"
#include "graph.h"
/* Defined in this module */
void processGraphIDCMP(void);
BOOL printxyz(int mouseX, int mouseY);
void drawBox(int X, int Y, int halfW, int halfH);
/* Defined in UI.c */
extern struct Screen *graphScreen;
extern struct Window *graphWindow;
extern struct Window *CPWindow;
extern struct Window *xyzWindow;
extern struct Gadget *CPGadgets[];
extern int graphHeight;
extern int graphWidth;
extern void noPointer(void);
/* Defined in graph.c */
extern void printX(struct graph *G, char *string, int xIndex);
extern void printY(struct graph *G, char *string, int yIndex);
extern void printZ(struct graph *G, char *string, int xIndex, int yIndex);
/* Defined in CP.c */
extern struct CPMessage CPmsg;
extern void CP_displayExtrema(struct graph *);
extern void CP_displayDomain(void);
extern void CP_computeAspect(void);
extern void CP_adjustY(void);
/* Defined in graphtask.c */
extern struct graph *theGraph;
extern void graphMessage(int command);
extern double readX(struct graph *G, int xIndex);
extern double readY(struct graph *G, int yIndex);
static BOOL mouseDragging = FALSE;
static int clickX;
static int clickY;
static int zoomHW;
static int zoomHH;
static int maxHW;
static int maxHH;
static double xMinSave, xMaxSave, yMinSave, yMaxSave, aspectSave;
#define MINHH 2
#define MINHW 4
void processGraphIDCMP(void){
struct IntuiMessage *m;
struct IntuiMessage message;
BOOL mouseMoved = FALSE;
int mouseX, mouseY;
static int clickX, clickY;
double boxAspect = (double)graphHeight/graphWidth;
while(m = (struct IntuiMessage *)GetMsg(graphWindow->UserPort)){
message = *m;
ReplyMsg((struct Message *)m);
switch(message.Class){
case MOUSEMOVE:
mouseX = message.MouseX;
mouseY = message.MouseY;
mouseMoved = TRUE;
break;
case MOUSEBUTTONS:
/*
Start zooming in.
*/
if (message.Code == SELECTDOWN){
clickX = graphWindow->MouseX;
clickY = graphWindow->MouseY;
if (printxyz(clickX,clickY)){
mouseDragging = TRUE;
noPointer();
maxHW = 2*clickX<graphWidth?clickX:(graphWidth - clickX - 1);
maxHH = 2*clickY<graphHeight?clickY:(graphHeight - clickY - 1);
zoomHW = 0;
zoomHH = 0;
xMinSave = CPmsg.xMin;
xMaxSave = CPmsg.xMax;
yMinSave = CPmsg.yMin;
yMaxSave = CPmsg.yMax;
aspectSave = CPmsg.aspect;
}
}
/*
Done zooming. Redraw the graph.
*/
else if (message.Code == SELECTUP){
mouseDragging = FALSE;
drawBox(clickX,clickY,zoomHW, zoomHH);
ClearPointer(graphWindow);
/*
If the box is too small we assume that User changed her mind.
*/
if (zoomHW > MINHW && zoomHH > MINHH){
CPmsg.computeNewValues = YES;
graphMessage(DRAW_CMD);
}
else{
CPmsg.xMin = xMinSave;
CPmsg.xMax = xMaxSave;
CPmsg.yMin = yMinSave;
CPmsg.yMax = yMaxSave;
CPmsg.aspect = aspectSave;
CP_displayDomain();
}
}
break;
case IDCMP_RAWKEY:
switch (message.Code){
case UPARROW:
graphMessage(UP_CMD);
break;
case DOWNARROW:
graphMessage(DOWN_CMD);
break;
case LEFTARROW:
graphMessage(LEFT_CMD);
break;
case RIGHTARROW:
graphMessage(RIGHT_CMD);
break;
default:
break;
}
CP_displayDomain();
CP_displayExtrema(theGraph);
break;
default:
break;
}
}
if (mouseMoved) {
if (mouseDragging){
/*
Erase the old box. Note that drawBox does nothing if the box is too
small.
*/
drawBox(clickX,clickY,zoomHW, zoomHH);
/*
Compute the size of the new box.
*/
zoomHW = mouseX - clickX;
if (zoomHW < 0) zoomHW = -zoomHW;
if (zoomHW > maxHW) zoomHW = maxHW;
if (CPmsg.aspectIsFixed == TRUE){
if (zoomHW*boxAspect <= maxHH) zoomHH = zoomHW*boxAspect;
else {
zoomHH = maxHH;
zoomHW = zoomHH/boxAspect;
}
}
else {
zoomHH = mouseY - clickY;
if (zoomHH < 0) zoomHH = -zoomHH;
if (zoomHH > maxHH) zoomHH = maxHH;
}
/*
Draw a new box.
*/
drawBox(clickX,clickY,zoomHW,zoomHH);
/*
Save and display the domain;
*/
CPmsg.xMin=readX(theGraph,clickX - zoomHW);
CPmsg.xMax=readX(theGraph,clickX + zoomHW);
CPmsg.yMin=readY(theGraph,clickY + zoomHH);
CPmsg.yMax=readY(theGraph,clickY - zoomHH);
if (CPmsg.aspectIsFixed == TRUE) CP_adjustY();
else CP_computeAspect();
CP_displayDomain();
}
/*
If User isn't dragging the mouse, we print x,y and z values.
During a drag, we leave the coordinates of the center point
in the xyzWindow. Maybe we should print out Xmin, ... Ymax, though.
This is a good time to check if the pointer is in the CPWindow,
and if so to activate it.
*/
else {
printxyz(mouseX,mouseY);
if (mouseY < 0) ActivateWindow(CPWindow);
}
}
}
void drawBox(int X, int Y, int halfW, int halfH){
struct RastPort *rp = &(graphScreen->RastPort);
if (halfW <= MINHW || halfH <= MINHH) return;
/* SetWrMsk(rp, 0x10);*/ /*We draw boxes on plane 4 only.*/
SetWrMsk(rp, 0x21);
Move(rp,(long)(X-halfW),(long)(Y-halfH));
Draw(rp,(long)(X+halfW),(long)(Y-halfH));
Draw(rp,(long)(X+halfW),(long)(Y+halfH));
Draw(rp,(long)(X-halfW),(long)(Y+halfH));
Draw(rp,(long)(X-halfW),(long)(Y-halfH+1));
SetWrMsk(rp, 0xff);
}
/* If the pointer is not on the graph, clear the xyz gadgets and return FALSE.
Otherwise print the coordinates and return TRUE. */
BOOL printxyz(int mouseX, int mouseY){
/* These have to be long because printf does weird things with nans. */
char xString[64];
char yString[64];
char zString[64];
BOOL value;
if (mouseX < 0 | mouseX >= graphWidth | mouseY >= graphHeight | mouseY < 0){
xString[0] = '\0';
yString[0] = '\0';
zString[0] = '\0';
value = FALSE;
}
else {
printX(theGraph, xString, mouseX);
printY(theGraph, yString, mouseY);
printZ(theGraph, zString, mouseX, mouseY);
value = TRUE;
}
GT_SetGadgetAttrs(CPGadgets[XDISPLAY], xyzWindow,NULL,
GTTX_Text, xString,
TAG_END);
GT_SetGadgetAttrs(CPGadgets[YDISPLAY], xyzWindow,NULL,
GTTX_Text, yString,
TAG_END);
GT_SetGadgetAttrs(CPGadgets[ZDISPLAY], xyzWindow,NULL,
GTTX_Text, zString,
TAG_END);
return(value);
}