4 * This file implements window items for canvas widgets.
6 * Copyright 1992 Regents of the University of California.
7 * Permission to use, copy, modify, and distribute this
8 * software and its documentation for any purpose and without
9 * fee is hereby granted, provided that the above copyright
10 * notice appear in all copies. The University of California
11 * makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without
13 * express or implied warranty.
17 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkCanvWind.c,v 1.4 92/08/24 09:24:22 ouster Exp $ SPRITE (Berkeley)";
26 * The structure below defines the record for each window item.
29 typedef struct WindowItem
{
30 Tk_Item header
; /* Generic stuff that's the same for all
31 * types. MUST BE FIRST IN STRUCTURE. */
32 double x
, y
; /* Coordinates of positioning point for
34 Tk_Window tkwin
; /* Window associated with item. NULL means
35 * window has been destroyed. */
36 int width
; /* Width to use for window (<= 0 means use
37 * window's requested width). */
38 int height
; /* Width to use for window (<= 0 means use
39 * window's requested width). */
40 Tk_Anchor anchor
; /* Where to anchor window relative to
42 Tk_Canvas
*canvasPtr
; /* Canvas containing this item. */
46 * Information used for parsing configuration specs:
49 static Tk_ConfigSpec configSpecs
[] = {
50 {TK_CONFIG_ANCHOR
, "-anchor", (char *) NULL
, (char *) NULL
,
51 "center", Tk_Offset(WindowItem
, anchor
), TK_CONFIG_DONT_SET_DEFAULT
},
52 {TK_CONFIG_PIXELS
, "-height", (char *) NULL
, (char *) NULL
,
53 "0", Tk_Offset(WindowItem
, height
), TK_CONFIG_DONT_SET_DEFAULT
},
54 {TK_CONFIG_CUSTOM
, "-tags", (char *) NULL
, (char *) NULL
,
55 (char *) NULL
, 0, TK_CONFIG_NULL_OK
, &tkCanvasTagsOption
},
56 {TK_CONFIG_PIXELS
, "-width", (char *) NULL
, (char *) NULL
,
57 "0", Tk_Offset(WindowItem
, width
), TK_CONFIG_DONT_SET_DEFAULT
},
58 {TK_CONFIG_WINDOW
, "-window", (char *) NULL
, (char *) NULL
,
59 (char *) NULL
, Tk_Offset(WindowItem
, tkwin
), TK_CONFIG_NULL_OK
},
60 {TK_CONFIG_END
, (char *) NULL
, (char *) NULL
, (char *) NULL
,
65 * Prototypes for procedures defined in this file:
68 static void ComputeWindowBbox
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
69 WindowItem
*winItemPtr
));
70 static int ConfigureWinItem
_ANSI_ARGS_((
71 Tk_Canvas
*canvasPtr
, Tk_Item
*itemPtr
, int argc
,
72 char **argv
, int flags
));
73 static int CreateWinItem
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
74 struct Tk_Item
*itemPtr
, int argc
, char **argv
));
75 static void DeleteWinItem
_ANSI_ARGS_((Tk_Item
*itemPtr
));
76 static void DisplayWinItem
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
77 Tk_Item
*itemPtr
, Drawable dst
));
78 static void ScaleWinItem
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
79 Tk_Item
*itemPtr
, double originX
, double originY
,
80 double scaleX
, double scaleY
));
81 static void TranslateWinItem
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
82 Tk_Item
*itemPtr
, double deltaX
, double deltaY
));
83 static int WinItemCoords
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
84 Tk_Item
*itemPtr
, int argc
, char **argv
));
85 static void WinItemRequestProc
_ANSI_ARGS_((ClientData clientData
,
87 static void WinItemStructureProc
_ANSI_ARGS_((
88 ClientData clientData
, XEvent
*eventPtr
));
89 static int WinItemToArea
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
90 Tk_Item
*itemPtr
, double *rectPtr
));
91 static double WinItemToPoint
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
92 Tk_Item
*itemPtr
, double *pointPtr
));
95 * The structures below defines the rectangle and oval item types
96 * by means of procedures that can be invoked by generic item code.
99 Tk_ItemType TkWindowType
= {
101 sizeof(WindowItem
), /* itemSize */
102 CreateWinItem
, /* createProc */
103 configSpecs
, /* configSpecs */
104 ConfigureWinItem
, /* configureProc */
105 WinItemCoords
, /* coordProc */
106 DeleteWinItem
, /* deleteProc */
107 DisplayWinItem
, /* displayProc */
108 1, /* alwaysRedraw */
109 WinItemToPoint
, /* pointProc */
110 WinItemToArea
, /* areaProc */
111 (Tk_ItemPostscriptProc
*) NULL
, /* postscriptProc */
112 ScaleWinItem
, /* scaleProc */
113 TranslateWinItem
, /* translateProc */
114 (Tk_ItemIndexProc
*) NULL
, /* indexProc */
115 (Tk_ItemCursorProc
*) NULL
, /* cursorProc */
116 (Tk_ItemSelectionProc
*) NULL
, /* selectionProc */
117 (Tk_ItemInsertProc
*) NULL
, /* insertProc */
118 (Tk_ItemDCharsProc
*) NULL
, /* dTextProc */
119 (Tk_ItemType
*) NULL
/* nextPtr */
123 *--------------------------------------------------------------
127 * This procedure is invoked to create a new window
131 * A standard Tcl return value. If an error occurred in
132 * creating the item, then an error message is left in
133 * canvasPtr->interp->result; in this case itemPtr is
134 * left uninitialized, so it can be safely freed by the
138 * A new window item is created.
140 *--------------------------------------------------------------
145 register Tk_Canvas
*canvasPtr
, /* Canvas to hold new item. */
146 Tk_Item
*itemPtr
, /* Record to hold new item; header
147 * has been initialized by caller. */
148 int argc
, /* Number of arguments in argv. */
149 char **argv
/* Arguments describing rectangle. */
152 register WindowItem
*winItemPtr
= (WindowItem
*) itemPtr
;
155 Tcl_AppendResult(canvasPtr
->interp
, "wrong # args: should be \"",
156 Tk_PathName(canvasPtr
->tkwin
), "\" create ",
157 itemPtr
->typePtr
->name
, " x y ?options?",
163 * Initialize item's record.
166 winItemPtr
->tkwin
= NULL
;
167 winItemPtr
->width
= 0;
168 winItemPtr
->height
= 0;
169 winItemPtr
->anchor
= TK_ANCHOR_CENTER
;
170 winItemPtr
->canvasPtr
= canvasPtr
;
173 * Process the arguments to fill in the item record.
176 if ((TkGetCanvasCoord(canvasPtr
, argv
[0], &winItemPtr
->x
) != TCL_OK
)
177 || (TkGetCanvasCoord(canvasPtr
, argv
[1],
178 &winItemPtr
->y
) != TCL_OK
)) {
182 if (ConfigureWinItem(canvasPtr
, itemPtr
, argc
-2, argv
+2, 0) != TCL_OK
) {
183 DeleteWinItem(itemPtr
);
190 *--------------------------------------------------------------
194 * This procedure is invoked to process the "coords" widget
195 * command on window items. See the user documentation for
196 * details on what it does.
199 * Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
202 * The coordinates for the given item may be changed.
204 *--------------------------------------------------------------
209 register Tk_Canvas
*canvasPtr
, /* Canvas containing item. */
210 Tk_Item
*itemPtr
, /* Item whose coordinates are to be
211 * read or modified. */
212 int argc
, /* Number of coordinates supplied in
214 char **argv
/* Array of coordinates: x1, y1,
218 register WindowItem
*winItemPtr
= (WindowItem
*) itemPtr
;
221 sprintf(canvasPtr
->interp
->result
, "%g %g", winItemPtr
->x
,
223 } else if (argc
== 2) {
224 if ((TkGetCanvasCoord(canvasPtr
, argv
[0], &winItemPtr
->x
) != TCL_OK
)
225 || (TkGetCanvasCoord(canvasPtr
, argv
[1],
226 &winItemPtr
->y
) != TCL_OK
)) {
229 ComputeWindowBbox(canvasPtr
, winItemPtr
);
231 sprintf(canvasPtr
->interp
->result
,
232 "wrong # coordinates: expected 0 or 2, got %d",
240 *--------------------------------------------------------------
242 * ConfigureWinItem --
244 * This procedure is invoked to configure various aspects
245 * of a window item, such as its anchor position.
248 * A standard Tcl result code. If an error occurs, then
249 * an error message is left in canvasPtr->interp->result.
252 * Configuration information may be set for itemPtr.
254 *--------------------------------------------------------------
259 Tk_Canvas
*canvasPtr
, /* Canvas containing itemPtr. */
260 Tk_Item
*itemPtr
, /* Window item to reconfigure. */
261 int argc
, /* Number of elements in argv. */
262 char **argv
, /* Arguments describing things to configure. */
263 int flags
/* Flags to pass to Tk_ConfigureWidget. */
266 register WindowItem
*winItemPtr
= (WindowItem
*) itemPtr
;
269 oldWindow
= winItemPtr
->tkwin
;
270 if (Tk_ConfigureWidget(canvasPtr
->interp
, canvasPtr
->tkwin
,
271 configSpecs
, argc
, argv
, (char *) winItemPtr
, flags
) != TCL_OK
) {
276 * A few of the options require additional processing.
279 if (oldWindow
!= winItemPtr
->tkwin
) {
280 if (oldWindow
!= NULL
) {
281 Tk_DeleteEventHandler(oldWindow
, StructureNotifyMask
,
282 WinItemStructureProc
, (ClientData
) winItemPtr
);
283 Tk_ManageGeometry(oldWindow
, (Tk_GeometryProc
*) NULL
,
285 Tk_UnmapWindow(oldWindow
);
287 if (winItemPtr
->tkwin
!= NULL
) {
288 Tk_Window ancestor
, parent
;
291 * Make sure that the canvas is either the parent of the
292 * window associated with the item or a descendant of that
293 * parent. Also, don't allow a top-level window to be
294 * managed inside a canvas.
297 parent
= Tk_Parent(winItemPtr
->tkwin
);
298 for (ancestor
= canvasPtr
->tkwin
; ;
299 ancestor
= Tk_Parent(ancestor
)) {
300 if (ancestor
== parent
) {
303 if (((Tk_FakeWin
*) (ancestor
))->flags
& TK_TOP_LEVEL
) {
305 Tcl_AppendResult(canvasPtr
->interp
, "can't use ",
306 Tk_PathName(winItemPtr
->tkwin
),
307 " in a window item of this canvas", (char *) NULL
);
308 winItemPtr
->tkwin
= NULL
;
312 if (((Tk_FakeWin
*) (winItemPtr
->tkwin
))->flags
& TK_TOP_LEVEL
) {
315 if (winItemPtr
->tkwin
== canvasPtr
->tkwin
) {
318 Tk_CreateEventHandler(winItemPtr
->tkwin
, StructureNotifyMask
,
319 WinItemStructureProc
, (ClientData
) winItemPtr
);
320 Tk_ManageGeometry(winItemPtr
->tkwin
, WinItemRequestProc
,
321 (ClientData
) winItemPtr
);
325 ComputeWindowBbox(canvasPtr
, winItemPtr
);
331 *--------------------------------------------------------------
335 * This procedure is called to clean up the data structure
336 * associated with a window item.
342 * Resources associated with itemPtr are released.
344 *--------------------------------------------------------------
349 Tk_Item
*itemPtr
/* Item that is being deleted. */
352 register WindowItem
*winItemPtr
= (WindowItem
*) itemPtr
;
354 if (winItemPtr
->tkwin
!= NULL
) {
355 Tk_DeleteEventHandler(winItemPtr
->tkwin
, StructureNotifyMask
,
356 WinItemStructureProc
, (ClientData
) winItemPtr
);
357 Tk_ManageGeometry(winItemPtr
->tkwin
, (Tk_GeometryProc
*) NULL
,
359 Tk_UnmapWindow(winItemPtr
->tkwin
);
364 *--------------------------------------------------------------
366 * ComputeWindowBbox --
368 * This procedure is invoked to compute the bounding box of
369 * all the pixels that may be drawn as part of a window item.
370 * This procedure is where the child window's placement is
377 * The fields x1, y1, x2, and y2 are updated in the header
380 *--------------------------------------------------------------
386 Tk_Canvas
*canvasPtr
, /* Canvas that contains item. */
387 register WindowItem
*winItemPtr
/* Item whose bbox is to be
391 int width
, height
, x
, y
;
393 x
= winItemPtr
->x
+ 0.5;
394 y
= winItemPtr
->y
+ 0.5;
396 if (winItemPtr
->tkwin
== NULL
) {
397 winItemPtr
->header
.x1
= winItemPtr
->header
.x2
= x
;
398 winItemPtr
->header
.y1
= winItemPtr
->header
.y2
= y
;
403 * Compute dimensions of window.
406 width
= winItemPtr
->width
;
408 width
= Tk_ReqWidth(winItemPtr
->tkwin
);
413 height
= winItemPtr
->height
;
415 height
= Tk_ReqHeight(winItemPtr
->tkwin
);
422 * Compute location of window, using anchor information.
425 switch (winItemPtr
->anchor
) {
452 case TK_ANCHOR_CENTER
:
459 * Store the information in the item header.
462 winItemPtr
->header
.x1
= x
;
463 winItemPtr
->header
.y1
= y
;
464 winItemPtr
->header
.x2
= x
+ width
;
465 winItemPtr
->header
.y2
= y
+ height
;
469 *--------------------------------------------------------------
473 * This procedure is invoked to "draw" a window item in a given
474 * drawable. Since the window draws itself, we needn't do any
475 * actual redisplay here. However, this procedure takes care
476 * of actually repositioning the child window so that it occupies
477 * the correct screen position.
483 * The child window's position may get changed.
485 *--------------------------------------------------------------
491 register Tk_Canvas
*canvasPtr
, /* Canvas that contains item. */
492 Tk_Item
*itemPtr
, /* Item to be displayed. */
493 Drawable drawable
/* Pixmap or window in which to draw
497 register WindowItem
*winItemPtr
= (WindowItem
*) itemPtr
;
498 int x
,y
, width
, height
;
499 Tk_Window ancestor
, parent
;
501 if (winItemPtr
->tkwin
== NULL
) {
504 x
= winItemPtr
->header
.x1
- canvasPtr
->xOrigin
;
505 y
= winItemPtr
->header
.y1
- canvasPtr
->yOrigin
;
506 width
= winItemPtr
->header
.x2
- winItemPtr
->header
.x1
;
507 height
= winItemPtr
->header
.y2
- winItemPtr
->header
.y1
;
510 * If the canvas isn't the parent of the window, then translate the
511 * coordinates from those of the canvas to those of the window's
515 parent
= Tk_Parent(winItemPtr
->tkwin
);
516 for (ancestor
= canvasPtr
->tkwin
; ancestor
!= parent
;
517 ancestor
= Tk_Parent(ancestor
)) {
518 x
+= Tk_X(ancestor
) + Tk_Changes(ancestor
)->border_width
;
519 y
+= Tk_Y(ancestor
) + Tk_Changes(ancestor
)->border_width
;
523 * Reconfigure the window if it isn't already in the correct place.
526 if ((x
!= Tk_X(winItemPtr
->tkwin
)) || (y
!= Tk_Y(winItemPtr
->tkwin
))
527 || (width
!= Tk_Width(winItemPtr
->tkwin
))
528 || (height
!= Tk_Height(winItemPtr
->tkwin
))) {
529 Tk_MoveResizeWindow(winItemPtr
->tkwin
, x
, y
, (unsigned int) width
,
530 (unsigned int) height
);
532 if (!Tk_IsMapped(winItemPtr
->tkwin
)) {
533 Tk_MapWindow(winItemPtr
->tkwin
);
538 *--------------------------------------------------------------
542 * Computes the distance from a given point to a given
543 * rectangle, in canvas units.
546 * The return value is 0 if the point whose x and y coordinates
547 * are coordPtr[0] and coordPtr[1] is inside the window. If the
548 * point isn't inside the window then the return value is the
549 * distance from the point to the window.
554 *--------------------------------------------------------------
560 Tk_Canvas
*canvasPtr
, /* Canvas containing item. */
561 Tk_Item
*itemPtr
, /* Item to check against point. */
562 double *pointPtr
/* Pointer to x and y coordinates. */
565 register WindowItem
*winItemPtr
= (WindowItem
*) itemPtr
;
566 double x1
, x2
, y1
, y2
, xDiff
, yDiff
;
568 x1
= winItemPtr
->header
.x1
;
569 y1
= winItemPtr
->header
.y1
;
570 x2
= winItemPtr
->header
.x2
;
571 y2
= winItemPtr
->header
.y2
;
574 * Point is outside rectangle.
577 if (pointPtr
[0] < x1
) {
578 xDiff
= x1
- pointPtr
[0];
579 } else if (pointPtr
[0] > x2
) {
580 xDiff
= pointPtr
[0] - x2
;
585 if (pointPtr
[1] < y1
) {
586 yDiff
= y1
- pointPtr
[1];
587 } else if (pointPtr
[1] > y2
) {
588 yDiff
= pointPtr
[1] - y2
;
593 return hypot(xDiff
, yDiff
);
597 *--------------------------------------------------------------
601 * This procedure is called to determine whether an item
602 * lies entirely inside, entirely outside, or overlapping
606 * -1 is returned if the item is entirely outside the area
607 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
608 * inside the given area.
613 *--------------------------------------------------------------
619 Tk_Canvas
*canvasPtr
, /* Canvas containing item. */
620 Tk_Item
*itemPtr
, /* Item to check against rectangle. */
621 double *rectPtr
/* Pointer to array of four coordinates
622 * (x1, y1, x2, y2) describing rectangular
626 register WindowItem
*winItemPtr
= (WindowItem
*) itemPtr
;
628 if ((rectPtr
[2] <= winItemPtr
->header
.x1
)
629 || (rectPtr
[0] >= winItemPtr
->header
.x2
)
630 || (rectPtr
[3] <= winItemPtr
->header
.y1
)
631 || (rectPtr
[1] >= winItemPtr
->header
.y2
)) {
634 if ((rectPtr
[0] <= winItemPtr
->header
.x1
)
635 && (rectPtr
[1] <= winItemPtr
->header
.y1
)
636 && (rectPtr
[2] >= winItemPtr
->header
.x2
)
637 && (rectPtr
[3] >= winItemPtr
->header
.y2
)) {
644 *--------------------------------------------------------------
648 * This procedure is invoked to rescale a rectangle or oval
655 * The rectangle or oval referred to by itemPtr is rescaled
656 * so that the following transformation is applied to all
658 * x' = originX + scaleX*(x-originX)
659 * y' = originY + scaleY*(y-originY)
661 *--------------------------------------------------------------
666 Tk_Canvas
*canvasPtr
, /* Canvas containing rectangle. */
667 Tk_Item
*itemPtr
, /* Rectangle to be scaled. */
669 double originY
, /* Origin about which to scale rect. */
670 double scaleX
, /* Amount to scale in X direction. */
671 double scaleY
/* Amount to scale in Y direction. */
674 register WindowItem
*winItemPtr
= (WindowItem
*) itemPtr
;
676 winItemPtr
->x
= originX
+ scaleX
*(winItemPtr
->x
- originX
);
677 winItemPtr
->y
= originY
+ scaleY
*(winItemPtr
->y
- originY
);
678 if (winItemPtr
->width
> 0) {
679 winItemPtr
->width
= scaleY
*winItemPtr
->width
;
681 if (winItemPtr
->height
> 0) {
682 winItemPtr
->height
= scaleY
*winItemPtr
->height
;
684 ComputeWindowBbox(canvasPtr
, winItemPtr
);
688 *--------------------------------------------------------------
690 * TranslateWinItem --
692 * This procedure is called to move a rectangle or oval by a
699 * The position of the rectangle or oval is offset by
700 * (xDelta, yDelta), and the bounding box is updated in the
701 * generic part of the item structure.
703 *--------------------------------------------------------------
708 Tk_Canvas
*canvasPtr
, /* Canvas containing item. */
709 Tk_Item
*itemPtr
, /* Item that is being moved. */
711 double deltaY
/* Amount by which item is to be
715 register WindowItem
*winItemPtr
= (WindowItem
*) itemPtr
;
717 winItemPtr
->x
+= deltaX
;
718 winItemPtr
->y
+= deltaY
;
719 ComputeWindowBbox(canvasPtr
, winItemPtr
);
723 *--------------------------------------------------------------
725 * WinItemStructureProc --
727 * This procedure is invoked whenever StructureNotify events
728 * occur for a window that's managed as part of a canvas window
729 * item. This procudure's only purpose is to clean up when
730 * windows are deleted.
736 * The window is disassociated from the window item when it is
739 *--------------------------------------------------------------
743 WinItemStructureProc (
744 ClientData clientData
, /* Pointer to record describing window item. */
745 XEvent
*eventPtr
/* Describes what just happened. */
748 register WindowItem
*winItemPtr
= (WindowItem
*) clientData
;
750 if (eventPtr
->type
== DestroyNotify
) {
751 winItemPtr
->tkwin
= NULL
;
756 *--------------------------------------------------------------
758 * WinItemRequestProc --
760 * This procedure is invoked whenever a window that's associated
761 * with a window canvas item changes its requested dimensions.
767 * The size and location on the screen of the window may change,
768 * depending on the options specified for the window item.
770 *--------------------------------------------------------------
776 ClientData clientData
, /* Pointer to record for window item. */
777 Tk_Window tkwin
/* Window that changed its desired
781 WindowItem
*winItemPtr
= (WindowItem
*) clientData
;
783 ComputeWindowBbox(winItemPtr
->canvasPtr
, winItemPtr
);
784 DisplayWinItem(winItemPtr
->canvasPtr
, (Tk_Item
*) winItemPtr
,