tkMacMenubutton.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:15k
源码类别:

通讯编程

开发平台:

Visual C++

  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.  * RCS: @(#) $Id: tkMacMenubutton.c,v 1.9.4.1 2003/11/17 23:29:36 hobbs Exp $
  13.  */
  14. #include "tkMenubutton.h"
  15. #include "tkMacInt.h"
  16. #include <Controls.h>
  17. #define kShadowOffset (3) /* amount to offset shadow from frame */
  18. #define kTriangleWidth (11) /* width of the triangle */
  19. #define kTriangleHeight (6) /* height of the triangle */
  20. #define kTriangleMargin (5) /* margin around triangle */
  21. /*
  22.  * Declaration of Unix specific button structure.
  23.  */
  24. typedef struct MacMenuButton {
  25.     TkMenuButton info; /* Generic button info. */
  26. } MacMenuButton;
  27. /*
  28.  * The structure below defines menubutton class behavior by means of
  29.  * procedures that can be invoked from generic window code.
  30.  */
  31. Tk_ClassProcs tkpMenubuttonClass = {
  32.     sizeof(Tk_ClassProcs), /* size */
  33.     TkMenuButtonWorldChanged, /* worldChangedProc */
  34. };
  35. /*
  36.  *----------------------------------------------------------------------
  37.  *
  38.  * TkpCreateMenuButton --
  39.  *
  40.  * Allocate a new TkMenuButton structure.
  41.  *
  42.  * Results:
  43.  * Returns a newly allocated TkMenuButton structure.
  44.  *
  45.  * Side effects:
  46.  * Registers an event handler for the widget.
  47.  *
  48.  *----------------------------------------------------------------------
  49.  */
  50. TkMenuButton *
  51. TkpCreateMenuButton(
  52.     Tk_Window tkwin)
  53. {
  54.     MacMenuButton *butPtr = (MacMenuButton *)ckalloc(sizeof(MacMenuButton));
  55.     return (TkMenuButton *) butPtr;
  56. }
  57. /*
  58.  *----------------------------------------------------------------------
  59.  *
  60.  * TkpDisplayMenuButton --
  61.  *
  62.  * This procedure is invoked to display a menubutton widget.
  63.  *
  64.  * Results:
  65.  * None.
  66.  *
  67.  * Side effects:
  68.  * Commands are output to X to display the menubutton in its
  69.  * current mode.
  70.  *
  71.  *----------------------------------------------------------------------
  72.  */
  73. void
  74. TkpDisplayMenuButton(
  75.     ClientData clientData) /* Information about widget. */
  76. {
  77.     TkMenuButton *mbPtr = (TkMenuButton *) clientData;
  78.     GC gc;
  79.     Tk_3DBorder border;
  80.     int x = 0; /* Initialization needed only to stop
  81.  * compiler warning. */
  82.     int y;
  83.     Tk_Window tkwin = mbPtr->tkwin;
  84.     int width, height, fullWidth, fullHeight;
  85.     int imageWidth, imageHeight;
  86.     int imageXOffset, imageYOffset, textXOffset, textYOffset;
  87.     int haveImage = 0, haveText = 0;
  88.     MacMenuButton * macMBPtr = (MacMenuButton *) mbPtr;
  89.     GWorldPtr destPort;
  90.     CGrafPtr saveWorld;
  91.     GDHandle saveDevice;
  92.     MacDrawable *macDraw;
  93.     mbPtr->flags &= ~REDRAW_PENDING;
  94.     if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
  95. return;
  96.     }
  97.     GetGWorld(&saveWorld, &saveDevice);
  98.     destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
  99.     SetGWorld(destPort, NULL);
  100.     macDraw = (MacDrawable *) Tk_WindowId(tkwin);
  101.     if ((mbPtr->state == STATE_DISABLED) && (mbPtr->disabledFg != NULL)) {
  102. gc = mbPtr->disabledGC;
  103.     } else if ((mbPtr->state == STATE_ACTIVE)
  104.     && !Tk_StrictMotif(mbPtr->tkwin)) {
  105. gc = mbPtr->activeTextGC;
  106.     } else {
  107. gc = mbPtr->normalTextGC;
  108.     }
  109.     border = mbPtr->normalBorder;
  110.     if (mbPtr->image != None) {
  111.         Tk_SizeOfImage(mbPtr->image, &width, &height);
  112.         haveImage = 1;
  113.     } else if (mbPtr->bitmap != None) {
  114.         Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
  115.         haveImage = 1;
  116.     }
  117.     imageWidth  = width;
  118.     imageHeight = height;
  119.     haveText = (mbPtr->textWidth != 0 && mbPtr->textHeight != 0);
  120.     /*
  121.      * In order to avoid screen flashes, this procedure redraws
  122.      * the menu button in a pixmap, then copies the pixmap to the
  123.      * screen in a single operation.  This means that there's no
  124.      * point in time where the on-sreen image has been cleared.
  125.      */
  126.     Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, 0, 0,
  127.     Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
  128.     imageXOffset = 0;
  129.     imageYOffset = 0;
  130.     textXOffset = 0;
  131.     textYOffset = 0;
  132.     fullWidth = 0;
  133.     fullHeight = 0;
  134.     if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) {
  135.         switch ((enum compound) mbPtr->compound) {
  136.             case COMPOUND_TOP:
  137.             case COMPOUND_BOTTOM: {
  138.                 /* Image is above or below text */
  139.                 if (mbPtr->compound == COMPOUND_TOP) {
  140.                     textYOffset = height + mbPtr->padY;
  141.                 } else {
  142.                     imageYOffset = mbPtr->textHeight + mbPtr->padY;
  143.                 }
  144.                 fullHeight = height + mbPtr->textHeight + mbPtr->padY;
  145.                 fullWidth = (width > mbPtr->textWidth ? width :
  146.                         mbPtr->textWidth);
  147.                 textXOffset = (fullWidth - mbPtr->textWidth)/2;
  148.                 imageXOffset = (fullWidth - width)/2;
  149.                 break;
  150.             }
  151.             case COMPOUND_LEFT:
  152.             case COMPOUND_RIGHT: {
  153.                 /* Image is left or right of text */
  154.                 if (mbPtr->compound == COMPOUND_LEFT) {
  155.                     textXOffset = width + mbPtr->padX;
  156.                 } else {
  157.                     imageXOffset = mbPtr->textWidth + mbPtr->padX;
  158.                 }
  159.                 fullWidth = mbPtr->textWidth + mbPtr->padX + width;
  160.                 fullHeight = (height > mbPtr->textHeight ? height :
  161.                         mbPtr->textHeight);
  162.                 textYOffset = (fullHeight - mbPtr->textHeight)/2;
  163.                 imageYOffset = (fullHeight - height)/2;
  164.                 break;
  165.             }
  166.             case COMPOUND_CENTER: {
  167.                 /* Image and text are superimposed */
  168.                 fullWidth = (width > mbPtr->textWidth ? width :
  169.                         mbPtr->textWidth);
  170.                 fullHeight = (height > mbPtr->textHeight ? height :
  171.                         mbPtr->textHeight);
  172.                 textXOffset = (fullWidth - mbPtr->textWidth)/2;
  173.                 imageXOffset = (fullWidth - width)/2;
  174.                 textYOffset = (fullHeight - mbPtr->textHeight)/2;
  175.                 imageYOffset = (fullHeight - height)/2;
  176.                 break;
  177.             }
  178.             case COMPOUND_NONE: {break;}
  179.         }
  180.         TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0,
  181.                 mbPtr->indicatorWidth + fullWidth, fullHeight,
  182.                 &x, &y);
  183. imageXOffset += x;
  184. imageYOffset += y;
  185.         if (mbPtr->image != NULL) {
  186.             Tk_RedrawImage(mbPtr->image, 0, 0, width, height, Tk_WindowId(tkwin),
  187.                     imageXOffset, imageYOffset);
  188.         } else if (mbPtr->bitmap != None) {
  189.             XCopyPlane(mbPtr->display, mbPtr->bitmap, Tk_WindowId(tkwin),
  190.                     gc, 0, 0, (unsigned) width, (unsigned) height,
  191.                     imageXOffset, imageYOffset, 1);
  192.         }
  193. Tk_DrawTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc,
  194. mbPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1);
  195. Tk_UnderlineTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc,
  196. mbPtr->textLayout, x + textXOffset, y + textYOffset,
  197. mbPtr->underline);
  198.     } else if (haveImage) {
  199. TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0,
  200. width + mbPtr->indicatorWidth, height, &x, &y);
  201. imageXOffset += x;
  202. imageYOffset += y;
  203. if (mbPtr->image != NULL) {
  204.     Tk_RedrawImage(mbPtr->image, 0, 0, width, height, Tk_WindowId(tkwin),
  205.     imageXOffset, imageYOffset);
  206. } else if (mbPtr->bitmap != None) {
  207.     XCopyPlane(mbPtr->display, mbPtr->bitmap, Tk_WindowId(tkwin),
  208.     gc, 0, 0, (unsigned) width, (unsigned) height, 
  209.     x, y, 1);
  210. }
  211.     } else {
  212. TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY,
  213. mbPtr->textWidth + mbPtr->indicatorWidth,
  214. mbPtr->textHeight, &x, &y);
  215. Tk_DrawTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc,
  216. mbPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1);
  217. Tk_UnderlineTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc,
  218. mbPtr->textLayout, x + textXOffset, y + textYOffset,
  219. mbPtr->underline);
  220.     }
  221. #if 0 /* this is the original code */
  222.     /*
  223.      * Display image or bitmap or text for button.
  224.      */
  225.     if (mbPtr->image != None) {
  226. Tk_SizeOfImage(mbPtr->image, &width, &height);
  227. imageOrBitmap:
  228. TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, 
  229. width + mbPtr->indicatorWidth, height, &x, &y);
  230. if (mbPtr->image != NULL) {
  231.     Tk_RedrawImage(mbPtr->image, 0, 0, width, height,
  232.     Tk_WindowId(tkwin), x, y);
  233. } else {
  234.     XCopyPlane(mbPtr->display, mbPtr->bitmap, Tk_WindowId(tkwin),
  235.     gc, 0, 0, (unsigned) width, (unsigned) height, x, y, 1);
  236. }
  237.     } else if (mbPtr->bitmap != None) {
  238. Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
  239. goto imageOrBitmap;
  240.     } else {
  241. TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY,
  242. mbPtr->textWidth + mbPtr->indicatorWidth, mbPtr->textHeight,
  243. &x, &y);
  244. Tk_DrawTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc,
  245. mbPtr->textLayout, x, y, 0, -1);
  246.     }
  247. #endif
  248.     /*
  249.      * If the menu button is disabled with a stipple rather than a special
  250.      * foreground color, generate the stippled effect.
  251.      */
  252.     if ((mbPtr->state == STATE_DISABLED)
  253.     && ((mbPtr->disabledFg != NULL) || (mbPtr->image != NULL))) {
  254. /*
  255.  * Stipple the whole button if no disabledFg was specified,
  256.  * otherwise restrict stippling only to displayed image
  257.  */
  258. if (mbPtr->disabledFg == NULL) {
  259.     XFillRectangle(mbPtr->display, Tk_WindowId(tkwin),
  260.     mbPtr->stippleGC, mbPtr->inset, mbPtr->inset,
  261.     (unsigned) (Tk_Width(tkwin) - 2*mbPtr->inset),
  262.     (unsigned) (Tk_Height(tkwin) - 2*mbPtr->inset));
  263. } else {
  264.     XFillRectangle(mbPtr->display, Tk_WindowId(tkwin),
  265.     mbPtr->stippleGC, imageXOffset, imageYOffset,
  266.     (unsigned) imageWidth, (unsigned) imageHeight);
  267. }
  268.     }
  269.     /*
  270.      * Draw the cascade indicator for the menu button on the
  271.      * right side of the window, if desired.
  272.      */
  273.     if (mbPtr->indicatorOn) {
  274. int w, h, i;
  275. Rect r;
  276. r.left = macDraw->xOff + Tk_Width(tkwin) - mbPtr->inset
  277.     - mbPtr->indicatorWidth;
  278. r.top = macDraw->yOff + Tk_Height(tkwin)/2
  279.     - mbPtr->indicatorHeight/2;
  280. r.right = macDraw->xOff + Tk_Width(tkwin) - mbPtr->inset
  281.     - kTriangleMargin;
  282. r.bottom = macDraw->yOff + Tk_Height(tkwin)/2
  283.     + mbPtr->indicatorHeight/2;
  284. h = mbPtr->indicatorHeight;
  285. w = mbPtr->indicatorWidth - 1 - kTriangleMargin;
  286. for (i = 0; i < h; i++) {
  287.     MoveTo(r.left + i, r.top + i);
  288.     LineTo(r.left + i + w, r.top + i);
  289.     w -= 2;
  290. }
  291.     }
  292.     /*
  293.      * Draw the border and traversal highlight last.  This way, if the
  294.      * menu button's contents overflow onto the border they'll be covered
  295.      * up by the border.
  296.      */
  297.     TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
  298.     if (mbPtr->borderWidth > 0) {
  299. Rect r;
  300. r.left = macDraw->xOff + mbPtr->highlightWidth + mbPtr->borderWidth;
  301. r.top = macDraw->yOff + mbPtr->highlightWidth + mbPtr->borderWidth;
  302. r.right = macDraw->xOff + Tk_Width(tkwin) - mbPtr->highlightWidth
  303.     - mbPtr->borderWidth;
  304. r.bottom = macDraw->yOff + Tk_Height(tkwin) - mbPtr->highlightWidth
  305.     - mbPtr->borderWidth;
  306. FrameRect(&r);
  307. PenSize(mbPtr->borderWidth - 1, mbPtr->borderWidth - 1);
  308. MoveTo(r.right, r.top + kShadowOffset);
  309. LineTo(r.right, r.bottom);
  310. LineTo(r.left + kShadowOffset, r.bottom);
  311.     }
  312.     
  313.     if (mbPtr->highlightWidth != 0) {
  314. GC fgGC, bgGC;
  315. bgGC = Tk_GCForColor(mbPtr->highlightBgColorPtr, Tk_WindowId(tkwin));
  316. if (mbPtr->flags & GOT_FOCUS) {
  317.     fgGC = Tk_GCForColor(mbPtr->highlightColorPtr, Tk_WindowId(tkwin));
  318.     TkpDrawHighlightBorder(tkwin, fgGC, bgGC, mbPtr->highlightWidth,
  319.     Tk_WindowId(tkwin));
  320. } else {
  321.     TkpDrawHighlightBorder(tkwin, bgGC, bgGC, mbPtr->highlightWidth,
  322.     Tk_WindowId(tkwin));
  323. }
  324.     }
  325.     SetGWorld(saveWorld, saveDevice);
  326. }
  327. /*
  328.  *----------------------------------------------------------------------
  329.  *
  330.  * TkpDestroyMenuButton --
  331.  *
  332.  * Free data structures associated with the menubutton control.
  333.  *
  334.  * Results:
  335.  * None.
  336.  *
  337.  * Side effects:
  338.  * Restores the default control state.
  339.  *
  340.  *----------------------------------------------------------------------
  341.  */
  342. void
  343. TkpDestroyMenuButton(
  344.     TkMenuButton *mbPtr)
  345. {
  346. }
  347. /*
  348.  *----------------------------------------------------------------------
  349.  *
  350.  * TkpComputeMenuButtonGeometry --
  351.  *
  352.  * After changes in a menu button's text or bitmap, this procedure
  353.  * recomputes the menu button's geometry and passes this information
  354.  * along to the geometry manager for the window.
  355.  *
  356.  * Results:
  357.  * None.
  358.  *
  359.  * Side effects:
  360.  * The menu button's window may change size.
  361.  *
  362.  *----------------------------------------------------------------------
  363.  */
  364. void
  365. TkpComputeMenuButtonGeometry(mbPtr)
  366.     register TkMenuButton *mbPtr; /* Widget record for menu button. */
  367. {
  368.     int width=0, height=0, textwidth=0, textheight=0, mm, pixels, noimage=0;
  369.     mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth;
  370.     if (mbPtr->image != None) {
  371. Tk_SizeOfImage(mbPtr->image, &width, &height);
  372. if (mbPtr->width > 0) {
  373.     width = mbPtr->width;
  374. }
  375. if (mbPtr->height > 0) {
  376.     height = mbPtr->height;
  377. }
  378.     } else if (mbPtr->bitmap != None) {
  379. Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
  380. if (mbPtr->width > 0) {
  381.     width = mbPtr->width;
  382. }
  383. if (mbPtr->height > 0) {
  384.     height = mbPtr->height;
  385. }
  386.     } else {
  387.     noimage=1;
  388.     }
  389.     
  390.     if ( noimage || mbPtr->compound != COMPOUND_NONE ) {
  391. Tk_FreeTextLayout(mbPtr->textLayout);
  392. mbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->text,
  393. -1, mbPtr->wrapLength, mbPtr->justify, 0, &mbPtr->textWidth,
  394. &mbPtr->textHeight);
  395. textwidth = mbPtr->textWidth;
  396. textheight = mbPtr->textHeight;
  397. if (mbPtr->width > 0) {
  398.     textwidth = mbPtr->width * Tk_TextWidth(mbPtr->tkfont, "0", 1);
  399. }
  400. if (mbPtr->height > 0) {
  401.     Tk_FontMetrics fm;
  402.     Tk_GetFontMetrics(mbPtr->tkfont, &fm);
  403.     textheight = mbPtr->height * fm.linespace;
  404. }
  405. textwidth += 2*mbPtr->padX;
  406. textheight +=  2*mbPtr->padY;
  407.     }
  408.     
  409. switch ((enum compound) mbPtr->compound) {
  410.   case COMPOUND_TOP:
  411.   case COMPOUND_BOTTOM: {
  412.       height += textheight + mbPtr->padY;
  413.       width = (width > textwidth ? width : textwidth);
  414.       break;
  415.   }
  416.   case COMPOUND_LEFT:
  417.   case COMPOUND_RIGHT: {
  418.       height = (height > textheight ? height : textheight);
  419.       width += textwidth + mbPtr->padX;
  420.       break;
  421.   }
  422.   case COMPOUND_CENTER: {
  423.       height = (height > textheight ? height : textheight);
  424.       width = (width > textwidth ? width : textwidth);
  425.       break;
  426.   }
  427.   case COMPOUND_NONE: {
  428.      if (noimage) {
  429.       height = textheight;
  430.       width = textwidth;
  431.      }
  432.      break;
  433. }
  434.     }
  435.     if (mbPtr->indicatorOn) {
  436. mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin));
  437. pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin));
  438. mbPtr->indicatorHeight= kTriangleHeight;
  439. mbPtr->indicatorWidth = kTriangleWidth + kTriangleMargin;
  440. width += mbPtr->indicatorWidth;
  441.     } else {
  442. mbPtr->indicatorHeight = 0;
  443. mbPtr->indicatorWidth = 0;
  444.     }
  445.     Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset),
  446.     (int) (height + 2*mbPtr->inset));
  447.     Tk_SetInternalBorder(mbPtr->tkwin, mbPtr->inset);
  448. }