home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / mac / tkMacMenubutton.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  9.1 KB  |  340 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tkMacMenubutton.c --
  3.  *
  4.  *    This file implements the Macintosh specific portion of the
  5.  *    menubutton widget.
  6.  *
  7.  * Copyright (c) 1996 by Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tkMacMenubutton.c 1.4 97/01/03 13:55:19
  13.  */
  14.  
  15. #include "tkMenubutton.h"
  16. #include "tkMacInt.h"
  17. #include <Controls.h>
  18.  
  19. #define kShadowOffset                (3)    /* amount to offset shadow from frame */
  20. #define kTriangleWidth                (11)    /* width of the triangle */
  21. #define kTriangleHeight                (6)    /* height of the triangle */
  22. #define kTriangleMargin                (5)    /* margin around triangle */
  23.  
  24. /*
  25.  * Declaration of Unix specific button structure.
  26.  */
  27.  
  28. typedef struct MacMenuButton {
  29.     TkMenuButton info;        /* Generic button info. */
  30. } MacMenuButton;
  31.  
  32. /*
  33.  * The structure below defines menubutton class behavior by means of
  34.  * procedures that can be invoked from generic window code.
  35.  */
  36.  
  37. TkClassProcs tkpMenubuttonClass = {
  38.     NULL,            /* createProc. */
  39.     TkMenuButtonWorldChanged,    /* geometryProc. */
  40.     NULL            /* modalProc. */
  41. };
  42.  
  43. /*
  44.  *----------------------------------------------------------------------
  45.  *
  46.  * TkpCreateMenuButton --
  47.  *
  48.  *    Allocate a new TkMenuButton structure.
  49.  *
  50.  * Results:
  51.  *    Returns a newly allocated TkMenuButton structure.
  52.  *
  53.  * Side effects:
  54.  *    Registers an event handler for the widget.
  55.  *
  56.  *----------------------------------------------------------------------
  57.  */
  58.  
  59. TkMenuButton *
  60. TkpCreateMenuButton(
  61.     Tk_Window tkwin)
  62. {
  63.     MacMenuButton *butPtr = (MacMenuButton *)ckalloc(sizeof(MacMenuButton));
  64.  
  65.     return (TkMenuButton *) butPtr;
  66. }
  67.  
  68. /*
  69.  *----------------------------------------------------------------------
  70.  *
  71.  * TkpDisplayMenuButton --
  72.  *
  73.  *    This procedure is invoked to display a menubutton widget.
  74.  *
  75.  * Results:
  76.  *    None.
  77.  *
  78.  * Side effects:
  79.  *    Commands are output to X to display the menubutton in its
  80.  *    current mode.
  81.  *
  82.  *----------------------------------------------------------------------
  83.  */
  84.  
  85. void
  86. TkpDisplayMenuButton(
  87.     ClientData clientData)    /* Information about widget. */
  88. {
  89.     TkMenuButton *mbPtr = (TkMenuButton *) clientData;
  90.     GC gc;
  91.     Tk_3DBorder border;
  92.     int x = 0;            /* Initialization needed only to stop
  93.                  * compiler warning. */
  94.     int y;
  95.     Tk_Window tkwin = mbPtr->tkwin;
  96.     int width, height;
  97.     MacMenuButton * macMBPtr = (MacMenuButton *) mbPtr;
  98.     GWorldPtr destPort;
  99.     CGrafPtr saveWorld;
  100.     GDHandle saveDevice;
  101.     MacDrawable *macDraw;
  102.  
  103.     mbPtr->flags &= ~REDRAW_PENDING;
  104.     if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
  105.     return;
  106.     }
  107.  
  108.     GetGWorld(&saveWorld, &saveDevice);
  109.     destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
  110.     SetGWorld(destPort, NULL);
  111.     macDraw = (MacDrawable *) Tk_WindowId(tkwin);
  112.  
  113.     if ((mbPtr->state == tkDisabledUid) && (mbPtr->disabledFg != NULL)) {
  114.     gc = mbPtr->disabledGC;
  115.     } else if ((mbPtr->state == tkActiveUid) && !Tk_StrictMotif(mbPtr->tkwin)) {
  116.     gc = mbPtr->activeTextGC;
  117.     } else {
  118.     gc = mbPtr->normalTextGC;
  119.     }
  120.     border = mbPtr->normalBorder;
  121.  
  122.     /*
  123.      * In order to avoid screen flashes, this procedure redraws
  124.      * the menu button in a pixmap, then copies the pixmap to the
  125.      * screen in a single operation.  This means that there's no
  126.      * point in time where the on-sreen image has been cleared.
  127.      */
  128.  
  129.     Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, 0, 0,
  130.         Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
  131.  
  132.     /*
  133.      * Display image or bitmap or text for button.
  134.      */
  135.  
  136.     if (mbPtr->image != None) {
  137.     Tk_SizeOfImage(mbPtr->image, &width, &height);
  138.  
  139.     imageOrBitmap:
  140.     TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, 
  141.         width + mbPtr->indicatorWidth, height, &x, &y);
  142.     if (mbPtr->image != NULL) {
  143.         Tk_RedrawImage(mbPtr->image, 0, 0, width, height,
  144.             Tk_WindowId(tkwin), x, y);
  145.     } else {
  146.         XCopyPlane(mbPtr->display, mbPtr->bitmap, Tk_WindowId(tkwin),
  147.             gc, 0, 0, (unsigned) width, (unsigned) height, x, y, 1);
  148.     }
  149.     } else if (mbPtr->bitmap != None) {
  150.     Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
  151.     goto imageOrBitmap;
  152.     } else {
  153.     TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY,
  154.         mbPtr->textWidth + mbPtr->indicatorWidth, mbPtr->textHeight,
  155.         &x, &y);
  156.     Tk_DrawTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc,
  157.         mbPtr->textLayout, x, y, 0, -1);
  158.     }
  159.  
  160.     /*
  161.      * If the menu button is disabled with a stipple rather than a special
  162.      * foreground color, generate the stippled effect.
  163.      */
  164.  
  165.     if ((mbPtr->state == tkDisabledUid)
  166.         && ((mbPtr->disabledFg == NULL) || (mbPtr->image != NULL))) {
  167.     XFillRectangle(mbPtr->display, Tk_WindowId(tkwin), mbPtr->disabledGC,
  168.         mbPtr->inset, mbPtr->inset,
  169.         (unsigned) (Tk_Width(tkwin) - 2*mbPtr->inset),
  170.         (unsigned) (Tk_Height(tkwin) - 2*mbPtr->inset));
  171.     }
  172.  
  173.     /*
  174.      * Draw the cascade indicator for the menu button on the
  175.      * right side of the window, if desired.
  176.      */
  177.  
  178.     if (mbPtr->indicatorOn) {
  179.     int w, h, i;
  180.     Rect r;
  181.  
  182.     r.left = macDraw->xOff + Tk_Width(tkwin) - mbPtr->inset
  183.         - mbPtr->indicatorWidth;
  184.     r.top = macDraw->yOff + Tk_Height(tkwin)/2
  185.         - mbPtr->indicatorHeight/2;
  186.     r.right = macDraw->xOff + Tk_Width(tkwin) - mbPtr->inset
  187.         - kTriangleMargin;
  188.     r.bottom = macDraw->yOff + Tk_Height(tkwin)/2
  189.         + mbPtr->indicatorHeight/2;
  190.  
  191.     h = mbPtr->indicatorHeight;
  192.     w = mbPtr->indicatorWidth - 1 - kTriangleMargin;
  193.     for (i = 0; i < h; i++) {
  194.         MoveTo(r.left + i, r.top + i);
  195.         LineTo(r.left + i + w, r.top + i);
  196.         w -= 2;
  197.     }
  198.     }
  199.  
  200.     /*
  201.      * Draw the border and traversal highlight last.  This way, if the
  202.      * menu button's contents overflow onto the border they'll be covered
  203.      * up by the border.
  204.      */
  205.  
  206.     TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
  207.     if (mbPtr->borderWidth > 0) {
  208.     Rect r;
  209.     
  210.     r.left = macDraw->xOff + mbPtr->highlightWidth + mbPtr->borderWidth;
  211.     r.top = macDraw->yOff + mbPtr->highlightWidth + mbPtr->borderWidth;
  212.     r.right = macDraw->xOff + Tk_Width(tkwin) - mbPtr->highlightWidth
  213.         - mbPtr->borderWidth;
  214.     r.bottom = macDraw->yOff + Tk_Height(tkwin) - mbPtr->highlightWidth
  215.         - mbPtr->borderWidth;
  216.     FrameRect(&r);
  217.  
  218.     PenSize(mbPtr->borderWidth - 1, mbPtr->borderWidth - 1);
  219.     MoveTo(r.right, r.top + kShadowOffset);
  220.     LineTo(r.right, r.bottom);
  221.     LineTo(r.left + kShadowOffset, r.bottom);
  222.     }
  223.     
  224.     if (mbPtr->state == tkDisabledUid) {
  225.     }
  226.     
  227.     if (mbPtr->highlightWidth != 0) {
  228.     GC gc;
  229.  
  230.     if (mbPtr->flags & GOT_FOCUS) {
  231.         gc = Tk_GCForColor(mbPtr->highlightColorPtr, Tk_WindowId(tkwin));
  232.     } else {
  233.         gc = Tk_GCForColor(mbPtr->highlightBgColorPtr, Tk_WindowId(tkwin));
  234.     }
  235.     Tk_DrawFocusHighlight(tkwin, gc, mbPtr->highlightWidth,
  236.         Tk_WindowId(tkwin));
  237.     }
  238.  
  239.     SetGWorld(saveWorld, saveDevice);
  240. }
  241.  
  242. /*
  243.  *----------------------------------------------------------------------
  244.  *
  245.  * TkpDestroyMenuButton --
  246.  *
  247.  *    Free data structures associated with the menubutton control.
  248.  *
  249.  * Results:
  250.  *    None.
  251.  *
  252.  * Side effects:
  253.  *    Restores the default control state.
  254.  *
  255.  *----------------------------------------------------------------------
  256.  */
  257.  
  258. void
  259. TkpDestroyMenuButton(
  260.     TkMenuButton *mbPtr)
  261. {
  262. }
  263.  
  264. /*
  265.  *----------------------------------------------------------------------
  266.  *
  267.  * TkpComputeMenuButtonGeometry --
  268.  *
  269.  *    After changes in a menu button's text or bitmap, this procedure
  270.  *    recomputes the menu button's geometry and passes this information
  271.  *    along to the geometry manager for the window.
  272.  *
  273.  * Results:
  274.  *    None.
  275.  *
  276.  * Side effects:
  277.  *    The menu button's window may change size.
  278.  *
  279.  *----------------------------------------------------------------------
  280.  */
  281.  
  282. void
  283. TkpComputeMenuButtonGeometry(mbPtr)
  284.     register TkMenuButton *mbPtr;        /* Widget record for menu button. */
  285. {
  286.     int width, height, mm, pixels;
  287.  
  288.     mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth;
  289.     if (mbPtr->image != None) {
  290.     Tk_SizeOfImage(mbPtr->image, &width, &height);
  291.     if (mbPtr->width > 0) {
  292.         width = mbPtr->width;
  293.     }
  294.     if (mbPtr->height > 0) {
  295.         height = mbPtr->height;
  296.     }
  297.     } else if (mbPtr->bitmap != None) {
  298.     Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
  299.     if (mbPtr->width > 0) {
  300.         width = mbPtr->width;
  301.     }
  302.     if (mbPtr->height > 0) {
  303.         height = mbPtr->height;
  304.     }
  305.     } else {
  306.     Tk_FreeTextLayout(mbPtr->textLayout);
  307.     mbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->text,
  308.         -1, mbPtr->wrapLength, mbPtr->justify, 0, &mbPtr->textWidth,
  309.         &mbPtr->textHeight);
  310.     width = mbPtr->textWidth;
  311.     height = mbPtr->textHeight;
  312.     if (mbPtr->width > 0) {
  313.         width = mbPtr->width * Tk_TextWidth(mbPtr->tkfont, "0", 1);
  314.     }
  315.     if (mbPtr->height > 0) {
  316.         Tk_FontMetrics fm;
  317.  
  318.         Tk_GetFontMetrics(mbPtr->tkfont, &fm);
  319.         height = mbPtr->height * fm.linespace;
  320.     }
  321.     width += 2*mbPtr->padX;
  322.     height += 2*mbPtr->padY;
  323.     }
  324.  
  325.     if (mbPtr->indicatorOn) {
  326.     mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin));
  327.     pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin));
  328.     mbPtr->indicatorHeight= kTriangleHeight;
  329.     mbPtr->indicatorWidth = kTriangleWidth + kTriangleMargin;
  330.     width += mbPtr->indicatorWidth;
  331.     } else {
  332.     mbPtr->indicatorHeight = 0;
  333.     mbPtr->indicatorWidth = 0;
  334.     }
  335.  
  336.     Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset),
  337.         (int) (height + 2*mbPtr->inset));
  338.     Tk_SetInternalBorder(mbPtr->tkwin, mbPtr->inset);
  339. }
  340.