]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * tkCanvWind.c -- | |
3 | * | |
4 | * This file implements window items for canvas widgets. | |
5 | * | |
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. | |
14 | */ | |
15 | ||
16 | #ifndef lint | |
17 | static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkCanvWind.c,v 1.4 92/08/24 09:24:22 ouster Exp $ SPRITE (Berkeley)"; | |
18 | #endif | |
19 | ||
20 | #include <stdio.h> | |
21 | #include <math.h> | |
22 | #include "tkint.h" | |
23 | #include "tkcanvas.h" | |
24 | ||
25 | /* | |
26 | * The structure below defines the record for each window item. | |
27 | */ | |
28 | ||
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 | |
33 | * window. */ | |
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 | |
41 | * (x,y). */ | |
42 | Tk_Canvas *canvasPtr; /* Canvas containing this item. */ | |
43 | } WindowItem; | |
44 | ||
45 | /* | |
46 | * Information used for parsing configuration specs: | |
47 | */ | |
48 | ||
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, | |
61 | (char *) NULL, 0, 0} | |
62 | }; | |
63 | ||
64 | /* | |
65 | * Prototypes for procedures defined in this file: | |
66 | */ | |
67 | ||
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, | |
86 | Tk_Window tkwin)); | |
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)); | |
93 | ||
94 | /* | |
95 | * The structures below defines the rectangle and oval item types | |
96 | * by means of procedures that can be invoked by generic item code. | |
97 | */ | |
98 | ||
99 | Tk_ItemType TkWindowType = { | |
100 | "window", /* name */ | |
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 */ | |
120 | }; | |
121 | \f | |
122 | /* | |
123 | *-------------------------------------------------------------- | |
124 | * | |
125 | * CreateWinItem -- | |
126 | * | |
127 | * This procedure is invoked to create a new window | |
128 | * item in a canvas. | |
129 | * | |
130 | * Results: | |
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 | |
135 | * caller. | |
136 | * | |
137 | * Side effects: | |
138 | * A new window item is created. | |
139 | * | |
140 | *-------------------------------------------------------------- | |
141 | */ | |
142 | ||
143 | static int | |
144 | CreateWinItem(canvasPtr, itemPtr, argc, argv) | |
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. */ | |
150 | { | |
151 | register WindowItem *winItemPtr = (WindowItem *) itemPtr; | |
152 | ||
153 | if (argc < 2) { | |
154 | Tcl_AppendResult(canvasPtr->interp, "wrong # args: should be \"", | |
155 | Tk_PathName(canvasPtr->tkwin), "\" create ", | |
156 | itemPtr->typePtr->name, " x y ?options?", | |
157 | (char *) NULL); | |
158 | return TCL_ERROR; | |
159 | } | |
160 | ||
161 | /* | |
162 | * Initialize item's record. | |
163 | */ | |
164 | ||
165 | winItemPtr->tkwin = NULL; | |
166 | winItemPtr->width = 0; | |
167 | winItemPtr->height = 0; | |
168 | winItemPtr->anchor = TK_ANCHOR_CENTER; | |
169 | winItemPtr->canvasPtr = canvasPtr; | |
170 | ||
171 | /* | |
172 | * Process the arguments to fill in the item record. | |
173 | */ | |
174 | ||
175 | if ((TkGetCanvasCoord(canvasPtr, argv[0], &winItemPtr->x) != TCL_OK) | |
176 | || (TkGetCanvasCoord(canvasPtr, argv[1], | |
177 | &winItemPtr->y) != TCL_OK)) { | |
178 | return TCL_ERROR; | |
179 | } | |
180 | ||
181 | if (ConfigureWinItem(canvasPtr, itemPtr, argc-2, argv+2, 0) != TCL_OK) { | |
182 | DeleteWinItem(itemPtr); | |
183 | return TCL_ERROR; | |
184 | } | |
185 | return TCL_OK; | |
186 | } | |
187 | \f | |
188 | /* | |
189 | *-------------------------------------------------------------- | |
190 | * | |
191 | * WinItemCoords -- | |
192 | * | |
193 | * This procedure is invoked to process the "coords" widget | |
194 | * command on window items. See the user documentation for | |
195 | * details on what it does. | |
196 | * | |
197 | * Results: | |
198 | * Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result. | |
199 | * | |
200 | * Side effects: | |
201 | * The coordinates for the given item may be changed. | |
202 | * | |
203 | *-------------------------------------------------------------- | |
204 | */ | |
205 | ||
206 | static int | |
207 | WinItemCoords(canvasPtr, itemPtr, argc, argv) | |
208 | register Tk_Canvas *canvasPtr; /* Canvas containing item. */ | |
209 | Tk_Item *itemPtr; /* Item whose coordinates are to be | |
210 | * read or modified. */ | |
211 | int argc; /* Number of coordinates supplied in | |
212 | * argv. */ | |
213 | char **argv; /* Array of coordinates: x1, y1, | |
214 | * x2, y2, ... */ | |
215 | { | |
216 | register WindowItem *winItemPtr = (WindowItem *) itemPtr; | |
217 | ||
218 | if (argc == 0) { | |
219 | sprintf(canvasPtr->interp->result, "%g %g", winItemPtr->x, | |
220 | winItemPtr->y); | |
221 | } else if (argc == 2) { | |
222 | if ((TkGetCanvasCoord(canvasPtr, argv[0], &winItemPtr->x) != TCL_OK) | |
223 | || (TkGetCanvasCoord(canvasPtr, argv[1], | |
224 | &winItemPtr->y) != TCL_OK)) { | |
225 | return TCL_ERROR; | |
226 | } | |
227 | ComputeWindowBbox(canvasPtr, winItemPtr); | |
228 | } else { | |
229 | sprintf(canvasPtr->interp->result, | |
230 | "wrong # coordinates: expected 0 or 2, got %d", | |
231 | argc); | |
232 | return TCL_ERROR; | |
233 | } | |
234 | return TCL_OK; | |
235 | } | |
236 | \f | |
237 | /* | |
238 | *-------------------------------------------------------------- | |
239 | * | |
240 | * ConfigureWinItem -- | |
241 | * | |
242 | * This procedure is invoked to configure various aspects | |
243 | * of a window item, such as its anchor position. | |
244 | * | |
245 | * Results: | |
246 | * A standard Tcl result code. If an error occurs, then | |
247 | * an error message is left in canvasPtr->interp->result. | |
248 | * | |
249 | * Side effects: | |
250 | * Configuration information may be set for itemPtr. | |
251 | * | |
252 | *-------------------------------------------------------------- | |
253 | */ | |
254 | ||
255 | static int | |
256 | ConfigureWinItem(canvasPtr, itemPtr, argc, argv, flags) | |
257 | Tk_Canvas *canvasPtr; /* Canvas containing itemPtr. */ | |
258 | Tk_Item *itemPtr; /* Window item to reconfigure. */ | |
259 | int argc; /* Number of elements in argv. */ | |
260 | char **argv; /* Arguments describing things to configure. */ | |
261 | int flags; /* Flags to pass to Tk_ConfigureWidget. */ | |
262 | { | |
263 | register WindowItem *winItemPtr = (WindowItem *) itemPtr; | |
264 | Tk_Window oldWindow; | |
265 | ||
266 | oldWindow = winItemPtr->tkwin; | |
267 | if (Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin, | |
268 | configSpecs, argc, argv, (char *) winItemPtr, flags) != TCL_OK) { | |
269 | return TCL_ERROR; | |
270 | } | |
271 | ||
272 | /* | |
273 | * A few of the options require additional processing. | |
274 | */ | |
275 | ||
276 | if (oldWindow != winItemPtr->tkwin) { | |
277 | if (oldWindow != NULL) { | |
278 | Tk_DeleteEventHandler(oldWindow, StructureNotifyMask, | |
279 | WinItemStructureProc, (ClientData) winItemPtr); | |
280 | Tk_ManageGeometry(oldWindow, (Tk_GeometryProc *) NULL, | |
281 | (ClientData) NULL); | |
282 | Tk_UnmapWindow(oldWindow); | |
283 | } | |
284 | if (winItemPtr->tkwin != NULL) { | |
285 | Tk_Window ancestor, parent; | |
286 | ||
287 | /* | |
288 | * Make sure that the canvas is either the parent of the | |
289 | * window associated with the item or a descendant of that | |
290 | * parent. Also, don't allow a top-level window to be | |
291 | * managed inside a canvas. | |
292 | */ | |
293 | ||
294 | parent = Tk_Parent(winItemPtr->tkwin); | |
295 | for (ancestor = canvasPtr->tkwin; ; | |
296 | ancestor = Tk_Parent(ancestor)) { | |
297 | if (ancestor == parent) { | |
298 | break; | |
299 | } | |
300 | if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_LEVEL) { | |
301 | badWindow: | |
302 | Tcl_AppendResult(canvasPtr->interp, "can't use ", | |
303 | Tk_PathName(winItemPtr->tkwin), | |
304 | " in a window item of this canvas", (char *) NULL); | |
305 | winItemPtr->tkwin = NULL; | |
306 | return TCL_ERROR; | |
307 | } | |
308 | } | |
309 | if (((Tk_FakeWin *) (winItemPtr->tkwin))->flags & TK_TOP_LEVEL) { | |
310 | goto badWindow; | |
311 | } | |
312 | if (winItemPtr->tkwin == canvasPtr->tkwin) { | |
313 | goto badWindow; | |
314 | } | |
315 | Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask, | |
316 | WinItemStructureProc, (ClientData) winItemPtr); | |
317 | Tk_ManageGeometry(winItemPtr->tkwin, WinItemRequestProc, | |
318 | (ClientData) winItemPtr); | |
319 | } | |
320 | } | |
321 | ||
322 | ComputeWindowBbox(canvasPtr, winItemPtr); | |
323 | ||
324 | return TCL_OK; | |
325 | } | |
326 | \f | |
327 | /* | |
328 | *-------------------------------------------------------------- | |
329 | * | |
330 | * DeleteWinItem -- | |
331 | * | |
332 | * This procedure is called to clean up the data structure | |
333 | * associated with a window item. | |
334 | * | |
335 | * Results: | |
336 | * None. | |
337 | * | |
338 | * Side effects: | |
339 | * Resources associated with itemPtr are released. | |
340 | * | |
341 | *-------------------------------------------------------------- | |
342 | */ | |
343 | ||
344 | static void | |
345 | DeleteWinItem(itemPtr) | |
346 | Tk_Item *itemPtr; /* Item that is being deleted. */ | |
347 | { | |
348 | register WindowItem *winItemPtr = (WindowItem *) itemPtr; | |
349 | ||
350 | if (winItemPtr->tkwin != NULL) { | |
351 | Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask, | |
352 | WinItemStructureProc, (ClientData) winItemPtr); | |
353 | Tk_ManageGeometry(winItemPtr->tkwin, (Tk_GeometryProc *) NULL, | |
354 | (ClientData) NULL); | |
355 | Tk_UnmapWindow(winItemPtr->tkwin); | |
356 | } | |
357 | } | |
358 | \f | |
359 | /* | |
360 | *-------------------------------------------------------------- | |
361 | * | |
362 | * ComputeWindowBbox -- | |
363 | * | |
364 | * This procedure is invoked to compute the bounding box of | |
365 | * all the pixels that may be drawn as part of a window item. | |
366 | * This procedure is where the child window's placement is | |
367 | * computed. | |
368 | * | |
369 | * Results: | |
370 | * None. | |
371 | * | |
372 | * Side effects: | |
373 | * The fields x1, y1, x2, and y2 are updated in the header | |
374 | * for itemPtr. | |
375 | * | |
376 | *-------------------------------------------------------------- | |
377 | */ | |
378 | ||
379 | /* ARGSUSED */ | |
380 | static void | |
381 | ComputeWindowBbox(canvasPtr, winItemPtr) | |
382 | Tk_Canvas *canvasPtr; /* Canvas that contains item. */ | |
383 | register WindowItem *winItemPtr; /* Item whose bbox is to be | |
384 | * recomputed. */ | |
385 | { | |
386 | int width, height, x, y; | |
387 | ||
388 | x = winItemPtr->x + 0.5; | |
389 | y = winItemPtr->y + 0.5; | |
390 | ||
391 | if (winItemPtr->tkwin == NULL) { | |
392 | winItemPtr->header.x1 = winItemPtr->header.x2 = x; | |
393 | winItemPtr->header.y1 = winItemPtr->header.y2 = y; | |
394 | return; | |
395 | } | |
396 | ||
397 | /* | |
398 | * Compute dimensions of window. | |
399 | */ | |
400 | ||
401 | width = winItemPtr->width; | |
402 | if (width <= 0) { | |
403 | width = Tk_ReqWidth(winItemPtr->tkwin); | |
404 | if (width <= 0) { | |
405 | width = 1; | |
406 | } | |
407 | } | |
408 | height = winItemPtr->height; | |
409 | if (height <= 0) { | |
410 | height = Tk_ReqHeight(winItemPtr->tkwin); | |
411 | if (height <= 0) { | |
412 | height = 1; | |
413 | } | |
414 | } | |
415 | ||
416 | /* | |
417 | * Compute location of window, using anchor information. | |
418 | */ | |
419 | ||
420 | switch (winItemPtr->anchor) { | |
421 | case TK_ANCHOR_N: | |
422 | x -= width/2; | |
423 | break; | |
424 | case TK_ANCHOR_NE: | |
425 | x -= width; | |
426 | break; | |
427 | case TK_ANCHOR_E: | |
428 | x -= width; | |
429 | y -= height/2; | |
430 | break; | |
431 | case TK_ANCHOR_SE: | |
432 | x -= width; | |
433 | y -= height; | |
434 | break; | |
435 | case TK_ANCHOR_S: | |
436 | x -= width/2; | |
437 | y -= height; | |
438 | break; | |
439 | case TK_ANCHOR_SW: | |
440 | y -= height; | |
441 | break; | |
442 | case TK_ANCHOR_W: | |
443 | y -= height/2; | |
444 | break; | |
445 | case TK_ANCHOR_NW: | |
446 | break; | |
447 | case TK_ANCHOR_CENTER: | |
448 | x -= width/2; | |
449 | y -= height/2; | |
450 | break; | |
451 | } | |
452 | ||
453 | /* | |
454 | * Store the information in the item header. | |
455 | */ | |
456 | ||
457 | winItemPtr->header.x1 = x; | |
458 | winItemPtr->header.y1 = y; | |
459 | winItemPtr->header.x2 = x + width; | |
460 | winItemPtr->header.y2 = y + height; | |
461 | } | |
462 | \f | |
463 | /* | |
464 | *-------------------------------------------------------------- | |
465 | * | |
466 | * DisplayWinItem -- | |
467 | * | |
468 | * This procedure is invoked to "draw" a window item in a given | |
469 | * drawable. Since the window draws itself, we needn't do any | |
470 | * actual redisplay here. However, this procedure takes care | |
471 | * of actually repositioning the child window so that it occupies | |
472 | * the correct screen position. | |
473 | * | |
474 | * Results: | |
475 | * None. | |
476 | * | |
477 | * Side effects: | |
478 | * The child window's position may get changed. | |
479 | * | |
480 | *-------------------------------------------------------------- | |
481 | */ | |
482 | ||
483 | /* ARGSUSED */ | |
484 | static void | |
485 | DisplayWinItem(canvasPtr, itemPtr, drawable) | |
486 | register Tk_Canvas *canvasPtr; /* Canvas that contains item. */ | |
487 | Tk_Item *itemPtr; /* Item to be displayed. */ | |
488 | Drawable drawable; /* Pixmap or window in which to draw | |
489 | * item. */ | |
490 | { | |
491 | register WindowItem *winItemPtr = (WindowItem *) itemPtr; | |
492 | int x,y, width, height; | |
493 | Tk_Window ancestor, parent; | |
494 | ||
495 | if (winItemPtr->tkwin == NULL) { | |
496 | return; | |
497 | } | |
498 | x = winItemPtr->header.x1 - canvasPtr->xOrigin; | |
499 | y = winItemPtr->header.y1 - canvasPtr->yOrigin; | |
500 | width = winItemPtr->header.x2 - winItemPtr->header.x1; | |
501 | height = winItemPtr->header.y2 - winItemPtr->header.y1; | |
502 | ||
503 | /* | |
504 | * If the canvas isn't the parent of the window, then translate the | |
505 | * coordinates from those of the canvas to those of the window's | |
506 | * parent. | |
507 | */ | |
508 | ||
509 | parent = Tk_Parent(winItemPtr->tkwin); | |
510 | for (ancestor = canvasPtr->tkwin; ancestor != parent; | |
511 | ancestor = Tk_Parent(ancestor)) { | |
512 | x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width; | |
513 | y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width; | |
514 | } | |
515 | ||
516 | /* | |
517 | * Reconfigure the window if it isn't already in the correct place. | |
518 | */ | |
519 | ||
520 | if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin)) | |
521 | || (width != Tk_Width(winItemPtr->tkwin)) | |
522 | || (height != Tk_Height(winItemPtr->tkwin))) { | |
523 | Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, (unsigned int) width, | |
524 | (unsigned int) height); | |
525 | } | |
526 | if (!Tk_IsMapped(winItemPtr->tkwin)) { | |
527 | Tk_MapWindow(winItemPtr->tkwin); | |
528 | } | |
529 | } | |
530 | \f | |
531 | /* | |
532 | *-------------------------------------------------------------- | |
533 | * | |
534 | * WinItemToPoint -- | |
535 | * | |
536 | * Computes the distance from a given point to a given | |
537 | * rectangle, in canvas units. | |
538 | * | |
539 | * Results: | |
540 | * The return value is 0 if the point whose x and y coordinates | |
541 | * are coordPtr[0] and coordPtr[1] is inside the window. If the | |
542 | * point isn't inside the window then the return value is the | |
543 | * distance from the point to the window. | |
544 | * | |
545 | * Side effects: | |
546 | * None. | |
547 | * | |
548 | *-------------------------------------------------------------- | |
549 | */ | |
550 | ||
551 | /* ARGSUSED */ | |
552 | static double | |
553 | WinItemToPoint(canvasPtr, itemPtr, pointPtr) | |
554 | Tk_Canvas *canvasPtr; /* Canvas containing item. */ | |
555 | Tk_Item *itemPtr; /* Item to check against point. */ | |
556 | double *pointPtr; /* Pointer to x and y coordinates. */ | |
557 | { | |
558 | register WindowItem *winItemPtr = (WindowItem *) itemPtr; | |
559 | double x1, x2, y1, y2, xDiff, yDiff; | |
560 | ||
561 | x1 = winItemPtr->header.x1; | |
562 | y1 = winItemPtr->header.y1; | |
563 | x2 = winItemPtr->header.x2; | |
564 | y2 = winItemPtr->header.y2; | |
565 | ||
566 | /* | |
567 | * Point is outside rectangle. | |
568 | */ | |
569 | ||
570 | if (pointPtr[0] < x1) { | |
571 | xDiff = x1 - pointPtr[0]; | |
572 | } else if (pointPtr[0] > x2) { | |
573 | xDiff = pointPtr[0] - x2; | |
574 | } else { | |
575 | xDiff = 0; | |
576 | } | |
577 | ||
578 | if (pointPtr[1] < y1) { | |
579 | yDiff = y1 - pointPtr[1]; | |
580 | } else if (pointPtr[1] > y2) { | |
581 | yDiff = pointPtr[1] - y2; | |
582 | } else { | |
583 | yDiff = 0; | |
584 | } | |
585 | ||
586 | return hypot(xDiff, yDiff); | |
587 | } | |
588 | \f | |
589 | /* | |
590 | *-------------------------------------------------------------- | |
591 | * | |
592 | * WinItemToArea -- | |
593 | * | |
594 | * This procedure is called to determine whether an item | |
595 | * lies entirely inside, entirely outside, or overlapping | |
596 | * a given rectangle. | |
597 | * | |
598 | * Results: | |
599 | * -1 is returned if the item is entirely outside the area | |
600 | * given by rectPtr, 0 if it overlaps, and 1 if it is entirely | |
601 | * inside the given area. | |
602 | * | |
603 | * Side effects: | |
604 | * None. | |
605 | * | |
606 | *-------------------------------------------------------------- | |
607 | */ | |
608 | ||
609 | /* ARGSUSED */ | |
610 | static int | |
611 | WinItemToArea(canvasPtr, itemPtr, rectPtr) | |
612 | Tk_Canvas *canvasPtr; /* Canvas containing item. */ | |
613 | Tk_Item *itemPtr; /* Item to check against rectangle. */ | |
614 | double *rectPtr; /* Pointer to array of four coordinates | |
615 | * (x1, y1, x2, y2) describing rectangular | |
616 | * area. */ | |
617 | { | |
618 | register WindowItem *winItemPtr = (WindowItem *) itemPtr; | |
619 | ||
620 | if ((rectPtr[2] <= winItemPtr->header.x1) | |
621 | || (rectPtr[0] >= winItemPtr->header.x2) | |
622 | || (rectPtr[3] <= winItemPtr->header.y1) | |
623 | || (rectPtr[1] >= winItemPtr->header.y2)) { | |
624 | return -1; | |
625 | } | |
626 | if ((rectPtr[0] <= winItemPtr->header.x1) | |
627 | && (rectPtr[1] <= winItemPtr->header.y1) | |
628 | && (rectPtr[2] >= winItemPtr->header.x2) | |
629 | && (rectPtr[3] >= winItemPtr->header.y2)) { | |
630 | return 1; | |
631 | } | |
632 | return 0; | |
633 | } | |
634 | \f | |
635 | /* | |
636 | *-------------------------------------------------------------- | |
637 | * | |
638 | * ScaleWinItem -- | |
639 | * | |
640 | * This procedure is invoked to rescale a rectangle or oval | |
641 | * item. | |
642 | * | |
643 | * Results: | |
644 | * None. | |
645 | * | |
646 | * Side effects: | |
647 | * The rectangle or oval referred to by itemPtr is rescaled | |
648 | * so that the following transformation is applied to all | |
649 | * point coordinates: | |
650 | * x' = originX + scaleX*(x-originX) | |
651 | * y' = originY + scaleY*(y-originY) | |
652 | * | |
653 | *-------------------------------------------------------------- | |
654 | */ | |
655 | ||
656 | static void | |
657 | ScaleWinItem(canvasPtr, itemPtr, originX, originY, scaleX, scaleY) | |
658 | Tk_Canvas *canvasPtr; /* Canvas containing rectangle. */ | |
659 | Tk_Item *itemPtr; /* Rectangle to be scaled. */ | |
660 | double originX, originY; /* Origin about which to scale rect. */ | |
661 | double scaleX; /* Amount to scale in X direction. */ | |
662 | double scaleY; /* Amount to scale in Y direction. */ | |
663 | { | |
664 | register WindowItem *winItemPtr = (WindowItem *) itemPtr; | |
665 | ||
666 | winItemPtr->x = originX + scaleX*(winItemPtr->x - originX); | |
667 | winItemPtr->y = originY + scaleY*(winItemPtr->y - originY); | |
668 | if (winItemPtr->width > 0) { | |
669 | winItemPtr->width = scaleY*winItemPtr->width; | |
670 | } | |
671 | if (winItemPtr->height > 0) { | |
672 | winItemPtr->height = scaleY*winItemPtr->height; | |
673 | } | |
674 | ComputeWindowBbox(canvasPtr, winItemPtr); | |
675 | } | |
676 | \f | |
677 | /* | |
678 | *-------------------------------------------------------------- | |
679 | * | |
680 | * TranslateWinItem -- | |
681 | * | |
682 | * This procedure is called to move a rectangle or oval by a | |
683 | * given amount. | |
684 | * | |
685 | * Results: | |
686 | * None. | |
687 | * | |
688 | * Side effects: | |
689 | * The position of the rectangle or oval is offset by | |
690 | * (xDelta, yDelta), and the bounding box is updated in the | |
691 | * generic part of the item structure. | |
692 | * | |
693 | *-------------------------------------------------------------- | |
694 | */ | |
695 | ||
696 | static void | |
697 | TranslateWinItem(canvasPtr, itemPtr, deltaX, deltaY) | |
698 | Tk_Canvas *canvasPtr; /* Canvas containing item. */ | |
699 | Tk_Item *itemPtr; /* Item that is being moved. */ | |
700 | double deltaX, deltaY; /* Amount by which item is to be | |
701 | * moved. */ | |
702 | { | |
703 | register WindowItem *winItemPtr = (WindowItem *) itemPtr; | |
704 | ||
705 | winItemPtr->x += deltaX; | |
706 | winItemPtr->y += deltaY; | |
707 | ComputeWindowBbox(canvasPtr, winItemPtr); | |
708 | } | |
709 | \f | |
710 | /* | |
711 | *-------------------------------------------------------------- | |
712 | * | |
713 | * WinItemStructureProc -- | |
714 | * | |
715 | * This procedure is invoked whenever StructureNotify events | |
716 | * occur for a window that's managed as part of a canvas window | |
717 | * item. This procudure's only purpose is to clean up when | |
718 | * windows are deleted. | |
719 | * | |
720 | * Results: | |
721 | * None. | |
722 | * | |
723 | * Side effects: | |
724 | * The window is disassociated from the window item when it is | |
725 | * deleted. | |
726 | * | |
727 | *-------------------------------------------------------------- | |
728 | */ | |
729 | ||
730 | static void | |
731 | WinItemStructureProc(clientData, eventPtr) | |
732 | ClientData clientData; /* Pointer to record describing window item. */ | |
733 | XEvent *eventPtr; /* Describes what just happened. */ | |
734 | { | |
735 | register WindowItem *winItemPtr = (WindowItem *) clientData; | |
736 | ||
737 | if (eventPtr->type == DestroyNotify) { | |
738 | winItemPtr->tkwin = NULL; | |
739 | } | |
740 | } | |
741 | \f | |
742 | /* | |
743 | *-------------------------------------------------------------- | |
744 | * | |
745 | * WinItemRequestProc -- | |
746 | * | |
747 | * This procedure is invoked whenever a window that's associated | |
748 | * with a window canvas item changes its requested dimensions. | |
749 | * | |
750 | * Results: | |
751 | * None. | |
752 | * | |
753 | * Side effects: | |
754 | * The size and location on the screen of the window may change, | |
755 | * depending on the options specified for the window item. | |
756 | * | |
757 | *-------------------------------------------------------------- | |
758 | */ | |
759 | ||
760 | /* ARGSUSED */ | |
761 | static void | |
762 | WinItemRequestProc(clientData, tkwin) | |
763 | ClientData clientData; /* Pointer to record for window item. */ | |
764 | Tk_Window tkwin; /* Window that changed its desired | |
765 | * size. */ | |
766 | { | |
767 | WindowItem *winItemPtr = (WindowItem *) clientData; | |
768 | ||
769 | ComputeWindowBbox(winItemPtr->canvasPtr, winItemPtr); | |
770 | DisplayWinItem(winItemPtr->canvasPtr, (Tk_Item *) winItemPtr, | |
771 | (Drawable) None); | |
772 | } |