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

通讯编程

开发平台:

Visual C++

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