📄 tkcanvwind.c
字号:
/* * tkCanvWind.c -- * * This file implements window items for canvas widgets. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tkCanvWind.c 1.29 97/10/14 10:40:54 */#include <stdio.h>#include "tkInt.h"#include "tkPort.h"#include "tkCanvas.h"/* * The structure below defines the record for each window item. */typedef struct WindowItem { Tk_Item header; /* Generic stuff that's the same for all * types. MUST BE FIRST IN STRUCTURE. */ double x, y; /* Coordinates of positioning point for * window. */ Tk_Window tkwin; /* Window associated with item. NULL means * window has been destroyed. */ int width; /* Width to use for window (<= 0 means use * window's requested width). */ int height; /* Width to use for window (<= 0 means use * window's requested width). */ Tk_Anchor anchor; /* Where to anchor window relative to * (x,y). */ Tk_Canvas canvas; /* Canvas containing this item. */} WindowItem;/* * Information used for parsing configuration specs: */static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, (ClientData) NULL};static Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL, "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT}, {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL, "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT}, {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL, "0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT}, {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK}, {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, 0}};/* * Prototypes for procedures defined in this file: */static void ComputeWindowBbox _ANSI_ARGS_((Tk_Canvas canvas, WindowItem *winItemPtr));static int ConfigureWinItem _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, char **argv, int flags));static int CreateWinItem _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, int argc, char **argv));static void DeleteWinItem _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, Display *display));static void DisplayWinItem _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, int x, int y, int width, int height));static void ScaleWinItem _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, double scaleX, double scaleY));static void TranslateWinItem _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY));static int WinItemCoords _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, char **argv));static void WinItemLostSlaveProc _ANSI_ARGS_(( ClientData clientData, Tk_Window tkwin));static void WinItemRequestProc _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin));static void WinItemStructureProc _ANSI_ARGS_(( ClientData clientData, XEvent *eventPtr));static int WinItemToArea _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, double *rectPtr));static double WinItemToPoint _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, double *pointPtr));/* * The structure below defines the window item type by means of procedures * that can be invoked by generic item code. */Tk_ItemType tkWindowType = { "window", /* name */ sizeof(WindowItem), /* itemSize */ CreateWinItem, /* createProc */ configSpecs, /* configSpecs */ ConfigureWinItem, /* configureProc */ WinItemCoords, /* coordProc */ DeleteWinItem, /* deleteProc */ DisplayWinItem, /* displayProc */ 1, /* alwaysRedraw */ WinItemToPoint, /* pointProc */ WinItemToArea, /* areaProc */ (Tk_ItemPostscriptProc *) NULL, /* postscriptProc */ ScaleWinItem, /* scaleProc */ TranslateWinItem, /* translateProc */ (Tk_ItemIndexProc *) NULL, /* indexProc */ (Tk_ItemCursorProc *) NULL, /* cursorProc */ (Tk_ItemSelectionProc *) NULL, /* selectionProc */ (Tk_ItemInsertProc *) NULL, /* insertProc */ (Tk_ItemDCharsProc *) NULL, /* dTextProc */ (Tk_ItemType *) NULL /* nextPtr */};/* * The structure below defines the official type record for the * placer: */static Tk_GeomMgr canvasGeomType = { "canvas", /* name */ WinItemRequestProc, /* requestProc */ WinItemLostSlaveProc, /* lostSlaveProc */};/* *-------------------------------------------------------------- * * CreateWinItem -- * * This procedure is invoked to create a new window * item in a canvas. * * Results: * A standard Tcl return value. If an error occurred in * creating the item, then an error message is left in * interp->result; in this case itemPtr is * left uninitialized, so it can be safely freed by the * caller. * * Side effects: * A new window item is created. * *-------------------------------------------------------------- */static intCreateWinItem(interp, canvas, itemPtr, argc, argv) Tcl_Interp *interp; /* Interpreter for error reporting. */ Tk_Canvas canvas; /* Canvas to hold new item. */ Tk_Item *itemPtr; /* Record to hold new item; header * has been initialized by caller. */ int argc; /* Number of arguments in argv. */ char **argv; /* Arguments describing rectangle. */{ WindowItem *winItemPtr = (WindowItem *) itemPtr; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", Tk_PathName(Tk_CanvasTkwin(canvas)), " create ", itemPtr->typePtr->name, " x y ?options?\"", (char *) NULL); return TCL_ERROR; } /* * Initialize item's record. */ winItemPtr->tkwin = NULL; winItemPtr->width = 0; winItemPtr->height = 0; winItemPtr->anchor = TK_ANCHOR_CENTER; winItemPtr->canvas = canvas; /* * Process the arguments to fill in the item record. */ if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x) != TCL_OK) || (Tk_CanvasGetCoord(interp, canvas, argv[1], &winItemPtr->y) != TCL_OK)) { return TCL_ERROR; } if (ConfigureWinItem(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) { DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; } return TCL_OK;}/* *-------------------------------------------------------------- * * WinItemCoords -- * * This procedure is invoked to process the "coords" widget * command on window items. See the user documentation for * details on what it does. * * Results: * Returns TCL_OK or TCL_ERROR, and sets interp->result. * * Side effects: * The coordinates for the given item may be changed. * *-------------------------------------------------------------- */static intWinItemCoords(interp, canvas, itemPtr, argc, argv) Tcl_Interp *interp; /* Used for error reporting. */ Tk_Canvas canvas; /* Canvas containing item. */ Tk_Item *itemPtr; /* Item whose coordinates are to be * read or modified. */ int argc; /* Number of coordinates supplied in * argv. */ char **argv; /* Array of coordinates: x1, y1, * x2, y2, ... */{ WindowItem *winItemPtr = (WindowItem *) itemPtr; char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE]; if (argc == 0) { Tcl_PrintDouble(interp, winItemPtr->x, x); Tcl_PrintDouble(interp, winItemPtr->y, y); Tcl_AppendResult(interp, x, " ", y, (char *) NULL); } else if (argc == 2) { if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x) != TCL_OK) || (Tk_CanvasGetCoord(interp, canvas, argv[1], &winItemPtr->y) != TCL_OK)) { return TCL_ERROR; } ComputeWindowBbox(canvas, winItemPtr); } else { sprintf(interp->result, "wrong # coordinates: expected 0 or 2, got %d", argc); return TCL_ERROR; } return TCL_OK;}/* *-------------------------------------------------------------- * * ConfigureWinItem -- * * This procedure is invoked to configure various aspects * of a window item, such as its anchor position. * * Results: * A standard Tcl result code. If an error occurs, then * an error message is left in interp->result. * * Side effects: * Configuration information may be set for itemPtr. * *-------------------------------------------------------------- */static intConfigureWinItem(interp, canvas, itemPtr, argc, argv, flags) Tcl_Interp *interp; /* Used for error reporting. */ Tk_Canvas canvas; /* Canvas containing itemPtr. */ Tk_Item *itemPtr; /* Window item to reconfigure. */ int argc; /* Number of elements in argv. */ char **argv; /* Arguments describing things to configure. */ int flags; /* Flags to pass to Tk_ConfigureWidget. */{ WindowItem *winItemPtr = (WindowItem *) itemPtr; Tk_Window oldWindow; Tk_Window canvasTkwin; oldWindow = winItemPtr->tkwin; canvasTkwin = Tk_CanvasTkwin(canvas); if (Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, argc, argv, (char *) winItemPtr, flags) != TCL_OK) { return TCL_ERROR; } /* * A few of the options require additional processing. */ if (oldWindow != winItemPtr->tkwin) { if (oldWindow != NULL) { Tk_DeleteEventHandler(oldWindow, StructureNotifyMask, WinItemStructureProc, (ClientData) winItemPtr); Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL, (ClientData) NULL); Tk_UnmaintainGeometry(oldWindow, canvasTkwin); Tk_UnmapWindow(oldWindow); } if (winItemPtr->tkwin != NULL) { Tk_Window ancestor, parent; /* * Make sure that the canvas is either the parent of the * window associated with the item or a descendant of that * parent. Also, don't allow a top-level window to be * managed inside a canvas. */ parent = Tk_Parent(winItemPtr->tkwin); for (ancestor = canvasTkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { break; } if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_LEVEL) { badWindow: Tcl_AppendResult(interp, "can't use ", Tk_PathName(winItemPtr->tkwin), " in a window item of this canvas", (char *) NULL); winItemPtr->tkwin = NULL; return TCL_ERROR; } } if (((Tk_FakeWin *) (winItemPtr->tkwin))->flags & TK_TOP_LEVEL) { goto badWindow; } if (winItemPtr->tkwin == canvasTkwin) { goto badWindow; } Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask, WinItemStructureProc, (ClientData) winItemPtr); Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType, (ClientData) winItemPtr); } } ComputeWindowBbox(canvas, winItemPtr); return TCL_OK;}/* *-------------------------------------------------------------- * * DeleteWinItem -- * * This procedure is called to clean up the data structure * associated with a window item. * * Results: * None. * * Side effects: * Resources associated with itemPtr are released. * *-------------------------------------------------------------- */static voidDeleteWinItem(canvas, itemPtr, display) Tk_Canvas canvas; /* Overall info about widget. */ Tk_Item *itemPtr; /* Item that is being deleted. */ Display *display; /* Display containing window for * canvas. */{ WindowItem *winItemPtr = (WindowItem *) itemPtr; Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas); if (winItemPtr->tkwin != NULL) { Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask, WinItemStructureProc, (ClientData) winItemPtr); Tk_ManageGeometry(winItemPtr->tkwin, (Tk_GeomMgr *) NULL, (ClientData) NULL); if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } Tk_UnmapWindow(winItemPtr->tkwin); }}/* *-------------------------------------------------------------- * * ComputeWindowBbox -- * * This procedure is invoked to compute the bounding box of * all the pixels that may be drawn as part of a window item. * This procedure is where the child window's placement is * computed. * * Results: * None. * * Side effects: * The fields x1, y1, x2, and y2 are updated in the header * for itemPtr. * *-------------------------------------------------------------- */static voidComputeWindowBbox(canvas, winItemPtr) Tk_Canvas canvas; /* Canvas that contains item. */ WindowItem *winItemPtr; /* Item whose bbox is to be * recomputed. */{ int width, height, x, y; x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5)); y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5)); if (winItemPtr->tkwin == NULL) { /* * There is no window for this item yet. Just give it a 1x1 * bounding box. Don't give it a 0x0 bounding box; there are * strange cases where this bounding box might be used as the * dimensions of the window, and 0x0 causes problems under X. */ winItemPtr->header.x1 = x; winItemPtr->header.x2 = winItemPtr->header.x1 + 1; winItemPtr->header.y1 = y;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -