diff options
Diffstat (limited to 'src/bltGraph.C')
-rw-r--r-- | src/bltGraph.C | 67 |
1 files changed, 31 insertions, 36 deletions
diff --git a/src/bltGraph.C b/src/bltGraph.C index d8036a9..697c3fe 100644 --- a/src/bltGraph.C +++ b/src/bltGraph.C @@ -309,10 +309,13 @@ static int NewGraph(ClientData clientData, Tcl_Interp*interp, if (Blt_CreatePen(graphPtr, interp, "activeBar", CID_ELEM_BAR, 0, NULL) != TCL_OK) goto error; - if (Blt_CreatePageSetup(graphPtr) != TCL_OK) goto error; + // Keep a hold of the associated tkwin until we destroy the graph, + // otherwise Tk might free it while we still need it. + Tcl_Preserve(graphPtr->tkwin); + Tk_CreateEventHandler(graphPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, GraphEventProc, graphPtr); @@ -364,21 +367,17 @@ int Blt_GraphInstCmdProc(ClientData clientData, Tcl_Interp* interp, // called by Tcl_DeleteCommandx static void GraphInstCmdDeleteProc(ClientData clientData) { + printf("GraphInstCmdDeleteProc\n"); Graph* graphPtr = clientData; - - // NULL indicates window has already been destroyed. - if (graphPtr->tkwin != NULL) { - Tk_Window tkwin = graphPtr->tkwin; - graphPtr->tkwin = NULL; - Tk_DestroyWindow(tkwin); - } + if (!(graphPtr->flags & GRAPH_DELETED)) + Tk_DestroyWindow(graphPtr->tkwin); } // called by Tcl_EventuallyFree and others static void DestroyGraph(char* dataPtr) { + printf("DestroyGraph\n"); Graph* graphPtr = (Graph*)dataPtr; - Tk_DeleteOptionTable(graphPtr->optionTable); Blt_DestroyCrosshairs(graphPtr); Blt_DestroyMarkers(graphPtr); @@ -398,6 +397,9 @@ static void DestroyGraph(char* dataPtr) if (graphPtr->cache != None) Tk_FreePixmap(graphPtr->display, graphPtr->cache); + Tk_FreeConfigOptions((char*)graphPtr, graphPtr->optionTable, graphPtr->tkwin); + Tcl_Release(graphPtr->tkwin); + graphPtr->tkwin = NULL; free(graphPtr); } @@ -421,19 +423,14 @@ static void GraphEventProc(ClientData clientData, XEvent* eventPtr) Blt_EventuallyRedrawGraph(graphPtr); } } else if (eventPtr->type == DestroyNotify) { - if (graphPtr->tkwin != NULL) { - Tk_FreeConfigOptions((char*)graphPtr, graphPtr->optionTable, - graphPtr->tkwin); - Blt_DeleteCrosshairs(graphPtr); - Blt_DeleteLegend(graphPtr); - - graphPtr->tkwin = NULL; + printf("GraphEventProc:DestroyNotify\n"); + if (!(graphPtr->flags & GRAPH_DELETED)) { + graphPtr->flags |= GRAPH_DELETED; Tcl_DeleteCommandFromToken(graphPtr->interp, graphPtr->cmdToken); + if (graphPtr->flags & REDRAW_PENDING) + Tcl_CancelIdleCall(DisplayGraph, graphPtr); + Tcl_EventuallyFree(graphPtr, DestroyGraph); } - if (graphPtr->flags & REDRAW_PENDING) { - Tcl_CancelIdleCall(DisplayGraph, graphPtr); - } - Tcl_EventuallyFree(graphPtr, DestroyGraph); } else if (eventPtr->type == ConfigureNotify) { graphPtr->flags |= (MAP_WORLD | REDRAW_WORLD); Blt_EventuallyRedrawGraph(graphPtr); @@ -570,16 +567,12 @@ static void ConfigureGraph(Graph* graphPtr) static void DisplayGraph(ClientData clientData) { Graph* graphPtr = clientData; - Pixmap drawable; - Tk_Window tkwin; - int site; + Tk_Window tkwin = graphPtr->tkwin; graphPtr->flags &= ~REDRAW_PENDING; - if (graphPtr->tkwin == NULL) { - return; /* Window has been destroyed (we - * should not get here) */ - } - tkwin = graphPtr->tkwin; + if ((graphPtr->flags & GRAPH_DELETED) || !Tk_IsMapped(tkwin)) + return; + if ((Tk_Width(tkwin) <= 1) || (Tk_Height(tkwin) <= 1)) { /* Don't bother computing the layout until the size of the window is * something reasonable. */ @@ -595,12 +588,13 @@ static void DisplayGraph(ClientData clientData) return; } /* Create a pixmap the size of the window for double buffering. */ - if (graphPtr->doubleBuffer) { + Pixmap drawable; + if (graphPtr->doubleBuffer) drawable = Tk_GetPixmap(graphPtr->display, Tk_WindowId(tkwin), graphPtr->width, graphPtr->height, Tk_Depth(tkwin)); - } else { + else drawable = Tk_WindowId(tkwin); - } + if (graphPtr->backingStore) { if ((graphPtr->cache == None) || (graphPtr->cacheWidth != graphPtr->width) || @@ -636,7 +630,7 @@ static void DisplayGraph(ClientData clientData) Blt_DrawMarkers(graphPtr, drawable, MARKER_ABOVE); Blt_DrawActiveElements(graphPtr, drawable); /* Don't draw legend in the plot area. */ - site = Blt_Legend_Site(graphPtr); + int site = Blt_Legend_Site(graphPtr); if ((site & LEGEND_PLOTAREA_MASK) && (Blt_Legend_IsRaised(graphPtr))) { Blt_DrawLegend(graphPtr, drawable); } @@ -920,11 +914,12 @@ static int nGraphOps = sizeof(graphOps) / sizeof(Blt_OpSpec); void Blt_EventuallyRedrawGraph(Graph* graphPtr) { - if ((graphPtr->tkwin != NULL) && - Tk_IsMapped(graphPtr->tkwin) && - !(graphPtr->flags & REDRAW_PENDING)) { - Tcl_DoWhenIdle(DisplayGraph, graphPtr); + if ((graphPtr->flags & GRAPH_DELETED) || !Tk_IsMapped(graphPtr->tkwin)) + return; + + if (!(graphPtr->flags & REDRAW_PENDING)) { graphPtr->flags |= REDRAW_PENDING; + Tcl_DoWhenIdle(DisplayGraph, graphPtr); } } |