source: trunk/gui/src/RpCanvPlacard.c @ 2117

Last change on this file since 2117 was 2117, checked in by mmc, 14 years ago

Added the "placard" canvas item type and a first cut at the Diffview
widget for showing textual diffs. I've been working on both of these
as part of "gui15", but we probably need Diffview for the new regression
tester, so I'm moving them over. The Diffview still needs lots of work.

File size: 42.5 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  RpCanvPlacard - canvas item with text and background box
4 *
5 *  This canvas item makes it easy to create a box with text inside.
6 *  The box is normally stretched around the text, but can be given
7 *  a max size and causing text to be clipped.
8 *
9 *    .c create placard <x> <y> -anchor <nsew> \
10 *        -text <text>         << text to be displayed
11 *        -font <name>         << font used for text
12 *        -imageleft <image>   << image displayed on the left of text
13 *        -imageright <image>  << image displayed on the right of text
14 *        -maxwidth <size>     << maximum size
15 *        -textcolor <color>   << text color
16 *        -background <color>  << fill for rect behind text
17 *        -outline <color>     << outline around text
18 *        -borderwidth <size>  << for 3D border
19 *        -relief <value>      << for 3D border (drawn under -outline)
20 *        -tags <taglist>      << usual Tk canvas tags
21 *
22 * ======================================================================
23 *  AUTHOR:  Michael McLennan, Purdue University
24 *  Copyright (c) 2004-2009  Purdue Research Foundation
25 *
26 *  See the file "license.terms" for information on usage and
27 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
28 * ======================================================================
29 */
30#include <string.h>
31#include <math.h>
32#include "tk.h"
33
34/* used for text within the placard that needs to be truncated */
35#define ellipsis_width 9
36#define ellipsis_height 1
37static unsigned char ellipsis_bits[] = {
38   0x92, 0x00};
39
40/*
41 * Record for each placard item:
42 */
43typedef struct PlacardItem  {
44    Tk_Item header;             /* Generic stuff that's the same for all
45                                 * types.  MUST BE FIRST IN STRUCTURE. */
46    Tcl_Interp *interp;         /* Interp that owns this item */
47    Tk_Window tkwin;            /* Window that represents this canvas */
48    Tk_Canvas canvas;           /* Canvas that owns this item */
49    Pixmap dots;                /* ellipsis used for truncated text */
50
51    /*
52     * Fields that are set by widget commands other than "configure":
53     */
54    double x, y;                /* Positioning point for text */
55
56    /*
57     * Configuration settings that are updated by Tk_ConfigureWidget:
58     */
59    char *text;                 /* text to be displayed */
60    Tk_Anchor anchor;           /* Where to anchor text relative to (x,y) */
61    XColor *textColor;          /* Color for text */
62    XColor *lineColor;          /* Color for outline of rectangle */
63    Tk_3DBorder bgBorder;       /* used for drawing background rectangle */
64    Tk_Font tkfont;             /* Font for drawing text */
65    int width;                  /* Fixed width for placard (0 = not set) */
66    int maxWidth;               /* Maximum overall width for placard */
67    int borderWidth;            /* supports 3D border (drawn under -outline) */
68    int relief;                 /* indicates whether placard as a whole is
69                                 * raised, sunken, or flat */
70    int padding;                /* Padding around text and images */
71
72    char *imageLeftString;      /* Name of image displayed on the left */
73    char *imageRightString;     /* Name of image displayed on the right */
74 
75    /*
76     * Fields whose values are derived from the current values of the
77     * configuration settings above:
78     */
79    int textNumChars;           /* Length of text in characters. */
80    int textNumBytes;           /* Length of text in bytes. */
81    int textDrawChars;          /* Same as textNumChars or shorter, if
82                                 * text is too long for -maxwidth */
83    int textWidth;              /* Overall width of text (perhaps truncated)
84                                 * in pixels */
85    Tk_TextLayout textLayout;   /* Cached text layout information for value */
86
87    Tk_Image imageLeft;         /* icon drawn to left of text */
88    int imageLeftW;             /* width of image (if image is not NULL) */
89    int imageLeftH;             /* height of image (if image is not NULL) */
90
91    Tk_Image imageRight;        /* icon drawn to right of text */
92    int imageRightW;            /* width of image (if image is not NULL) */
93    int imageRightH;            /* height of image (if image is not NULL) */
94
95    int leftEdge;               /* Pixel location of the left edge of the
96                                 * item. (Where the left border of the
97                                 * text layout is drawn.) */
98    int rightEdge;              /* Pixel just to right of right edge of
99                                 * area of text item. */
100    GC gcText;                  /* Graphics context for drawing text. */
101    GC gcLineRect;              /* Graphics context for rectangle outline. */
102} PlacardItem;
103
104/*
105 * Information used for parsing configuration specs:
106 */
107static Tk_CustomOption tagsOption = {
108    (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
109    Tk_CanvasTagsPrintProc, (ClientData) NULL
110};
111
112static Tk_ConfigSpec configSpecs[] = {
113    {TK_CONFIG_ANCHOR, "-anchor", (char*)NULL, (char*)NULL,
114        "center", Tk_Offset(PlacardItem, anchor),
115        TK_CONFIG_DONT_SET_DEFAULT},
116    {TK_CONFIG_BORDER, "-background", (char*)NULL, (char*)NULL,
117        "", Tk_Offset(PlacardItem, bgBorder), TK_CONFIG_NULL_OK},
118    {TK_CONFIG_PIXELS, "-borderwidth", (char*)NULL, (char*)NULL,
119        "0", Tk_Offset(PlacardItem, borderWidth), 0},
120    {TK_CONFIG_FONT, "-font", (char*)NULL, (char*)NULL,
121        "helvetica -12", Tk_Offset(PlacardItem, tkfont), 0},
122    {TK_CONFIG_COLOR, "-foreground", (char*)NULL, (char*)NULL,
123        "black", Tk_Offset(PlacardItem, textColor), TK_CONFIG_NULL_OK},
124    {TK_CONFIG_STRING, "-imageleft", (char*)NULL, (char*)NULL,
125        (char*)NULL, Tk_Offset(PlacardItem, imageLeftString),
126        TK_CONFIG_NULL_OK},
127    {TK_CONFIG_STRING, "-imageright", (char*)NULL, (char*)NULL,
128        (char*)NULL, Tk_Offset(PlacardItem, imageRightString),
129        TK_CONFIG_NULL_OK},
130    {TK_CONFIG_PIXELS, "-maxwidth", (char*)NULL, (char*)NULL,
131        "0", Tk_Offset(PlacardItem, maxWidth), 0},
132    {TK_CONFIG_COLOR, "-outline", (char*)NULL, (char*)NULL,
133        "", Tk_Offset(PlacardItem, lineColor), TK_CONFIG_NULL_OK},
134    {TK_CONFIG_PIXELS, "-padding", (char*)NULL, (char*)NULL,
135        "4", Tk_Offset(PlacardItem, padding), 0},
136    {TK_CONFIG_RELIEF, "-relief", (char*)NULL, (char*)NULL,
137        "flat", Tk_Offset(PlacardItem, relief), 0},
138    {TK_CONFIG_CUSTOM, "-tags", (char*)NULL, (char*)NULL,
139        (char*)NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
140    {TK_CONFIG_STRING, "-text", (char*)NULL, (char*)NULL,
141        "", Tk_Offset(PlacardItem, text), 0},
142    {TK_CONFIG_PIXELS, "-width", (char*)NULL, (char*)NULL,
143        "0", Tk_Offset(PlacardItem, width), 0},
144    {TK_CONFIG_END, (char*)NULL, (char*)NULL, (char*)NULL,
145        (char*)NULL, 0, 0}
146};
147
148/*
149 * Prototypes for procedures defined in this file
150 */
151static void ComputePlacardBbox _ANSI_ARGS_((Tk_Canvas canvas,
152    PlacardItem *plPtr));
153static int ConfigurePlacard _ANSI_ARGS_((Tcl_Interp *interp,
154    Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
155    Tcl_Obj *CONST argv[], int flags));
156static int CreatePlacard _ANSI_ARGS_((Tcl_Interp *interp,
157    Tk_Canvas canvas, struct Tk_Item *itemPtr,
158    int argc, Tcl_Obj *CONST argv[]));
159static void DeletePlacard _ANSI_ARGS_((Tk_Canvas canvas,
160    Tk_Item *itemPtr, Display *display));
161static void DisplayCanvPlacard _ANSI_ARGS_((Tk_Canvas canvas,
162    Tk_Item *itemPtr, Display *display, Drawable dst,
163    int x, int y, int width, int height));
164static void ScalePlacard _ANSI_ARGS_((Tk_Canvas canvas,
165    Tk_Item *itemPtr, double originX, double originY,
166    double scaleX, double scaleY));
167static void TranslatePlacard _ANSI_ARGS_((Tk_Canvas canvas,
168    Tk_Item *itemPtr, double deltaX, double deltaY));
169static int PlacardCoords _ANSI_ARGS_((Tcl_Interp *interp,
170    Tk_Canvas canvas, Tk_Item *itemPtr,
171    int argc, Tcl_Obj *CONST argv[]));
172static int PlacardToArea _ANSI_ARGS_((Tk_Canvas canvas,
173    Tk_Item *itemPtr, double *rectPtr));
174static double PlacardToPoint _ANSI_ARGS_((Tk_Canvas canvas,
175    Tk_Item *itemPtr, double *pointPtr));
176static int PlacardToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
177    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
178
179static void ImageLeftChangedProc _ANSI_ARGS_((ClientData clientData,
180    int x, int y, int width, int height, int imgWidth,
181    int imgHeight));
182static void ImageRightChangedProc _ANSI_ARGS_((ClientData clientData,
183    int x, int y, int width, int height, int imgWidth,
184    int imgHeight));
185
186/*
187 * The structures below defines the canvas item type:
188 */
189Tk_ItemType rpPlacardType = {
190    "placard",                          /* name */
191    sizeof(PlacardItem),                /* itemSize */
192    CreatePlacard,                      /* createProc */
193    configSpecs,                        /* configSpecs */
194    ConfigurePlacard,                   /* configureProc */
195    PlacardCoords,                      /* coordProc */
196    DeletePlacard,                      /* deleteProc */
197    DisplayCanvPlacard,                 /* displayProc */
198    TK_CONFIG_OBJS,                     /* flags */
199    PlacardToPoint,                     /* pointProc */
200    PlacardToArea,                      /* areaProc */
201    PlacardToPostscript,                /* postscriptProc */
202    ScalePlacard,                       /* scaleProc */
203    TranslatePlacard,                   /* translateProc */
204    (Tk_ItemIndexProc *) NULL,          /* indexProc */
205    (Tk_ItemCursorProc *) NULL,         /* icursorProc */
206    (Tk_ItemSelectionProc *) NULL,      /* selectionProc */
207    (Tk_ItemInsertProc *) NULL,         /* insertProc */
208    (Tk_ItemDCharsProc *) NULL,         /* dTextProc */
209    (Tk_ItemType *) NULL,               /* nextPtr */
210};
211
212/*
213 * ------------------------------------------------------------------------
214 *  RpCanvPlacard_Init --
215 *
216 *  Invoked when the Rappture GUI library is being initialized
217 *  to install the "placard" item on the Tk canvas widget.
218 *
219 *  Returns TCL_OK if successful, or TCL_ERROR (along with an error
220 *  message in the interp) if anything goes wrong.
221 * ------------------------------------------------------------------------
222 */
223int
224RpCanvPlacard_Init(interp)
225    Tcl_Interp *interp;         /* interpreter being initialized */
226{
227    Tk_CreateItemType(&rpPlacardType);
228
229    Tk_DefineBitmap(interp, Tk_GetUid("rp_ellipsis"),
230        (char*)ellipsis_bits, ellipsis_width, ellipsis_height);
231
232    return TCL_OK;
233}
234
235/*
236 * ------------------------------------------------------------------------
237 *  CreatePlacard --
238 *
239 *    This procedure is invoked to create a new placard item
240 *    in a canvas.  A placard is a text item with a box behind it.
241 *
242 *  Results:
243 *    A standard Tcl return name.  If an error occurred in creating
244 *    the item then an error message is left in the interp's result.
245 *    In this case itemPtr is left uninitialized so it can be safely
246 *    freed by the caller.
247 *
248 *  Side effects:
249 *    A new item is created.
250 * ------------------------------------------------------------------------
251 */
252static int
253CreatePlacard(interp, canvas, itemPtr, argc, argv)
254    Tcl_Interp *interp;           /* interpreter for error reporting */
255    Tk_Canvas canvas;             /* canvas to hold new item */
256    Tk_Item *itemPtr;             /* record to hold new item; header has been
257                                   * initialized by caller */
258    int argc;                     /* number of arguments in argv */
259    Tcl_Obj *CONST argv[];        /* arguments describing item */
260{
261    PlacardItem *plPtr = (PlacardItem *) itemPtr;
262    int i;
263
264    if (argc == 1) {
265        i = 1;
266    } else {
267        char *arg = Tcl_GetStringFromObj(argv[1], NULL);
268        if ((argc > 1) && (arg[0] == '-')
269                && (arg[1] >= 'a') && (arg[1] <= 'z')) {
270            i = 1;
271        } else {
272            i = 2;
273        }
274    }
275
276    if (argc < i) {
277        Tcl_AppendResult(interp, "wrong # args: should be \"",
278            Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
279            itemPtr->typePtr->name, " x y ?options?\"", (char *) NULL);
280        return TCL_ERROR;
281    }
282
283    /*
284     * Carry out initialization that is needed in order to clean up after
285     * errors during the the remainder of this procedure.
286     */
287    plPtr->interp           = interp;
288    plPtr->tkwin            = Tk_CanvasTkwin(canvas);
289    plPtr->canvas           = canvas;
290    plPtr->dots             = Tk_GetBitmap(interp, plPtr->tkwin,
291                                  Tk_GetUid("rp_ellipsis"));
292    plPtr->text             = NULL;
293    plPtr->anchor           = TK_ANCHOR_CENTER;
294    plPtr->textColor        = NULL;
295    plPtr->bgBorder         = NULL;
296    plPtr->lineColor        = NULL;
297    plPtr->tkfont           = NULL;
298    plPtr->width            = 0;
299    plPtr->maxWidth         = 0;
300    plPtr->borderWidth      = 0;
301    plPtr->relief           = TK_RELIEF_FLAT;
302    plPtr->padding          = 0;
303    plPtr->imageLeftString  = NULL;
304    plPtr->imageRightString = NULL;
305    plPtr->imageLeft        = NULL;
306    plPtr->imageRight       = NULL;
307    plPtr->textNumChars     = 0;
308    plPtr->textNumBytes     = 0;
309    plPtr->textDrawChars    = 0;
310    plPtr->textWidth        = 0;
311    plPtr->textLayout       = NULL;
312    plPtr->leftEdge         = 0;
313    plPtr->rightEdge        = 0;
314    plPtr->gcText           = None;
315    plPtr->gcLineRect       = None;
316
317    /*
318     * Process the arguments to fill in the item record.
319     */
320    if ((PlacardCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
321        goto error;
322    }
323    if (ConfigurePlacard(interp, canvas, itemPtr,
324            argc-i, argv+i, 0) == TCL_OK) {
325
326        return TCL_OK;
327    }
328
329error:
330    DeletePlacard(canvas, itemPtr, Tk_Display(plPtr->tkwin));
331    return TCL_ERROR;
332}
333
334/*
335 * ------------------------------------------------------------------------
336 *  PlacardCoords --
337 *
338 *    This procedure is invoked to process the "coords" widget command on
339 *    placard items.  See the user documentation for details on what
340 *    it does.
341 *
342 *  Results:
343 *    Returns TCL_OK or TCL_ERROR, and sets the interp's result.
344 *
345 *  Side effects:
346 *    The coordinates for the given item may be changed.
347 * ------------------------------------------------------------------------
348 */
349static int
350PlacardCoords(interp, canvas, itemPtr, argc, argv)
351    Tcl_Interp *interp;     /* Used for error reporting. */
352    Tk_Canvas canvas;       /* Canvas containing item. */
353    Tk_Item *itemPtr;       /* Item whose coordinates are to be read or
354                             * modified. */
355    int argc;               /* Number of coordinates supplied in argv. */
356    Tcl_Obj *CONST argv[];  /* Array of coordinates: x1, y1, x2, y2, ... */
357{
358    PlacardItem *plPtr = (PlacardItem *) itemPtr;
359    char buf[64 + TCL_INTEGER_SPACE];
360
361    if (argc == 0) {
362        Tcl_Obj *obj = Tcl_NewObj();
363        Tcl_Obj *subobj = Tcl_NewDoubleObj(plPtr->x);
364        Tcl_ListObjAppendElement(interp, obj, subobj);
365        subobj = Tcl_NewDoubleObj(plPtr->y);
366        Tcl_ListObjAppendElement(interp, obj, subobj);
367        Tcl_SetObjResult(interp, obj);
368    }
369    else if (argc < 3) {
370        if (argc == 1) {
371            if (Tcl_ListObjGetElements(interp, argv[0], &argc,
372                    (Tcl_Obj ***) &argv) != TCL_OK) {
373                return TCL_ERROR;
374            } else if (argc != 2) {
375
376                sprintf(buf, "wrong # coordinates: expected 2, got %d", argc);
377                Tcl_SetResult(interp, buf, TCL_VOLATILE);
378                return TCL_ERROR;
379            }
380        }
381        if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0],
382                   &plPtr->x) != TCL_OK)
383                || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
384                          &plPtr->y) != TCL_OK)) {
385            return TCL_ERROR;
386        }
387        ComputePlacardBbox(canvas, plPtr);
388    } else {
389        sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", argc);
390        Tcl_SetResult(interp, buf, TCL_VOLATILE);
391        return TCL_ERROR;
392    }
393    return TCL_OK;
394}
395
396/*
397 * ------------------------------------------------------------------------
398 *  ConfigurePlacard --
399 *
400 *    This procedure is invoked to configure various aspects of a
401 *    placard item, such as its color and font.
402 *
403 *  Results:
404 *    A standard Tcl result code.  If an error occurs, then an error
405 *    message is left in the interp's result.
406 *
407 *  Side effects:
408 *    Configuration information, such as colors and GCs, may be set
409 *    for itemPtr.
410 * ------------------------------------------------------------------------
411 */
412static int
413ConfigurePlacard(interp, canvas, itemPtr, argc, argv, flags)
414    Tcl_Interp *interp;           /* Interpreter for error reporting. */
415    Tk_Canvas canvas;             /* Canvas containing itemPtr. */
416    Tk_Item *itemPtr;             /* Rectangle item to reconfigure. */
417    int argc;                     /* Number of elements in argv.  */
418    Tcl_Obj *CONST argv[];        /* Args describing things to configure. */
419    int flags;                    /* Flags to pass to Tk_ConfigureWidget. */
420{
421    PlacardItem *plPtr = (PlacardItem *) itemPtr;
422    XGCValues gcValues;
423    GC newGC;
424    unsigned long mask;
425    Tk_Window tkwin;
426    XColor *color;
427    Tk_Image image;
428
429    tkwin = Tk_CanvasTkwin(canvas);
430    if (Tk_ConfigureWidget(interp, tkwin, configSpecs,
431            argc, (CONST char **) argv,
432            (char*)plPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
433        return TCL_ERROR;
434    }
435
436    /*
437     * A few of the options require additional processing, such as
438     * graphics contexts.
439     */
440    color = plPtr->textColor;
441    newGC = None;
442    if (plPtr->tkfont != NULL) {
443        gcValues.font = Tk_FontId(plPtr->tkfont);
444        mask = GCFont;
445        if (color != NULL) {
446            gcValues.foreground = color->pixel;
447            mask |= GCForeground;
448            newGC = Tk_GetGC(tkwin, mask, &gcValues);
449        }
450    }
451    if (plPtr->gcText != None) {
452        Tk_FreeGC(Tk_Display(tkwin), plPtr->gcText);
453    }
454    plPtr->gcText = newGC;
455
456
457    newGC = None;
458    if (plPtr->lineColor != NULL) {
459        gcValues.foreground = plPtr->lineColor->pixel;
460        gcValues.line_width = 1;
461        mask = GCForeground | GCLineWidth;
462        newGC = Tk_GetGC(tkwin, mask, &gcValues);
463    }
464    if (plPtr->gcLineRect != None) {
465        Tk_FreeGC(Tk_Display(tkwin), plPtr->gcLineRect);
466    }
467    plPtr->gcLineRect = newGC;
468
469
470    if (plPtr->imageLeftString != NULL) {
471        image = Tk_GetImage(interp, tkwin, plPtr->imageLeftString,
472                ImageLeftChangedProc, (ClientData)plPtr);
473        if (image == NULL) {
474            return TCL_ERROR;
475        }
476    } else {
477        image = NULL;
478    }
479    if (plPtr->imageLeft != NULL) {
480        Tk_FreeImage(plPtr->imageLeft);
481    }
482    plPtr->imageLeft = image;
483
484    if (image != NULL) {
485        Tk_SizeOfImage(image,&plPtr->imageLeftW, &plPtr->imageLeftH);
486    }
487
488
489    if (plPtr->imageRightString != NULL) {
490        image = Tk_GetImage(interp, tkwin, plPtr->imageRightString,
491                ImageRightChangedProc, (ClientData)plPtr);
492        if (image == NULL) {
493            return TCL_ERROR;
494        }
495    } else {
496        image = NULL;
497    }
498    if (plPtr->imageRight != NULL) {
499        Tk_FreeImage(plPtr->imageRight);
500    }
501    plPtr->imageRight = image;
502
503    if (image != NULL) {
504        Tk_SizeOfImage(image,&plPtr->imageRightW, &plPtr->imageRightH);
505    }
506
507
508    if (plPtr->text != NULL) {
509        plPtr->textNumBytes = strlen(plPtr->text);
510        plPtr->textNumChars = Tcl_NumUtfChars(plPtr->text, plPtr->textNumBytes);
511    };
512
513    ComputePlacardBbox(canvas, plPtr);
514    return TCL_OK;
515}
516
517/*
518 * ------------------------------------------------------------------------
519 *  DeletePlacard --
520 *
521 *    This procedure is called to clean up the data structure
522 *    associated with a placard item.
523 *
524 *  Results:
525 *    None.
526 *
527 *  Side effects:
528 *    Resources associated with itemPtr are released.
529 * ------------------------------------------------------------------------
530 */
531static void
532DeletePlacard(canvas, itemPtr, display)
533    Tk_Canvas canvas;          /* Info about overall canvas widget. */
534    Tk_Item *itemPtr;          /* Item that is being deleted. */
535    Display *display;          /* Display containing window for canvas. */
536{
537    PlacardItem *plPtr = (PlacardItem *) itemPtr;
538
539    if (plPtr->textColor != NULL) {
540        Tk_FreeColor(plPtr->textColor);
541    }
542    if (plPtr->lineColor != NULL) {
543        Tk_FreeColor(plPtr->lineColor);
544    }
545    if (plPtr->text != NULL) {
546        ckfree(plPtr->text);
547    }
548
549
550    if (plPtr->imageLeftString != NULL) {
551        ckfree(plPtr->imageLeftString);
552    }
553    if (plPtr->imageLeft != NULL ) {
554        Tk_FreeImage(plPtr->imageLeft);
555    }
556    if (plPtr->imageRightString != NULL) {
557        ckfree(plPtr->imageRightString);
558    }
559    if (plPtr->imageRight != NULL ) {
560        Tk_FreeImage(plPtr->imageRight);
561    }
562
563    Tk_FreeTextLayout(plPtr->textLayout);
564
565    Tk_FreeFont(plPtr->tkfont);
566
567    if (plPtr->gcText != None) {
568        Tk_FreeGC(display, plPtr->gcText);
569    }
570    if (plPtr->gcLineRect != None) {
571        Tk_FreeGC(display, plPtr->gcLineRect);
572    }
573}
574
575/*
576 * ------------------------------------------------------------------------
577 *  ComputePlacardBbox --
578 *
579 *    This procedure is invoked to compute the bounding box of
580 *    all the pixels that may be drawn as part of a text item.
581 *    In addition, it recomputes all of the geometry information
582 *    used to display a text item or check for mouse hits.
583 *
584 *  Results:
585 *    None.
586 *
587 *  Side effects:
588 *    The fields x1, y1, x2, and y2 are updated in the header
589 *    for itemPtr, and the linePtr structure is regenerated
590 *    for itemPtr.
591 * ------------------------------------------------------------------------
592 */
593static void
594ComputePlacardBbox(canvas, plPtr)
595    Tk_Canvas canvas;           /* Canvas that contains item. */
596    PlacardItem *plPtr;       /* Item whose bbox is to be recomputed. */
597{
598    int leftX, topY, width, height, maxwidth, ellw, ellh;
599
600    /*
601     * Get the layout for the placard text.
602     */
603    plPtr->textDrawChars = plPtr->textNumChars;
604
605    Tk_FreeTextLayout(plPtr->textLayout);
606    plPtr->textLayout = Tk_ComputeTextLayout(plPtr->tkfont,
607            plPtr->text, plPtr->textNumChars, -1,
608            TK_JUSTIFY_LEFT, 0, &width, &height);
609
610    plPtr->textWidth = width;
611
612    if (plPtr->textColor == NULL) {
613        width = height = 0;
614    } else {
615        width += 2*plPtr->padding;
616        height += 2*plPtr->padding;
617    }
618
619    /*
620     * If the current value has an image, add on its width.
621     */
622    if (plPtr->imageLeft) {
623        width += plPtr->imageLeftW;
624        if (plPtr->textWidth > 0) {
625            width += plPtr->padding;
626        }
627        if (plPtr->imageLeftH > height) {
628            height = plPtr->imageLeftH;
629        }
630    }
631    if (plPtr->imageRight) {
632        width += plPtr->imageRightW;
633        if (plPtr->textWidth > 0) {
634            width += plPtr->padding;
635        }
636        if (plPtr->imageRightH > height) {
637            height = plPtr->imageRightH;
638        }
639    }
640
641    /*
642     * Add on extra size for the 3D border (if there is one).
643     */
644    if (plPtr->borderWidth > 0) {
645        width += 2*plPtr->borderWidth;
646        height += 2*plPtr->borderWidth;
647    }
648
649    /*
650     * If the overall width exceeds the -maxwidth, then we must
651     * truncate the text to make it fit.
652     */
653    maxwidth = 0;
654    if (plPtr->maxWidth > 0 && plPtr->width > 0) {
655        maxwidth = (plPtr->width < plPtr->maxWidth) ? plPtr->width : plPtr->maxWidth;
656    } else if (plPtr->maxWidth > 0) {
657        maxwidth = plPtr->maxWidth;
658    } else if (plPtr->width > 0) {
659        maxwidth = plPtr->width;
660    }
661
662    if (maxwidth > 0 && width > maxwidth) {
663        Tk_SizeOfBitmap(Tk_Display(plPtr->tkwin), plPtr->dots, &ellw, &ellh);
664        width = maxwidth - 2*plPtr->padding - 2*plPtr->borderWidth - ellw;
665        if (plPtr->imageLeft) {
666            width -= plPtr->imageLeftW + plPtr->padding;
667        }
668        if (plPtr->imageRight) {
669            width -= plPtr->imageRightW + plPtr->padding;
670        }
671        if (width < 0) { width = 0; }
672
673        plPtr->textDrawChars = Tk_MeasureChars(plPtr->tkfont,
674            plPtr->text, plPtr->textNumChars, width, /*flags*/ 0,
675            &plPtr->textWidth);
676
677        /* recompute layout for truncated text */
678        Tk_FreeTextLayout(plPtr->textLayout);
679        plPtr->textLayout = Tk_ComputeTextLayout(plPtr->tkfont,
680                plPtr->text, plPtr->textDrawChars, -1,
681                TK_JUSTIFY_LEFT, 0, NULL, NULL);
682
683        width = maxwidth;  /* fit everything in this width */
684    }
685
686    /*
687     * If there's a fixed -width, then use that instead.
688     */
689    if (plPtr->width > 0) {
690        width = plPtr->width;
691    }
692
693    /*
694     * Use overall geometry information to compute the top-left corner
695     * of the bounding box for the text item.
696     */
697    leftX = (int) (plPtr->x + 0.5);
698    topY = (int) (plPtr->y + 0.5);
699    switch (plPtr->anchor) {
700        case TK_ANCHOR_NW:
701        case TK_ANCHOR_N:
702        case TK_ANCHOR_NE:
703            break;
704
705        case TK_ANCHOR_W:
706        case TK_ANCHOR_CENTER:
707        case TK_ANCHOR_E:
708            topY -= height / 2;
709            break;
710
711        case TK_ANCHOR_SW:
712        case TK_ANCHOR_S:
713        case TK_ANCHOR_SE:
714            topY -= height;
715            break;
716    }
717    switch (plPtr->anchor) {
718        case TK_ANCHOR_NW:
719        case TK_ANCHOR_W:
720        case TK_ANCHOR_SW:
721            break;
722
723        case TK_ANCHOR_N:
724        case TK_ANCHOR_CENTER:
725        case TK_ANCHOR_S:
726            leftX -= width / 2;
727            break;
728
729        case TK_ANCHOR_NE:
730        case TK_ANCHOR_E:
731        case TK_ANCHOR_SE:
732            leftX -= width;
733            break;
734    }
735
736    plPtr->leftEdge  = leftX;
737    plPtr->rightEdge = leftX + width;
738
739    /*
740     * Last of all, update the bounding box for the item.
741     */
742    plPtr->header.x1 = leftX;
743    plPtr->header.y1 = topY;
744    plPtr->header.x2 = leftX + width;
745    plPtr->header.y2 = topY + height;
746}
747
748/*
749 * ------------------------------------------------------------------------
750 *  DisplayCanvPlacard --
751 *
752 *    This procedure is invoked to draw a text item in a given drawable.
753 *
754 *  Results:
755 *    None.
756 *
757 *  Side effects:
758 *    ItemPtr is drawn in drawable using the transformation information
759 *    in canvas.
760 * ------------------------------------------------------------------------
761 */
762static void
763DisplayCanvPlacard(canvas, itemPtr, display, drawable, x, y, width, height)
764    Tk_Canvas canvas;           /* Canvas that contains item. */
765    Tk_Item *itemPtr;           /* Item to be displayed. */
766    Display *display;           /* Display on which to draw item. */
767    Drawable drawable;          /* Pixmap or window in which to draw item. */
768    int x, y, width, height;    /* Describes region of canvas that must be
769                                 * redisplayed (not used). */
770{
771    PlacardItem *plPtr = (PlacardItem *) itemPtr;
772    int imagew, delta, ellx, elly, ellw, ellh;
773    short drawableX, drawableY;
774    Tk_FontMetrics fm;
775
776    if (plPtr->gcText == None) {
777        return;
778    }
779
780    /*
781     * If there's a background rectangle, draw it first.
782     */
783    Tk_CanvasDrawableCoords(canvas, (double)plPtr->leftEdge,
784            (double)plPtr->header.y1, &drawableX, &drawableY);
785
786    if (plPtr->bgBorder) {
787        Tk_Fill3DRectangle(plPtr->tkwin, drawable, plPtr->bgBorder,
788            (int)drawableX, (int)drawableY,
789            (int)(plPtr->rightEdge - plPtr->leftEdge),
790            (int)(plPtr->header.y2 - plPtr->header.y1),
791            plPtr->borderWidth, plPtr->relief);
792    }
793
794    if (plPtr->gcLineRect) {
795        XDrawRectangle(display, drawable, plPtr->gcLineRect,
796            (int)drawableX, (int)drawableY,
797            (unsigned int)(plPtr->rightEdge - plPtr->leftEdge - 1),
798            (unsigned int)(plPtr->header.y2 - plPtr->header.y1 - 1));
799    }
800
801    /*
802     * If there's a right-hand image, draw it first.
803     */
804    imagew = 0;
805    if (plPtr->imageRight) {
806        Tk_CanvasDrawableCoords(canvas, (double)plPtr->rightEdge,
807                (double)plPtr->header.y1, &drawableX, &drawableY);
808
809        delta = (plPtr->header.y2 - plPtr->header.y1)/2 - plPtr->imageRightH/2;
810        drawableX -= plPtr->imageRightW + plPtr->padding + plPtr->borderWidth;
811        Tk_RedrawImage(plPtr->imageRight, 0, 0,
812                       plPtr->imageRightW, plPtr->imageRightH,
813                       drawable,
814                       (int)drawableX, (int)(drawableY+delta));
815        imagew += plPtr->imageRightW;
816    }
817
818    /*
819     * If there's a left-hand image, draw it next.
820     */
821    Tk_CanvasDrawableCoords(canvas, (double)plPtr->leftEdge,
822            (double)plPtr->header.y1, &drawableX, &drawableY);
823
824    drawableX += plPtr->padding + plPtr->borderWidth;
825    drawableY += plPtr->padding + plPtr->borderWidth;
826
827    if (plPtr->imageLeft) {
828        delta = (plPtr->header.y2 - plPtr->header.y1)/2
829                       - plPtr->imageLeftH/2 - plPtr->padding
830                       - plPtr->borderWidth;
831
832        Tk_RedrawImage(plPtr->imageLeft, 0, 0,
833                       plPtr->imageLeftW, plPtr->imageLeftH,
834                       drawable,
835                       (int)drawableX, (int)(drawableY+delta));
836        drawableX += plPtr->imageLeftW + plPtr->padding;
837        imagew += plPtr->imageLeftW;
838    }
839
840    /*
841     * Draw the text.
842     */
843    Tk_DrawTextLayout(display, drawable, plPtr->gcText, plPtr->textLayout,
844            drawableX, drawableY, 0, -1);
845
846    if (plPtr->textDrawChars < plPtr->textNumChars
847          && plPtr->rightEdge - plPtr->leftEdge - imagew > ellw) {
848        Tk_SizeOfBitmap(Tk_Display(plPtr->tkwin), plPtr->dots, &ellw, &ellh);
849        Tk_GetFontMetrics(plPtr->tkfont, &fm);
850        ellx = drawableX+plPtr->textWidth;
851        elly = drawableY+fm.ascent-1;
852
853        XSetClipMask(display, plPtr->gcText, plPtr->dots);
854        XSetClipOrigin(display, plPtr->gcText, ellx, elly);
855
856        XCopyPlane(display, plPtr->dots, drawable, plPtr->gcText, 0, 0,
857            (unsigned int)ellw, (unsigned int)ellh, ellx, elly, 1);
858
859        XSetClipOrigin(display, plPtr->gcText, 0, 0);
860        XSetClipMask(display, plPtr->gcText, None);
861    }
862}
863
864/*
865 * ------------------------------------------------------------------------
866 *  PlacardToPoint --
867 *
868 *    Computes the distance from a given point to a given placard
869 *    item, in canvas units.
870 *
871 *  Results:
872 *    The return value is 0 if the point whose x and y coordinates
873 *    are pointPtr[0] and pointPtr[1] is inside the text item.  If
874 *    the point isn't inside the text item then the return value
875 *    is the distance from the point to the text item.
876 *
877 *  Side effects:
878 *    None.
879 * ------------------------------------------------------------------------
880 */
881static double
882PlacardToPoint(canvas, itemPtr, pointPtr)
883    Tk_Canvas canvas;                /* Canvas containing itemPtr. */
884    Tk_Item *itemPtr;                /* Item to check against point. */
885    double *pointPtr;                /* Pointer to x and y coordinates. */
886{
887    PlacardItem *plPtr = (PlacardItem *) itemPtr;
888    double value, x0, y0, x1, y1, xDiff, yDiff;
889
890    if (plPtr->bgBorder || plPtr->lineColor) {
891        /* have a rectangle -- compare directly against that */
892        x0 = plPtr->leftEdge;
893        y0 = plPtr->header.y1;
894        x1 = plPtr->rightEdge;
895        y1 = plPtr->header.y2;
896    }
897    else if (plPtr->imageLeft || plPtr->imageRight) {
898        /* have images -- compare against a rectangle around image/text */
899        x0 = plPtr->leftEdge + plPtr->padding + plPtr->borderWidth;
900        y0 = plPtr->header.y1 + plPtr->padding + plPtr->borderWidth;
901        x1 = plPtr->rightEdge - plPtr->padding - plPtr->borderWidth;
902        y1 = plPtr->header.y2 - plPtr->padding - plPtr->borderWidth;
903    }
904    else {
905        value = (double) Tk_DistanceToTextLayout(plPtr->textLayout,
906                    (int) pointPtr[0] - plPtr->leftEdge,
907                    (int) pointPtr[1] - plPtr->header.y1);
908
909        if ((plPtr->textColor == NULL) || (plPtr->text == NULL)
910              || (*plPtr->text == 0)) {
911            value = 1.0e36;
912        }
913        return value;
914    }
915
916    if (pointPtr[0] < x0) {
917        xDiff = x0 - pointPtr[0];
918    } else if (pointPtr[0] >= x1)  {
919        xDiff = pointPtr[0] + 1 - x1;
920    } else {
921        xDiff = 0;
922    }
923
924    if (pointPtr[1] < y0) {
925        yDiff = y0 - pointPtr[1];
926    } else if (pointPtr[1] >= y1)  {
927        yDiff = pointPtr[1] + 1 - y1;
928    } else {
929        yDiff = 0;
930    }
931
932    return hypot(xDiff, yDiff);
933}
934
935/*
936 * ------------------------------------------------------------------------
937 *  PlacardToArea --
938 *
939 *    This procedure is called to determine whether an item lies
940 *    entirely inside, entirely outside, or overlapping a given
941 *    rectangle.
942 *
943 *  Results:
944 *    -1 is returned if the item is entirely outside the area given
945 *    by rectPtr, 0 if it overlaps, and 1 if it is entirely inside
946 *    the given area.
947 *
948 *  Side effects:
949 *    None.
950 * ------------------------------------------------------------------------
951 */
952static int
953PlacardToArea(canvas, itemPtr, rectPtr)
954    Tk_Canvas canvas;       /* Canvas containing itemPtr. */
955    Tk_Item *itemPtr;       /* Item to check against rectangle. */
956    double *rectPtr;        /* Pointer to array of four coordinates
957                             * (x1, y1, x2, y2) describing rectangular
958                             * area.  */
959{
960    PlacardItem *plPtr = (PlacardItem *) itemPtr;
961    int x0, y0, x1, y1;
962
963    if (plPtr->bgBorder || plPtr->lineColor) {
964        /* have a rectangle -- compare directly against that */
965        x0 = plPtr->leftEdge;
966        y0 = plPtr->header.y1;
967        x1 = plPtr->rightEdge;
968        y1 = plPtr->header.y2;
969    }
970    else if (plPtr->imageLeft || plPtr->imageRight) {
971        /* have images -- compare against a rectangle around image/text */
972        x0 = plPtr->leftEdge + plPtr->padding + plPtr->borderWidth;
973        y0 = plPtr->header.y1 + plPtr->padding + plPtr->borderWidth;
974        x1 = plPtr->rightEdge - plPtr->padding - plPtr->borderWidth;
975        y1 = plPtr->header.y2 - plPtr->padding - plPtr->borderWidth;
976    }
977    else {
978        /* have only text -- compare against text layout */
979        return Tk_IntersectTextLayout(plPtr->textLayout,
980            (int) (rectPtr[0] + 0.5) - (plPtr->leftEdge + plPtr->padding + plPtr->borderWidth),
981            (int) (rectPtr[1] + 0.5) - (plPtr->header.y1 + plPtr->padding + plPtr->borderWidth),
982            (int) (rectPtr[2] - rectPtr[0] + 0.5),
983            (int) (rectPtr[3] - rectPtr[1] + 0.5));
984    }
985
986    /* compare against rectangle... */
987    if (rectPtr[0] > x1 || rectPtr[1] > y1
988          || rectPtr[2] < x0 || rectPtr[3] < y0) {
989        return -1;  /* completely outside */
990    }
991    if (rectPtr[0] >= x0 && rectPtr[1] >= y0
992          && rectPtr[2] <= x1 && rectPtr[3] <= y1) {
993        return 1;  /* completely inside */
994    }
995    return 0;  /* must be overlapping */
996}
997
998/*
999 * ------------------------------------------------------------------------
1000 *  ScalePlacard --
1001 *
1002 *    This procedure is invoked to rescale a text item.
1003 *
1004 * Results:
1005 *    None.
1006 *
1007 * Side effects:
1008 *    Scales the position of the text, but not the size of the font
1009 *    for the text.
1010 * ------------------------------------------------------------------------
1011 */
1012        /* ARGSUSED */
1013static void
1014ScalePlacard(canvas, itemPtr, originX, originY, scaleX, scaleY)
1015    Tk_Canvas canvas;             /* Canvas containing rectangle. */
1016    Tk_Item *itemPtr;             /* Rectangle to be scaled. */
1017    double originX, originY;      /* Origin about which to scale rect. */
1018    double scaleX;                /* Amount to scale in X direction. */
1019    double scaleY;                /* Amount to scale in Y direction. */
1020{
1021    PlacardItem *plPtr = (PlacardItem *) itemPtr;
1022
1023    plPtr->x = originX + scaleX*(plPtr->x - originX);
1024    plPtr->y = originY + scaleY*(plPtr->y - originY);
1025    ComputePlacardBbox(canvas, plPtr);
1026    return;
1027}
1028
1029/*
1030 * ------------------------------------------------------------------------
1031 *  TranslatePlacard --
1032 *
1033 *    This procedure is called to move a text item by a given amount.
1034 *
1035 *  Results:
1036 *    None.
1037 *
1038 *  Side effects:
1039 *    The position of the text item is offset by (xDelta, yDelta),
1040 *    and the bounding box is updated in the generic part of the
1041 *    item structure.
1042 * ------------------------------------------------------------------------
1043 */
1044static void
1045TranslatePlacard(canvas, itemPtr, deltaX, deltaY)
1046    Tk_Canvas canvas;             /* Canvas containing item. */
1047    Tk_Item *itemPtr;             /* Item that is being moved. */
1048    double deltaX, deltaY;        /* Amount by which item is to be moved. */
1049{
1050    PlacardItem *plPtr = (PlacardItem *) itemPtr;
1051
1052    plPtr->x += deltaX;
1053    plPtr->y += deltaY;
1054    ComputePlacardBbox(canvas, plPtr);
1055}
1056
1057/*
1058 * ------------------------------------------------------------------------
1059 *  PlacardToPostscript --
1060 *
1061 *    This procedure is called to generate Postscript for placard
1062 *    items.
1063 *
1064 *  Results:
1065 *    The return value is a standard Tcl result.  If an error
1066 *    occurs in generating Postscript then an error message is
1067 *    left in the interp's result, replacing whatever used
1068 *    to be there.  If no error occurs, then Postscript for the
1069 *    item is appended to the result.
1070 *
1071 *  Side effects:
1072 *    None.
1073 * ------------------------------------------------------------------------
1074 */
1075static int
1076PlacardToPostscript(interp, canvas, itemPtr, prepass)
1077    Tcl_Interp *interp;         /* Leave Postscript or error message here. */
1078    Tk_Canvas canvas;           /* Information about overall canvas. */
1079    Tk_Item *itemPtr;           /* Item for which Postscript is wanted. */
1080    int prepass;                /* 1 means this is a prepass to collect
1081                                 * font information; 0 means final Postscript
1082                                 * is being created. */
1083{
1084    PlacardItem *plPtr = (PlacardItem *) itemPtr;
1085    Tk_Window canvasWin = Tk_CanvasTkwin(canvas);
1086
1087    int x, y;
1088    double xpos;
1089    Tk_FontMetrics fm;
1090    char *justify;
1091    char buffer[500];
1092    int delta;
1093
1094    if (plPtr->textColor == NULL || plPtr->text == NULL
1095          || *plPtr->text == 0) {
1096        return TCL_OK;
1097    }
1098
1099    if (Tk_CanvasPsFont(interp, canvas, plPtr->tkfont) != TCL_OK) {
1100        return TCL_ERROR;
1101    }
1102
1103
1104    if (!prepass &&
1105        Tk_CanvasPsColor(interp, canvas, plPtr->textColor) != TCL_OK) {
1106        return TCL_ERROR;
1107    }
1108    xpos = plPtr->x;
1109
1110    /*
1111     * Check for an image to print.
1112     */
1113
1114    if (plPtr->imageLeft) {
1115      if(!prepass) {
1116        delta = (plPtr->header.y2 - plPtr->header.y1)/2 - plPtr->imageLeftH/2;
1117        sprintf(buffer, "%.15g %.15g", xpos,
1118                Tk_CanvasPsY(canvas, plPtr->y+delta+2));
1119        Tcl_AppendResult(interp, buffer, " translate\n", (char *) NULL);
1120      }
1121/****
1122      Tk_PostscriptImage(plPtr->imageLeft, interp, canvasWin,
1123                         ((TkCanvas*)canvas)->psInfo, 0, 0,
1124                         plPtr->imageLeftW, plPtr->imageLeftH, prepass);
1125****/
1126
1127      if ( !prepass ) {
1128        /*
1129         * This PS code is needed in order for the label to display
1130         * correctly
1131         */
1132       
1133        Tcl_AppendResult(interp,"grestore\ngsave\n",(char *)NULL);
1134      }
1135
1136      xpos += plPtr->imageLeftW + plPtr->padding;
1137    }
1138
1139   
1140    if (prepass != 0 ) {
1141      return TCL_OK;
1142    }
1143
1144    /*
1145     * Before drawing the text, reset the font and color information.
1146     * Otherwise the text won't appear.
1147     */
1148
1149    if ( plPtr->imageLeft ){
1150      if (Tk_CanvasPsFont(interp, canvas, plPtr->tkfont) != TCL_OK) {
1151        return TCL_ERROR;
1152      }
1153     
1154      if (Tk_CanvasPsColor(interp, canvas, plPtr->textColor) != TCL_OK) {
1155        return TCL_ERROR;
1156      }
1157    }
1158
1159
1160    /*
1161     * Draw the text for the placard.
1162     */
1163    sprintf(buffer, "%.15g %.15g [\n", xpos,
1164        Tk_CanvasPsY(canvas, plPtr->y));
1165    Tcl_AppendResult(interp, buffer, (char *) NULL);
1166
1167    Tk_TextLayoutToPostscript(interp, plPtr->textLayout);
1168
1169    x = 0;  y = 0;  justify = NULL;
1170    switch (plPtr->anchor) {
1171        case TK_ANCHOR_NW:        x = 0; y = 0;        break;
1172        case TK_ANCHOR_N:         x = 1; y = 0;        break;
1173        case TK_ANCHOR_NE:        x = 2; y = 0;        break;
1174        case TK_ANCHOR_E:         x = 2; y = 1;        break;
1175        case TK_ANCHOR_SE:        x = 2; y = 2;        break;
1176        case TK_ANCHOR_S:         x = 1; y = 2;        break;
1177        case TK_ANCHOR_SW:        x = 0; y = 2;        break;
1178        case TK_ANCHOR_W:         x = 0; y = 1;        break;
1179        case TK_ANCHOR_CENTER:    x = 1; y = 1;        break;
1180    }
1181    justify = "0"; /* TK_JUSTIFY_LEFT */
1182
1183    Tk_GetFontMetrics(plPtr->tkfont, &fm);
1184    sprintf(buffer, "] %d %g %g %s %s DrawText\n",
1185            fm.linespace, x / -2.0, y / 2.0, justify,
1186            "false" /* stipple */);
1187    Tcl_AppendResult(interp, buffer, (char *) NULL);
1188
1189    return TCL_OK;
1190}
1191
1192/*
1193 * ----------------------------------------------------------------------
1194 *
1195 * ImageLeftChangedProc --
1196 *
1197 *      This procedure is invoked by the image code whenever the manager
1198 *      for an image does something that affects the image's size or
1199 *      how it is displayed.
1200 *
1201 * Results:
1202 *      None.
1203 *
1204 * Side effects:
1205 *      Arranges for the canvas to get redisplayed.
1206 *
1207 * ----------------------------------------------------------------------
1208 */
1209static void
1210ImageLeftChangedProc(clientData, x, y, width, height, imgWidth, imgHeight)
1211    ClientData clientData;              /* Pointer to canvas item for image. */
1212    int x, y;                           /* Upper left pixel (within image)
1213                                         * that must be redisplayed. */
1214    int width, height;                  /* Dimensions of area to redisplay
1215                                         * (may be <= 0). */
1216    int imgWidth, imgHeight;            /* New dimensions of image. */
1217{     
1218    PlacardItem *plPtr = (PlacardItem *) clientData;
1219   
1220    plPtr->imageLeftW = imgWidth;
1221    plPtr->imageLeftH = imgHeight;
1222    ComputePlacardBbox(plPtr->canvas, plPtr);
1223    return;
1224}
1225
1226/*
1227 * ----------------------------------------------------------------------
1228 *
1229 * ImageRightChangedProc --
1230 *
1231 *      This procedure is invoked by the image code whenever the manager
1232 *      for an image does something that affects the image's size or
1233 *      how it is displayed.
1234 *
1235 * Results:
1236 *      None.
1237 *
1238 * Side effects:
1239 *      Arranges for the canvas to get redisplayed.
1240 *
1241 * ----------------------------------------------------------------------
1242 */
1243static void
1244ImageRightChangedProc(clientData, x, y, width, height, imgWidth, imgHeight)
1245    ClientData clientData;              /* Pointer to canvas item for image. */
1246    int x, y;                           /* Upper left pixel (within image)
1247                                         * that must be redisplayed. */
1248    int width, height;                  /* Dimensions of area to redisplay
1249                                         * (may be <= 0). */
1250    int imgWidth, imgHeight;            /* New dimensions of image. */
1251{     
1252    PlacardItem *plPtr = (PlacardItem *) clientData;
1253   
1254    plPtr->imageRightW = imgWidth;
1255    plPtr->imageRightH = imgHeight;
1256    ComputePlacardBbox(plPtr->canvas, plPtr);
1257    return;
1258}
Note: See TracBrowser for help on using the repository browser.