📄 time_lbl.c
字号:
/* time_lbl.h - time label widget for Upshot Ed Karrels Argonne National Laboratory*/#if !defined(HAVE_STDLIB_H)#include <stdlib.h>#else#if HAVE_STDLIB_H#include <stdlib.h>#endif#endif#include <math.h>#include <string.h>#include "tcl.h"#include "tk.h"#include "time_lbl.h"#include "cvt_args.h"#include "str_dup.h"#define DEBUG 0#define DEBUG_NO_CONFIG 0/* Sorry about this kludge, but our ANSI C compiler on our suns has broken header files */#ifdef GCC_WALLint sscanf( char *, const char *, ... );#endif /* size of temporary buffers for building Tcl commands */#define TMP_CMD_LEN 200 /* length of hash marks */#define HASH_LEN 10 /* # of pixels to leave between the hash mark and the text label */#define SPACE_HASH_LBL 3 /* # of pixels to leave between labels */#define SPACE_LBL_LBL 10 /* # of pixels of space below the labels */#define SPACE_LBL_BOTTOM 3 /* default colors */#define DEF_TIMELBL_MONO_BG "white"#define DEF_TIMELBL_COLOR_BG "SteelBlue"#define DEF_TIMELBL_MONO_FG "black"#define DEF_TIMELBL_COLOR_FG "snow" /* default font *//* #define DEF_TIMELBL_FONT "7x13bold" *//* just use the canvas default font, 7x13bold does not convert to PostScript */static Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_STRING, "-foreground", "foreground", "Foreground", DEF_TIMELBL_COLOR_FG, Tk_Offset( timelbl, fg ), TK_CONFIG_COLOR_ONLY, (Tk_CustomOption*)NULL}, {TK_CONFIG_STRING, "-foreground", "foreground", "Foreground", DEF_TIMELBL_MONO_FG, Tk_Offset( timelbl, fg ), TK_CONFIG_MONO_ONLY, (Tk_CustomOption*)NULL}, {TK_CONFIG_SYNONYM, "-fg", "foreground", (char*)0, (char*)0, 0, 0, (Tk_CustomOption*)0}, {TK_CONFIG_STRING, "-background", "background", "Background", DEF_TIMELBL_COLOR_BG, Tk_Offset( timelbl, bg ), TK_CONFIG_COLOR_ONLY, (Tk_CustomOption*)NULL}, {TK_CONFIG_STRING, "-background", "background", "Background", DEF_TIMELBL_MONO_BG, Tk_Offset( timelbl, bg ), TK_CONFIG_MONO_ONLY, (Tk_CustomOption*)NULL}, {TK_CONFIG_SYNONYM, "-bg", "background", (char*)0, (char*)0, 0, 0, (Tk_CustomOption*)0},/* {TK_CONFIG_STRING, "-font", "font", "Font", DEF_TIMELBL_FONT, Tk_Offset( timelbl, font ), 0, (Tk_CustomOption*)NULL},*/ {TK_CONFIG_END, (char*)0, (char*)0, (char*)0, (char*)0, 0, 0, (Tk_CustomOption*)NULL}};#ifdef __STDC__#define ARGS(x) x#else#define ARGS(x) ()#endif/* Create a timelbl widget.*/static int TimeLbl_create ARGS((ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]));/* Called on resize events. Recalculate and redraw all labels.*/static int Resize ARGS(( timelbl*, int width, int height ));/* Call Tk_ConfigurreWidget, and any other configuration needed (none).*/static int Configure ARGS(( timelbl *lbl, int argc, char **argv ));/* Get the default font from the options database.*//* static int GetFont ARGS(( Tcl_Interp*, char *canvas )); *//* Try drawing some numbers on the canvas and see how big they are. Set lbl->height.*/static int CalcLblSize ARGS(( timelbl* ));/* Called to set new 'left' and 'span' values. If the span has changed, recalculate and redraw all. Other wise, just shift the view and draw/erase.*/static int Set ARGS(( timelbl*, double left, double span ));/* Used when printing. Copy the timelbl to a different canvas.*/static int Copy ARGS(( Tcl_Interp*, timelbl*, int argc, char *argv[] ));/* Create a new hash mark.*/static int CreateHash ARGS(( timelbl*, int hashNo, timelbl_hashmark * ));/* Move and put a different time on an existing hash mark.*/static int UpdateHash ARGS(( timelbl*, int hashNo, timelbl_hashmark * ));/* Delete a hash mark.*/static int DeleteHash ARGS(( timelbl*, timelbl_hashmark * ));/* Delete all hash marks.*/static int EraseAllHashes ARGS(( timelbl* ));/* Given the visWidth, span, and left, recalculate and redraw anything necessary.*/static int Recalc ARGS(( timelbl* ));/* Try out a new hashIncrement by drawing a few of the longest labels. If the hashes will fit OK, return 1, otherwise 0.*/static int HashesWillFit ARGS(( timelbl *lbl ));/* Calculate lbl->firstHashTime, and lbl->format_str.*/static int FiggerHashDrawingInfo ARGS(( timelbl *lbl, int ndec ));/* Convert a hash # to an x coordinate.*/static double LblHashNo2X ARGS(( timelbl*, int hashNo ));/* Convert an time to an x coordinate.*/static double LblTime2X ARGS(( timelbl*, double time )); /* Tcl_CmdProc */static int TimeLblCmd ARGS(( ClientData, Tcl_Interp *, int argc, char **argv )); /* Tcl_CmdDeleteProc */static void TimeLblDelete ARGS(( ClientData clientData ));/* Event handler*/static void TimeLblEvents ARGS(( ClientData data, XEvent *eventPtr ));int Timelbl_Init( interp )Tcl_Interp *interp;{ Tcl_CreateCommand( interp, "time_lbl", TimeLbl_create, (ClientData)Tk_MainWindow( interp ), (Tcl_CmdDeleteProc*) 0 ); return 0;}static int TimeLbl_create( clientData, interp, argc, argv )ClientData clientData;Tcl_Interp *interp;int argc;char *argv[];{ timelbl *lbl; char cmd[TMP_CMD_LEN]; lbl = (timelbl*) malloc( sizeof *lbl ); if (!lbl) { Tcl_AppendResult( interp, "Failed to allocate memory for time label ", "widget record.", (char*)0 ); return TCL_ERROR; } lbl->interp = interp; /* convert the arguments from strings, put them in the widget record */ if (TCL_OK != ConvertArgs( interp, "time_lbl <window name> <from time> <to time>", "1 sff", argc, argv, &lbl->windowName, &lbl->starttime, &lbl->endtime )) { goto failed_1; } if (lbl->starttime >= lbl->endtime) { Tcl_AppendResult( interp, "start time must be less than end time", (char*)0 ); goto failed_1; } /* this string won't last, better make a copy */ lbl->windowName = STRDUP( lbl->windowName ); /* create the Tk window */ lbl->win = Tk_CreateWindowFromPath( interp, (Tk_Window)clientData, lbl->windowName, (char*)0 ); if (!lbl->win) { Tcl_AppendResult( interp, "Failed to create window ", lbl->windowName, (char*)0 ); goto failed_2; } Tk_SetClass( lbl->win, "time_lbl" ); /* set default colors */ Configure( lbl, argc-4, argv+4 ); /* build canvas name */ lbl->canvasName = (char*)malloc( strlen(lbl->windowName)+3 ); sprintf( lbl->canvasName, "%s.c", lbl->windowName ); /* call Tcl to create the canvas */ sprintf( cmd, "canvas %s -bg %s -relief sunken -scrollincrement 1", lbl->canvasName, lbl->bg ); /* and return any error code */ if (TCL_OK != Tcl_Eval( interp, cmd )) goto failed_3; /* pack the canvas inside this widget's window */ sprintf( cmd, "pack %s -expand 1 -fill both", lbl->canvasName ); /* and return any error code */ if (TCL_OK != Tcl_Eval( interp, cmd )) goto failed_3; /* calculate the height of the labels, and thus the height of the canvas */ if (CalcLblSize( lbl )!= TCL_OK) goto failed_3; /* request the neccessary height, but dunno about width */ Tk_GeometryRequest( lbl->win, 1, lbl->height ); /* tell Tcl the size the widget wants */ sprintf( cmd, "%s config -height %d", lbl->canvasName, lbl->height ); /* and return any error code */ if (TCL_OK != Tcl_Eval( interp, cmd )) goto failed_3; lbl->totaltime = lbl->endtime - lbl->starttime; lbl->visWidth = 1; lbl->width = 1; lbl->left = -1; lbl->span = 0; lbl->lastSpan = -1; lbl->lastVisWidth = -1; /* set to NULL so nobody tries to free() */ lbl->format_str = 0; lbl->xview = 0; /* clear the linked list of hash marks */ lbl->head = lbl->tail = 0; /* create the widget command */ Tcl_CreateCommand( interp, lbl->windowName, TimeLblCmd, (ClientData)lbl, TimeLblDelete ); /* request resize events */ Tk_CreateEventHandler( lbl->win, (unsigned long)(StructureNotifyMask), TimeLblEvents, (ClientData)lbl ); return TCL_OK; failed_3: Tk_DestroyWindow( lbl->win ); failed_2: free( (char*)lbl->windowName ); free( (char*)lbl->canvasName ); failed_1: free( (char*)lbl ); return TCL_ERROR;}static void TimeLblDelete( data )ClientData data;{ timelbl *lbl; timelbl_hashmark *node, *next; /* convert data pointer to my widget record pointer */ lbl = (timelbl*) data; free( lbl->windowName ); free( lbl->canvasName ); /* free the linked list of hash labels */ node = lbl->head; while (node) { next = node->next; free( node ); node = next; } /* free the record itself */ free( lbl );}static int TimeLblCmd( clientData, interp, argc, argv )ClientData clientData;Tcl_Interp *interp;int argc;char **argv;{ timelbl *lbl; Tcl_DString cmd; int i, returnVal; double left, span; lbl = (timelbl*)clientData; if (!strcmp( argv[1], "setview" )) { if (ConvertArgs( lbl->interp, "timelbl set <left> <span>", "2 ff", argc, argv, &left, &span ) != TCL_OK) { return TCL_ERROR; } else { return Set( lbl, left, span ); } } if (!strcmp( argv[1], "copy" )) { return Copy( interp, lbl, argc, argv ); } Tcl_DStringInit( &cmd ); Tcl_DStringAppendElement( &cmd, lbl->canvasName ); for (i=1; i<argc; i++) { Tcl_DStringAppendElement( &cmd, argv[i] ); } returnVal = Tcl_Eval( interp, Tcl_DStringValue( &cmd ) ); Tcl_DStringFree( &cmd ); return returnVal;}static void TimeLblEvents( data, event )ClientData data;XEvent *event;{ timelbl *lbl; lbl = (timelbl*) data; switch (event->type) { case ConfigureNotify: Resize( lbl, event->xconfigure.width, event->xconfigure.height ); break; }}static int Resize( lbl, width, height )timelbl *lbl;int width, height;{ lbl->visWidth = width; return Recalc( lbl );}static int Configure( lbl, argc, argv )timelbl *lbl;int argc;char **argv;{ lbl->fg = lbl->bg = lbl->font = 0; if (TCL_OK != Tk_ConfigureWidget( lbl->interp, lbl->win, configSpecs, argc, argv, (void*)lbl, 0 )) { fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); } return 0;}#if 0static int GetFont( interp, canvas )Tcl_Interp *interp;char *canvas;{ if (TCL_OK != Tcl_VarEval( interp, "option get ", canvas, " font Font", (char*)0 )) { fprintf( stderr, "%s\n", interp->result ); return TCL_ERROR; } else { return TCL_OK; }}#endifstatic int CalcLblSize( lbl )timelbl *lbl;{ char cmd[TMP_CMD_LEN]; int tmp_text_id, top, bottom, height; /* if (TCL_OK != GetFont( lbl->interp, lbl->canvasName )) { goto err; }*//* font = STRDUP( lbl->interp->result );*/ /* create temporary object on the canvas */ if (TCL_OK != Tcl_VarEval( lbl->interp, lbl->canvasName, " create text 0 0 -text 8 ", (char*)0 )) { goto err; }/* free( font );*/ /* grab the id of the text created */ tmp_text_id = atoi( lbl->interp->result ); /* get the size of the text created */ sprintf( cmd, "%s bbox %d", lbl->canvasName, tmp_text_id ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) goto err; sscanf( lbl->interp->result, "%*d %d %*d %d", &top, &bottom ); sprintf( cmd, "%s delete %d", lbl->canvasName, tmp_text_id ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) goto err; height = bottom - top; lbl->height = HASH_LEN + SPACE_HASH_LBL + height + SPACE_LBL_BOTTOM; return TCL_OK; err: fprintf( stderr, "%s\n", lbl->interp->result ); return TCL_ERROR;}static int Set( lbl, left, span )timelbl *lbl;double left, span;{ if (span <= 0) { Tcl_SetResult( lbl->interp, "invalid span", TCL_STATIC ); return TCL_ERROR; } lbl->left = left; lbl->span = span; return Recalc( lbl );}static int CreateHash( lbl, hashNo, node )timelbl *lbl;int hashNo;timelbl_hashmark *node;{ char cmd[TMP_CMD_LEN], lbl_str[100]; double xpos;#if DEBUG>2 fprintf( stderr, "Creating hash # %d\n", hashNo );#endif xpos = LblHashNo2X( lbl, hashNo ); node->lbl_idx = hashNo; /* create the hash line */ sprintf( cmd, "%s create line %.17g 0 %.17g %d -fill %s -tags color_fg", lbl->canvasName, xpos, xpos, HASH_LEN, lbl->fg ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); sscanf( lbl->interp->result, "%d", &node->hashMark_canvas_idx ); /* create the text label */ sprintf( lbl_str, lbl->format_str, lbl->firstHashTime + lbl->hashIncrement * hashNo ); sprintf( cmd, "%s create text %.17g %d -anchor n -text %s -fill %s -tags color_fg", lbl->canvasName, xpos, HASH_LEN+SPACE_HASH_LBL, lbl_str, lbl->fg ); /* -font %s, lbl->font, */#if DEBUG>2 fprintf( stderr, "%s\n", cmd );#endif if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); sscanf( lbl->interp->result, "%d", &node->text_canvas_idx ); return 0;} static int UpdateHash( lbl, hashNo, node )timelbl *lbl;int hashNo;timelbl_hashmark *node;{ char cmd[TMP_CMD_LEN], lbl_str[100]; double xpos;#if DEBUG>2 fprintf( stderr, "Updating hash # %d from %d\n", hashNo, node->lbl_idx );#endif xpos = LblHashNo2X( lbl, hashNo ); node->lbl_idx = hashNo; sprintf( cmd, "%s coords %d %.17g 0 %.17g %d", lbl->canvasName, node->hashMark_canvas_idx, xpos, xpos, HASH_LEN ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); /* Shouldn't have to redefine the fill color sprintf( cmd, "%s itemconfig %d -fill %s", lbl->canvasName, node->hashMark_canvas_idx, lbl->fg ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -