📄 time_lbl.c
字号:
*/ sprintf( lbl_str, lbl->format_str, lbl->firstHashTime + lbl->hashIncrement * hashNo ); sprintf( cmd, "%s coords %d %.17g %d", lbl->canvasName, node->text_canvas_idx, xpos, HASH_LEN+SPACE_HASH_LBL ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); sprintf( cmd, "%s itemconfig %d -anchor n -text %s -fill %s", lbl->canvasName, node->text_canvas_idx, 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 ); return 0;}static int DeleteHash( lbl, node )timelbl *lbl;timelbl_hashmark *node;{ char cmd[TMP_CMD_LEN]; /* delete the hash line */ sprintf( cmd, "%s delete %d", lbl->canvasName, node->hashMark_canvas_idx ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); /* delete the text label */ sprintf( cmd, "%s delete %d", lbl->canvasName, node->text_canvas_idx ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); return 0;} /* erase all existing hash marks */static int EraseAllHashes( lbl )timelbl *lbl;{ timelbl_hashmark *node, *next; /* traverse the linked list of hash marks */ node = lbl->head; while (node) { /* delete each one from the canvas */ DeleteHash( lbl, node ); /* delete each one from the linked list */ next = node->next; free( (char*)node ); node = next; } lbl->head = lbl->tail = 0; return 0;} /* recalculate where the labels go and how to format them */ /* this routine sets lbl->hashIncrement, lbl->firstHashTime, and lbl->format_str */static int Recalc( lbl )timelbl *lbl;{ /* text_width - the actual width of the text that makes up an average label */ /* configure event hasn't been sent yet, so don't do anything */ if (lbl->visWidth == -1) return TCL_OK; /* nobody has set me, so don't do anything */ if (lbl->span == 0) return TCL_OK; if (lbl->left > lbl->endtime) { lbl->left = lbl->endtime; } else if (lbl->left < lbl->starttime) { lbl->left = lbl->starttime; } if (lbl->span > lbl->totaltime) { lbl->span = lbl->totaltime; }#if DEBUG>1 fprintf( stderr, "Start recalc\n" ); fprintf( stderr, "span: %f, width: %f\n", lbl->span, lbl->width ); fprintf( stderr, "time: %f to %f\n", lbl->starttime, lbl->endtime );#endif if (lbl->span != lbl->lastSpan || lbl->visWidth != lbl->lastVisWidth) { lbl->lastSpan = lbl->span; lbl->lastVisWidth = lbl->visWidth; RecalcSpan( lbl ); if (EraseAllHashes( lbl )!=TCL_OK) return TCL_ERROR; } RecalcLeft( lbl ); if (Redraw( lbl )!=TCL_OK) return TCL_ERROR; return TCL_OK;}/* Recalculate width and hashIncrement.*/int RecalcSpan( lbl )timelbl *lbl;{ int max_nlbls, ndec, try_again; /* recalculate the width of the canvas */ lbl->width = lbl->visWidth * (lbl->totaltime) / lbl->span; /* minimum magnitude of the difference between hash marks */ /* diffMag = log10( lbl->totaltime ); */ /* estimate 5 pixels as the narrowest a label could get */ /* set how many labels can be displayed */ max_nlbls = lbl->width / (5 + SPACE_LBL_LBL); if (max_nlbls == 0) max_nlbls = 1; /* calculate the difference between hash marks */ lbl->hashIncrement = pow( 10.0, ceil( log10( lbl->totaltime ) - log10( (double) max_nlbls ) ) ); /* start at a really small increment, and keep multiplying it by 10 until the hashes required to draw it will actually fit */ do { try_again = 0; /* figger the number of decimal places in each label */ ndec = lbl->hashIncrement >= 1 ? 0 : (int)(-log10( lbl->hashIncrement )+.5); /* calculate lbl->firstHashTime, and lbl->format_str */ FiggerHashDrawingInfo( lbl, ndec ); /* if the hashes won't fit, spread them out by a factor of 10 and try again */ if (!HashesWillFit( lbl )) { lbl->hashIncrement *= 10.0; try_again = 1; } } while (try_again); /* try 4 subdivisions */ lbl->hashIncrement /= 4.0; /* if the number of decimal places is already > 0, increment by 2, otherwise, if the hash increment is >= 100, leave at 0, for 10 -> 1, for <10, set to 2 */ ndec = (ndec) ? ndec+2 : (lbl->hashIncrement >= 100.0) ? 0 : (lbl->hashIncrement >= 10.0) ? 1 : 2; FiggerHashDrawingInfo( lbl, ndec ); if (!HashesWillFit( lbl )) { /* if 4 won't fit, try 2 */ lbl->hashIncrement *= 2.0; ndec -= (ndec) ? 1 : 0; FiggerHashDrawingInfo( lbl, ndec ); if (!HashesWillFit( lbl )) { /* if 2 won't fit, just go back to what it was */ lbl->hashIncrement *= 2.0; ndec -= (ndec) ? 1 : 0; FiggerHashDrawingInfo( lbl, ndec ); } }#if DEBUG fprintf( stderr, "labels with text of the form %s will be placed at intervals of %f starting at %f, first one at %f, x-intervals of %f\n", lbl->format_str, lbl->hashIncrement, lbl->firstHashTime, LblHashNo2X( lbl, 0), LblHashNo2X( lbl, 1 ) - LblHashNo2X( lbl, 0) );#endif return TCL_OK;}int RecalcLeft( lbl )timelbl *lbl;{ lbl->xview = (lbl->left - lbl->starttime) / lbl->totaltime * lbl->width; return TCL_OK;}int Redraw( lbl )timelbl *lbl;{ char *cmd; int firstVisibleHash, lastVisibleHash; /* indices of the first and last visible hash */ int hashNo; timelbl_hashmark *freeList, *last, *node, *freeListTail; timelbl_hashmark *firstExisting; cmd = malloc( strlen(lbl->canvasName) + 50 ); sprintf( cmd, "%s xview %d", lbl->canvasName, lbl->xview ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); /* figure out the indices of the hashes at the far left and right edges */ firstVisibleHash = (int)((lbl->left - lbl->starttime) / lbl->hashIncrement + .5); lastVisibleHash = (int)((lbl->left + lbl->span - lbl->starttime) / lbl->hashIncrement + .5); #if DEBUG>1 fprintf( stderr, "(left,right)(time,hash): %f %d %f %d\n", leftEdgeTime, firstVisibleHash, rightEdgeTime, lastVisibleHash );#endif /* get the necessary hashes drawn */ freeList = lbl->head; if (!freeList) { firstExisting = 0; } else { if (lbl->head->lbl_idx > lastVisibleHash || lbl->tail->lbl_idx < firstVisibleHash) { /* the lists are disjoint, reuse all the nodes */#if DEBUG>1 fprintf( stderr, "Lists are disjoint, reuse all the nodes.\n" );#endif firstExisting = 0; } else { last = 0; node = freeList; /* add any nodes to the left of visible to the free list */ while (node->lbl_idx < firstVisibleHash) {#if DEBUG>2 fprintf( stderr, "add %p %d to free list\n", (void*)node, node->lbl_idx );#endif last = node; node = node->next; } freeListTail = last; firstExisting = node; if (last) { /* if some free nodes were found, cut them off */ /* meaning, if free nodes precede existing nodes, terminate the free node list so that when the free nodes are used, they don't continue into existing nodes */ last->next = 0; } else { /* if no nodes were found, set free list to 0 */ freeList = 0; } /* skip over the existing nodes */ while (node && node->lbl_idx <= lastVisibleHash) {#if DEBUG>2 fprintf( stderr, "skipping %p %d\n", (void*)node, node->lbl_idx );#endif last = node; node = node->next; } /* if there are still more nodes after the existing nodes */ if (node) {#if DEBUG>1 fprintf( stderr, "Adding nodes after existing list to free list\n" );#endif /* finish off firstExisting list */ last->next = 0; if (freeList) { /* if a free list exists, attach these excess nodes to the first part of it */ freeListTail->next = node; } else { /* if no free list exists, then this is it */ freeList = node; } } } } /* freeList is now either null or points to a list of nodes that can be re-used. firstExisting is also either null or points to a list of nodes that are already set correctly */ hashNo = firstVisibleHash; last = 0; /* first create any nodes that may be needed to precede the existing nodes and skip over the existing nodes */ if (firstExisting) { /* create nodes preceding existing range */ while (hashNo < firstExisting->lbl_idx) { /* get valid node structure */ /* grab nodes from the free list if possible */#if DEBUG>2 fprintf( stderr, "Creating node %d to precede existing list\n", hashNo );#endif if (freeList) { node = freeList; freeList = freeList->next; UpdateHash( lbl, hashNo, node ); } else { node = (timelbl_hashmark*)malloc( sizeof *node ); if (!node) { fprintf( stderr, "Failed to allocate memory when creating hash labels\n" ); } CreateHash( lbl, hashNo, node ); } /* tell this node's predecessor who's next */ if (last) { last->next = node; } else { lbl->head = node; } /* move to next hash number */ last = node; hashNo++; } if (last) { last->next = firstExisting; } else { lbl->head = firstExisting; } /* skip over the exising portion */ node = firstExisting; while (node && hashNo <= lastVisibleHash) {#if DEBUG>2 fprintf( stderr, "skipping %p %d\n", (void*)node, node->lbl_idx );#endif last = node; node = node->next; hashNo++; } /* if node is nonzero, we have too many nodes */ if (node) { lbl->tail = last; last->next = 0; while (node) { last = node->next;#if DEBUG>2 fprintf( stderr, "freeing %p %d\n", (void*)node, node->lbl_idx );#endif DeleteHash( lbl, node ); free( node ); node = last; } } } /* creating nodes either after the exising range or fresh */ while (hashNo <= lastVisibleHash) {#if DEBUG>2 fprintf( stderr, "Creating node %d after existing list\n", hashNo );#endif if (freeList) { node = freeList; freeList = freeList->next; UpdateHash( lbl, hashNo, node ); } else { node = (timelbl_hashmark*)malloc( sizeof *node ); if (!node) { fprintf( stderr, "Failed to allocate memory when creating hash labels\n" ); } CreateHash( lbl, hashNo, node ); } /* tell this node's predecessor who's next */ if (last) { last->next = node; } else { lbl->head = node; } last = node; hashNo++; } last->next = 0; lbl->tail = last; /* free anything still in the free list */ while (freeList) {#if DEBUG>2 fprintf( stderr, "freeing %p %d\n", (void*)freeList, freeList->lbl_idx );#endif DeleteHash( lbl, freeList ); last = freeList->next; free( freeList ); freeList = last; } free( cmd );#if DEBUG>2 { timelbl_hashmark *node; fprintf( stderr, "*End of call to Redraw(), node list:\n" ); node = lbl->head; while (node) { fprintf( stderr, "hash idx: %d, canvas idxs: %d %d\n", node->lbl_idx, node->hashMark_canvas_idx, node->text_canvas_idx ); node = node->next; } }#endif return TCL_OK;} /* Calculate lbl->firstHashTime and lbl->format_str*/static int FiggerHashDrawingInfo( lbl, ndec )timelbl *lbl;int ndec;{ char format_str[100]; /* the value of the first label */ lbl->firstHashTime = (int)(lbl->starttime / lbl->hashIncrement + .5) * lbl->hashIncrement; sprintf( format_str, "%%.%df", ndec ); if (lbl->format_str) free( lbl->format_str ); lbl->format_str = STRDUP( format_str ); return 0;}static int HashesWillFit( lbl )timelbl *lbl;{ char cmd[TMP_CMD_LEN], sample_num[100]; int test_item_index, left, right, text_width; /* the endtime is goint to be the longest possible number displayed */ /* for example, over the range 1.0 to 100.0 */ sprintf( sample_num, lbl->format_str, lbl->endtime ); /* create the text item */ sprintf( cmd, "%s create text 0 0 -text %s", lbl->canvasName, sample_num ); /* -font %s , lbl->font */ if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); sscanf( lbl->interp->result, "%d", &test_item_index ); /* now get the coordinates of a box that encloses the text item */ sprintf( cmd, "%s bbox %d", lbl->canvasName, test_item_index ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); /* get only the first and third integers in the result string */ sscanf( lbl->interp->result, "%d %*d %d", &left, &right ); /* figger the width of the box */ text_width = right - left; /* remove the item */ sprintf( cmd, "%s delete %d", lbl->canvasName, test_item_index ); if (TCL_OK != Tcl_Eval( lbl->interp, cmd )) fprintf( stderr, "%s, %d: %s\n", __FILE__, __LINE__, lbl->interp->result ); #if DEBUG>2 fprintf( stderr, "text:%s:, width: %d, space: %d, positions of 0 and 1: %f %f\n", sample_num, text_width, SPACE_LBL_LBL, LblHashNo2X( lbl, 0 ), LblHashNo2X( lbl, 1 ) );#endif /* if just this label is wider than the entire window, let it go */ if (text_width > lbl->width) return 1; if (text_width + SPACE_LBL_LBL > LblHashNo2X( lbl, 1 ) - LblHashNo2X( lbl, 0)) { /* return 0 if the labels are too closely packed */ return 0; } else { return 1; }} /* convert hash number to the x coordinate it should be placed at */static double LblHashNo2X( lbl, hash_no )timelbl *lbl;int hash_no;{ return LblTime2X( lbl, lbl->firstHashTime + hash_no * lbl->hashIncrement );} /* convert time to x coordinate */static double LblTime2X( lbl, time )timelbl *lbl;double time;{ return (time - lbl->starttime) / (lbl->totaltime) * lbl->width;}static int Copy( interp, lbl, argc, argv )Tcl_Interp *interp;timelbl *lbl;int argc;char **argv;{ char *dest_canvas; int x, y, first_idx, last_idx, left_chop, right_chop; double x0, x1; char bbox[100]; char dest_coords[100]; if (ConvertArgs( interp, "<window> copy <dest_canvas> <x> <y>", "2 sdd", argc, argv, &dest_canvas, &x, &y ) != TCL_OK) { return TCL_ERROR; } first_idx = lbl->head->lbl_idx; x0 = LblHashNo2X( lbl, first_idx ); x1 = LblHashNo2X( lbl, first_idx+1 ); /* If the hash mark of the first label is visible, grab the whole label (set left chop point to halfway between lbl(0) and lbl(-1)). If it is not visible, chop it out of view entirely */ left_chop = (x0 < lbl->xview) ? (int)((x0 + x1)/2) : (int)(x0 - (x1 - x0)/2); last_idx = lbl->tail->lbl_idx; x0 = LblHashNo2X( lbl, last_idx-1 ); x1 = LblHashNo2X( lbl, last_idx ); /* similar deal with chopping off the last label */ right_chop = (x1 > lbl->xview + lbl->visWidth ) ? (int)((x0 + x1)/2) : (int)(x1 + (x1 - x0)/2); sprintf( bbox, "%d %d %d %d", left_chop, 0, right_chop, lbl->height ); sprintf( dest_coords, "%d %d", x - lbl->xview + left_chop, y ); return Tcl_VarEval( interp, "CopyCanvas ", lbl->canvasName, " {", bbox, "} ", dest_canvas, " {", dest_coords, "} color_bg", (char*)0 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -