345 lines
9.9 KiB
C
345 lines
9.9 KiB
C
/* File CP.c */
|
|
/* This module contains the instance data and methods for the Control Panel. */
|
|
|
|
/****************************************************************
|
|
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"
|
|
|
|
/* This data structure is passed as a message to the graph process. See Topograph.h */
|
|
|
|
struct CPMessage CPmsg = { {{NULL,NULL,NT_MESSAGE,0,"CPMessage"}, /*Node */
|
|
NULL, /*Reply*/
|
|
sizeof(struct CPMessage)}, /*Size */
|
|
0, /*Command */
|
|
-1.0, 1.0, -.625, .625, -1.0, 1.0, 1.0, .625, TRUE, NULL, YES, NULL /*Data */
|
|
};
|
|
|
|
/* Control panel methods. */
|
|
void CP_draw(UWORD code);
|
|
void CP_stop(UWORD code);
|
|
void CP_rescale(UWORD code);
|
|
void CP_zoom(double factor);
|
|
void CP_newZMin(UWORD code);
|
|
void CP_newZMax(UWORD code);
|
|
void CP_newXMin(UWORD code);
|
|
void CP_newXMax(UWORD code);
|
|
void CP_newYMin(UWORD code);
|
|
void CP_newYMax(UWORD code);
|
|
void CP_newAspect(UWORD code);
|
|
void CP_setAspect(UWORD code);
|
|
void CP_computeAspect(void);
|
|
void CP_adjustX(void);
|
|
void CP_adjustY(void);
|
|
void CP_displayDomain(void);
|
|
void CP_displayRange(void);
|
|
void CP_displayExtrema(struct graph *G);
|
|
void CP_setTitle(char *string);
|
|
void CP_disableRange(void);
|
|
void CP_enableRange(void);
|
|
void CP_buttons(ULONG flags);
|
|
void CP_menusOff(void);
|
|
void CP_menusOn(void);
|
|
void CP_userMessage(char *title, char *message);
|
|
|
|
/* Defined in UI.c */
|
|
extern struct Gadget *CPGadgets[];
|
|
extern struct Window *CPWindow;
|
|
extern char titleString[];
|
|
extern void stackScreens(void);
|
|
|
|
/* Defined in ParseIO.c */
|
|
extern void closeIOConsole(void);
|
|
|
|
/* Defined in Topograph.c */
|
|
extern void graphMessage(int);
|
|
|
|
void CP_draw(UWORD code){
|
|
closeIOConsole();
|
|
graphMessage(DRAW_CMD);
|
|
}
|
|
|
|
void CP_stop(UWORD code){
|
|
|
|
graphMessage(STOP_CMD);
|
|
CP_buttons(DRAW_BUTTON);
|
|
}
|
|
|
|
void CP_rescale(UWORD code){
|
|
CP_disableRange();
|
|
graphMessage(RESCALE_CMD);
|
|
CP_displayRange();
|
|
CP_enableRange();
|
|
}
|
|
|
|
void CP_zoom(double factor){
|
|
double middle, halfwidth;
|
|
|
|
graphMessage(RTNDOMAIN_CMD);
|
|
middle = (CPmsg.xMax + CPmsg.xMin)/2;
|
|
halfwidth = (CPmsg.xMax - CPmsg.xMin)/2;
|
|
CPmsg.xMin = middle - factor*halfwidth;
|
|
CPmsg.xMax = middle + factor*halfwidth;
|
|
|
|
middle = (CPmsg.yMax + CPmsg.yMin)/2;
|
|
halfwidth = (CPmsg.yMax - CPmsg.yMin)/2;
|
|
CPmsg.yMin = middle - factor*halfwidth;
|
|
CPmsg.yMax = middle + factor*halfwidth;
|
|
|
|
CP_displayDomain();
|
|
CPmsg.computeNewValues = YES;
|
|
graphMessage(DRAW_CMD);
|
|
}
|
|
|
|
|
|
void CP_newXMin(UWORD code){
|
|
struct StringInfo *SI = (struct StringInfo *)(CPGadgets[XMIN]->SpecialInfo);
|
|
|
|
sscanf(SI->Buffer, "%le", &(CPmsg.xMin));
|
|
if (CPmsg.aspectIsFixed == TRUE) CP_adjustY();
|
|
else CP_computeAspect();
|
|
CP_displayDomain();
|
|
}
|
|
|
|
void CP_newXMax(UWORD code){
|
|
struct StringInfo *SI = (struct StringInfo *)(CPGadgets[XMAX]->SpecialInfo);
|
|
|
|
sscanf(SI->Buffer, "%le", &(CPmsg.xMax));
|
|
if (CPmsg.aspectIsFixed == TRUE) CP_adjustY();
|
|
else CP_computeAspect();
|
|
CP_displayDomain();
|
|
}
|
|
|
|
void CP_adjustY(void){
|
|
double yMid = (CPmsg.yMax + CPmsg.yMin)/2;
|
|
double halfSpan = (CPmsg.aspect)*(CPmsg.screenAspect)*(CPmsg.xMax - CPmsg.xMin)/2;
|
|
|
|
CPmsg.yMax = yMid + halfSpan;
|
|
CPmsg.yMin = yMid - halfSpan;
|
|
}
|
|
|
|
void CP_newYMin(UWORD code){
|
|
struct StringInfo *SI = (struct StringInfo *)(CPGadgets[YMIN]->SpecialInfo);
|
|
|
|
sscanf(SI->Buffer, "%le", &(CPmsg.yMin));
|
|
if (CPmsg.aspectIsFixed == TRUE) CP_adjustX();
|
|
else CP_computeAspect();
|
|
CP_displayDomain();
|
|
}
|
|
|
|
void CP_newYMax(UWORD code){
|
|
struct StringInfo *SI = (struct StringInfo *)(CPGadgets[YMAX]->SpecialInfo);
|
|
|
|
sscanf(SI->Buffer, "%le", &(CPmsg.yMax));
|
|
if (CPmsg.aspectIsFixed == TRUE) CP_adjustX();
|
|
else CP_computeAspect();
|
|
CP_displayDomain();
|
|
}
|
|
|
|
void CP_adjustX(){
|
|
double xMid = (CPmsg.xMax + CPmsg.xMin)/2;
|
|
double halfSpan = (CPmsg.yMax - CPmsg.yMin)/((CPmsg.aspect)*(CPmsg.screenAspect)*2);
|
|
|
|
CPmsg.xMax = xMid + halfSpan;
|
|
CPmsg.xMin = xMid - halfSpan;
|
|
}
|
|
|
|
void CP_computeAspect(void){
|
|
CPmsg.aspect = (CPmsg.yMax - CPmsg.yMin)/(CPmsg.screenAspect*(CPmsg.xMax - CPmsg.xMin));
|
|
}
|
|
|
|
void CP_newZMin(UWORD code){
|
|
char buffer[30];
|
|
struct StringInfo *SI = (struct StringInfo *)(CPGadgets[ZBOTTOM]->SpecialInfo);
|
|
|
|
sscanf(SI->Buffer, "%le", &(CPmsg.zMin));
|
|
sprintf(buffer, "%10.6f", CPmsg.zMin);
|
|
GT_SetGadgetAttrs(CPGadgets[ZBOTTOM], CPWindow, NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
}
|
|
|
|
void CP_newZMax(UWORD code){
|
|
char buffer[30];
|
|
struct StringInfo *SI = (struct StringInfo *)(CPGadgets[ZTOP]->SpecialInfo);
|
|
|
|
sscanf(SI->Buffer, "%le", &(CPmsg.zMax));
|
|
sprintf(buffer, "%10.6f", CPmsg.zMax);
|
|
GT_SetGadgetAttrs(CPGadgets[ZTOP], CPWindow, NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
}
|
|
|
|
void CP_newAspect(UWORD code){
|
|
if (code == 0) {
|
|
CPmsg.aspectIsFixed = TRUE;
|
|
OffGadget(CPGadgets[ASPECT],CPWindow,NULL);
|
|
}
|
|
else {
|
|
CPmsg.aspectIsFixed = FALSE;
|
|
OnGadget(CPGadgets[ASPECT],CPWindow,NULL);
|
|
}
|
|
}
|
|
|
|
void CP_setAspect(UWORD code){
|
|
char buffer[30];
|
|
struct StringInfo *SI = (struct StringInfo *)(CPGadgets[ASPECT]->SpecialInfo);
|
|
|
|
sscanf(SI->Buffer, "%le", &(CPmsg.aspect));
|
|
sprintf(buffer, "%10.6f", CPmsg.aspect);
|
|
GT_SetGadgetAttrs(CPGadgets[ASPECT], CPWindow, NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
CP_adjustY();
|
|
CP_displayDomain();
|
|
}
|
|
|
|
/* Update the domain info and the aspect ratio. */
|
|
|
|
void CP_displayDomain(void){
|
|
char buffer[30];
|
|
|
|
sprintf(buffer, "%-10.6f", CPmsg.xMin);
|
|
GT_SetGadgetAttrs(CPGadgets[XMIN], CPWindow,NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
|
|
sprintf(buffer, "%-10.6f", CPmsg.xMax);
|
|
GT_SetGadgetAttrs(CPGadgets[XMAX], CPWindow,NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
|
|
sprintf(buffer, "%-10.6f", CPmsg.yMin);
|
|
GT_SetGadgetAttrs(CPGadgets[YMIN], CPWindow,NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
|
|
sprintf(buffer, "%-10.6f", CPmsg.yMax);
|
|
GT_SetGadgetAttrs(CPGadgets[YMAX], CPWindow,NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
|
|
sprintf(buffer, "%-10.6f", CPmsg.aspect);
|
|
GT_SetGadgetAttrs(CPGadgets[ASPECT], CPWindow, NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
}
|
|
|
|
/* Update the range info. */
|
|
|
|
void CP_displayRange(void){
|
|
char buffer[30];
|
|
|
|
sprintf(buffer, "%-10.6f", CPmsg.zMin);
|
|
GT_SetGadgetAttrs(CPGadgets[ZBOTTOM], CPWindow,NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
|
|
sprintf(buffer, "%-10.6f", CPmsg.zMax);
|
|
GT_SetGadgetAttrs(CPGadgets[ZTOP], CPWindow,NULL,
|
|
GTST_String, buffer,
|
|
TAG_END);
|
|
}
|
|
|
|
void CP_displayExtrema(struct graph *G){
|
|
char buffer[30];
|
|
|
|
if (G->extremaAreKnown){
|
|
sprintf(buffer, "%-10.6f", G->minimum);
|
|
GT_SetGadgetAttrs(CPGadgets[ZMIN], CPWindow, NULL,
|
|
GTTX_Text, buffer,
|
|
TAG_END);
|
|
|
|
sprintf(buffer, "%-10.6f", G->maximum);
|
|
GT_SetGadgetAttrs(CPGadgets[ZMAX], CPWindow, NULL,
|
|
GTTX_Text, buffer,
|
|
TAG_END);
|
|
}
|
|
|
|
else {
|
|
buffer[0] = '\0';
|
|
|
|
GT_SetGadgetAttrs(CPGadgets[ZMIN], CPWindow, NULL,
|
|
GTTX_Text, buffer,
|
|
TAG_END);
|
|
|
|
GT_SetGadgetAttrs(CPGadgets[ZMAX], CPWindow, NULL,
|
|
GTTX_Text, buffer,
|
|
TAG_END);
|
|
}
|
|
}
|
|
|
|
void CP_setTitle(char *string){
|
|
if (string == NULL) string = titleString;
|
|
SetWindowTitles(CPWindow, string, NULL);
|
|
}
|
|
|
|
void CP_menusOff(void){
|
|
OffMenu(CPWindow, FULLMENUNUM(0,0,NOSUB));
|
|
OffMenu(CPWindow, FULLMENUNUM(0,3,NOSUB));
|
|
OffMenu(CPWindow, FULLMENUNUM(1,NOITEM,NOSUB));
|
|
}
|
|
|
|
void CP_menusOn(void){
|
|
OnMenu(CPWindow, FULLMENUNUM(0,0,NOSUB));
|
|
OnMenu(CPWindow, FULLMENUNUM(0,3,NOSUB));
|
|
OnMenu(CPWindow, FULLMENUNUM(1,NOITEM,NOSUB));
|
|
}
|
|
|
|
void CP_disableRange(void){
|
|
OffGadget(CPGadgets[ZBOTTOM],CPWindow,NULL);
|
|
OffGadget(CPGadgets[ZTOP],CPWindow,NULL);
|
|
}
|
|
|
|
void CP_enableRange(void){
|
|
OnGadget(CPGadgets[ZBOTTOM],CPWindow,NULL);
|
|
OnGadget(CPGadgets[ZTOP],CPWindow,NULL);
|
|
}
|
|
|
|
void CP_buttons(ULONG flags){
|
|
if (flags & DRAW_BUTTON)OnGadget(CPGadgets[DRAW], CPWindow, NULL);
|
|
else OffGadget(CPGadgets[DRAW], CPWindow, NULL);
|
|
if (flags & RESCALE_BUTTON)OnGadget(CPGadgets[RESCALE], CPWindow, NULL);
|
|
else OffGadget(CPGadgets[RESCALE], CPWindow, NULL);
|
|
if (flags & STOP_BUTTON)OnGadget(CPGadgets[STOP], CPWindow, NULL);
|
|
else OffGadget(CPGadgets[STOP], CPWindow, NULL);
|
|
}
|
|
|
|
void CP_userMessage(char *title, char *message){
|
|
struct EasyStruct ES = {
|
|
sizeof(struct EasyStruct),
|
|
0,
|
|
NULL,
|
|
"%s",
|
|
"Oh"};
|
|
|
|
ES.es_Title = title;
|
|
EasyRequest(CPWindow,&ES,0,message);
|
|
stackScreens();
|
|
}
|
|
|