📄 tkbutton.c
字号:
if (argc < 2) { sprintf(interp->result, "wrong # args: should be \"%.50s option ?arg arg ...?\"", argv[0]); return TCL_ERROR; } Tcl_Preserve((ClientData) butPtr); c = argv[1][0]; length = strlen(argv[1]); if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0) && (length >= 2)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " cget option\"", (char *) NULL); goto error; } result = Tk_ConfigureValue(interp, butPtr->tkwin, tkpButtonConfigSpecs, (char *) butPtr, argv[2], configFlags[butPtr->type]); } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0) && (length >= 2)) { if (argc == 2) { result = Tk_ConfigureInfo(interp, butPtr->tkwin, tkpButtonConfigSpecs, (char *) butPtr, (char *) NULL, configFlags[butPtr->type]); } else if (argc == 3) { result = Tk_ConfigureInfo(interp, butPtr->tkwin, tkpButtonConfigSpecs, (char *) butPtr, argv[2], configFlags[butPtr->type]); } else { result = ConfigureButton(interp, butPtr, argc-2, argv+2, configFlags[butPtr->type] | TK_CONFIG_ARGV_ONLY); } } else if ((c == 'd') && (strncmp(argv[1], "deselect", length) == 0) && (butPtr->type >= TYPE_CHECK_BUTTON)) { if (argc > 2) { sprintf(interp->result, "wrong # args: should be \"%.50s deselect\"", argv[0]); goto error; } if (butPtr->type == TYPE_CHECK_BUTTON) { if (Tcl_SetVar(interp, butPtr->selVarName, butPtr->offValue, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; } } else if (butPtr->flags & SELECTED) { if (Tcl_SetVar(interp, butPtr->selVarName, "", TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; }; } } else if ((c == 'f') && (strncmp(argv[1], "flash", length) == 0) && (butPtr->type != TYPE_LABEL)) { int i; if (argc > 2) { sprintf(interp->result, "wrong # args: should be \"%.50s flash\"", argv[0]); goto error; } if (butPtr->state != tkDisabledUid) { for (i = 0; i < 4; i++) { butPtr->state = (butPtr->state == tkNormalUid) ? tkActiveUid : tkNormalUid; Tk_SetBackgroundFromBorder(butPtr->tkwin, (butPtr->state == tkActiveUid) ? butPtr->activeBorder : butPtr->normalBorder); TkpDisplayButton((ClientData) butPtr); /* * Special note: must cancel any existing idle handler * for TkpDisplayButton; it's no longer needed, and TkpDisplayButton * cleared the REDRAW_PENDING flag. */ Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr); XFlush(butPtr->display); Tcl_Sleep(50); } } } else if ((c == 'i') && (strncmp(argv[1], "invoke", length) == 0) && (butPtr->type > TYPE_LABEL)) { if (argc > 2) { sprintf(interp->result, "wrong # args: should be \"%.50s invoke\"", argv[0]); goto error; } if (butPtr->state != tkDisabledUid) { result = TkInvokeButton(butPtr); } } else if ((c == 's') && (strncmp(argv[1], "select", length) == 0) && (butPtr->type >= TYPE_CHECK_BUTTON)) { if (argc > 2) { sprintf(interp->result, "wrong # args: should be \"%.50s select\"", argv[0]); goto error; } if (Tcl_SetVar(interp, butPtr->selVarName, butPtr->onValue, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; } } else if ((c == 't') && (strncmp(argv[1], "toggle", length) == 0) && (length >= 2) && (butPtr->type == TYPE_CHECK_BUTTON)) { if (argc > 2) { sprintf(interp->result, "wrong # args: should be \"%.50s toggle\"", argv[0]); goto error; } if (butPtr->flags & SELECTED) { if (Tcl_SetVar(interp, butPtr->selVarName, butPtr->offValue, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; } } else { if (Tcl_SetVar(interp, butPtr->selVarName, butPtr->onValue, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; } } } else { sprintf(interp->result, "bad option \"%.50s\": must be %s", argv[1], optionStrings[butPtr->type]); goto error; } Tcl_Release((ClientData) butPtr); return result; error: Tcl_Release((ClientData) butPtr); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * DestroyButton -- * * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release * to clean up the internal structure of a button at a safe time * (when no-one is using it anymore). * * Results: * None. * * Side effects: * Everything associated with the widget is freed up. * *---------------------------------------------------------------------- */static voidDestroyButton(butPtr) TkButton *butPtr; /* Info about button widget. */{ /* * Free up all the stuff that requires special handling, then * let Tk_FreeOptions handle all the standard option-related * stuff. */ if (butPtr->textVarName != NULL) { Tcl_UntraceVar(butPtr->interp, butPtr->textVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, (ClientData) butPtr); } if (butPtr->image != NULL) { Tk_FreeImage(butPtr->image); } if (butPtr->selectImage != NULL) { Tk_FreeImage(butPtr->selectImage); } if (butPtr->normalTextGC != None) { Tk_FreeGC(butPtr->display, butPtr->normalTextGC); } if (butPtr->activeTextGC != None) { Tk_FreeGC(butPtr->display, butPtr->activeTextGC); } if (butPtr->gray != None) { Tk_FreeBitmap(butPtr->display, butPtr->gray); } if (butPtr->disabledGC != None) { Tk_FreeGC(butPtr->display, butPtr->disabledGC); } if (butPtr->copyGC != None) { Tk_FreeGC(butPtr->display, butPtr->copyGC); } if (butPtr->selVarName != NULL) { Tcl_UntraceVar(butPtr->interp, butPtr->selVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, (ClientData) butPtr); } Tk_FreeTextLayout(butPtr->textLayout); Tk_FreeOptions(tkpButtonConfigSpecs, (char *) butPtr, butPtr->display, configFlags[butPtr->type]); Tcl_EventuallyFree((ClientData)butPtr, TCL_DYNAMIC);}/* *---------------------------------------------------------------------- * * ConfigureButton -- * * This procedure is called to process an argv/argc list, plus * the Tk option database, in order to configure (or * reconfigure) a button widget. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then interp->result contains an error message. * * Side effects: * Configuration information, such as text string, colors, font, * etc. get set for butPtr; old resources get freed, if there * were any. The button is redisplayed. * *---------------------------------------------------------------------- */static intConfigureButton(interp, butPtr, argc, argv, flags) Tcl_Interp *interp; /* Used for error reporting. */ register TkButton *butPtr; /* Information about widget; may or may * not already have values for some fields. */ int argc; /* Number of valid entries in argv. */ char **argv; /* Arguments. */ int flags; /* Flags to pass to Tk_ConfigureWidget. */{ Tk_Image image; /* * Eliminate any existing trace on variables monitored by the button. */ if (butPtr->textVarName != NULL) { Tcl_UntraceVar(interp, butPtr->textVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, (ClientData) butPtr); } if (butPtr->selVarName != NULL) { Tcl_UntraceVar(interp, butPtr->selVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, (ClientData) butPtr); } if (Tk_ConfigureWidget(interp, butPtr->tkwin, tkpButtonConfigSpecs, argc, argv, (char *) butPtr, flags) != TCL_OK) { return TCL_ERROR; } /* * A few options need special processing, such as setting the * background from a 3-D border, or filling in complicated * defaults that couldn't be specified to Tk_ConfigureWidget. */ if ((butPtr->state == tkActiveUid) && !Tk_StrictMotif(butPtr->tkwin)) { Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->activeBorder); } else { Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->normalBorder); if ((butPtr->state != tkNormalUid) && (butPtr->state != tkActiveUid) && (butPtr->state != tkDisabledUid)) { Tcl_AppendResult(interp, "bad state value \"", butPtr->state, "\": must be normal, active, or disabled", (char *) NULL); butPtr->state = tkNormalUid; return TCL_ERROR; } } if ((butPtr->defaultState != tkActiveUid) && (butPtr->defaultState != tkDisabledUid) && (butPtr->defaultState != tkNormalUid)) { Tcl_AppendResult(interp, "bad -default value \"", butPtr->defaultState, "\": must be normal, active, or disabled", (char *) NULL); butPtr->defaultState = tkDisabledUid; return TCL_ERROR; } if (butPtr->highlightWidth < 0) { butPtr->highlightWidth = 0; } if (butPtr->padX < 0) { butPtr->padX = 0; } if (butPtr->padY < 0) { butPtr->padY = 0; } if (butPtr->type >= TYPE_CHECK_BUTTON) { char *value; if (butPtr->selVarName == NULL) { butPtr->selVarName = (char *) ckalloc((unsigned) (strlen(Tk_Name(butPtr->tkwin)) + 1)); strcpy(butPtr->selVarName, Tk_Name(butPtr->tkwin)); } /* * Select the button if the associated variable has the * appropriate value, initialize the variable if it doesn't * exist, then set a trace on the variable to monitor future * changes to its value. */ value = Tcl_GetVar(interp, butPtr->selVarName, TCL_GLOBAL_ONLY); butPtr->flags &= ~SELECTED; if (value != NULL) { if (strcmp(value, butPtr->onValue) == 0) { butPtr->flags |= SELECTED; } } else { if (Tcl_SetVar(interp, butPtr->selVarName, (butPtr->type == TYPE_CHECK_BUTTON) ? butPtr->offValue : "", TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } } Tcl_TraceVar(interp, butPtr->selVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, (ClientData) butPtr); } /* * Get the images for the widget, if there are any. Allocate the * new images before freeing the old ones, so that the reference * counts don't go to zero and cause image data to be discarded. */ if (butPtr->imageString != NULL) { image = Tk_GetImage(butPtr->interp, butPtr->tkwin, butPtr->imageString, ButtonImageProc, (ClientData) butPtr); if (image == NULL) { return TCL_ERROR; } } else { image = NULL; } if (butPtr->image != NULL) { Tk_FreeImage(butPtr->image); } butPtr->image = image; if (butPtr->selectImageString != NULL) { image = Tk_GetImage(butPtr->interp, butPtr->tkwin, butPtr->selectImageString, ButtonSelectImageProc, (ClientData) butPtr); if (image == NULL) { return TCL_ERROR; } } else { image = NULL; } if (butPtr->selectImage != NULL) { Tk_FreeImage(butPtr->selectImage); } butPtr->selectImage = image; if ((butPtr->image == NULL) && (butPtr->bitmap == None) && (butPtr->textVarName != NULL)) { /* * The button must display the value of a variable: set up a trace * on the variable's value, create the variable if it doesn't * exist, and fetch its current value. */ char *value; value = Tcl_GetVar(interp, butPtr->textVarName, TCL_GLOBAL_ONLY); if (value == NULL) { if (Tcl_SetVar(interp, butPtr->textVarName, butPtr->text, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } } else { if (butPtr->text != NULL) { ckfree(butPtr->text); } butPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1)); strcpy(butPtr->text, value); } Tcl_TraceVar(interp, butPtr->textVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, (ClientData) butPtr); } if ((butPtr->bitmap != None) || (butPtr->image != NULL)) { if (Tk_GetPixels(interp, butPtr->tkwin, butPtr->widthString, &butPtr->width) != TCL_OK) { widthError: Tcl_AddErrorInfo(interp, "\n (processing -width option)"); return TCL_ERROR; } if (Tk_GetPixels(interp, butPtr->tkwin, butPtr->heightString, &butPtr->height) != TCL_OK) { heightError: Tcl_AddErrorInfo(interp, "\n (processing -height option)"); return TCL_ERROR; } } else { if (Tcl_GetInt(interp, butPtr->widthString, &butPtr->width) != TCL_OK) { goto widthError; } if (Tcl_GetInt(interp, butPtr->heightString, &butPtr->height) != TCL_OK) { goto heightError; } } TkButtonWorldChanged((ClientData) butPtr); return TCL_OK;}/* *--------------------------------------------------------------------------- * * TkButtonWorldChanged -- * * This procedure is called when the world has changed in some * way and the widget needs to recompute all its graphics contexts * and determine its new geometry. * * Results: * None. * * Side effects: * Button will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ voidTkButtonWorldChanged(instanceData) ClientData instanceData; /* Information about widget. */{ XGCValues gcValues; GC newGC; unsigned long mask; TkButton *butPtr; butPtr = (TkButton *) instanceData;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -