📄 tklistbox.c
字号:
break; case TK_SCROLL_UNITS: offset = listPtr->xOffset + count*listPtr->xScrollUnit; break; } ChangeListboxOffset(listPtr, offset); } } else if ((c == 'y') && (strncmp(argv[1], "yview", length) == 0)) { int index, count, type; double fraction, fraction2; if (argc == 2) { if (listPtr->numElements == 0) { interp->result = "0 1"; } else { fraction = listPtr->topIndex/((double) listPtr->numElements); fraction2 = (listPtr->topIndex+listPtr->fullLines) /((double) listPtr->numElements); if (fraction2 > 1.0) { fraction2 = 1.0; } sprintf(interp->result, "%g %g", fraction, fraction2); } } else if (argc == 3) { if (GetListboxIndex(interp, listPtr, argv[2], 0, &index) != TCL_OK) { goto error; } ChangeListboxView(listPtr, index); } else { type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: goto error; case TK_SCROLL_MOVETO: index = (int) (listPtr->numElements*fraction + 0.5); break; case TK_SCROLL_PAGES: if (listPtr->fullLines > 2) { index = listPtr->topIndex + count*(listPtr->fullLines-2); } else { index = listPtr->topIndex + count; } break; case TK_SCROLL_UNITS: index = listPtr->topIndex + count; break; } ChangeListboxView(listPtr, index); } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be activate, bbox, cget, configure, ", "curselection, delete, get, index, insert, nearest, ", "scan, see, selection, size, ", "xview, or yview", (char *) NULL); goto error; } done: Tcl_Release((ClientData) listPtr); return result; error: Tcl_Release((ClientData) listPtr); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * DestroyListbox -- * * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release * to clean up the internal structure of a listbox at a safe time * (when no-one is using it anymore). * * Results: * None. * * Side effects: * Everything associated with the listbox is freed up. * *---------------------------------------------------------------------- */static voidDestroyListbox(memPtr) char *memPtr; /* Info about listbox widget. */{ register Listbox *listPtr = (Listbox *) memPtr; register Element *elPtr, *nextPtr; /* * Free up all of the list elements. */ for (elPtr = listPtr->firstPtr; elPtr != NULL; ) { nextPtr = elPtr->nextPtr; ckfree((char *) elPtr); elPtr = nextPtr; } /* * Free up all the stuff that requires special handling, then * let Tk_FreeOptions handle all the standard option-related * stuff. */ if (listPtr->textGC != None) { Tk_FreeGC(listPtr->display, listPtr->textGC); } if (listPtr->selTextGC != None) { Tk_FreeGC(listPtr->display, listPtr->selTextGC); } Tk_FreeOptions(configSpecs, (char *) listPtr, listPtr->display, 0); ckfree((char *) listPtr);}/* *---------------------------------------------------------------------- * * ConfigureListbox -- * * This procedure is called to process an argv/argc list, plus * the Tk option database, in order to configure (or reconfigure) * a listbox 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 colors, border width, * etc. get set for listPtr; old resources get freed, * if there were any. * *---------------------------------------------------------------------- */static intConfigureListbox(interp, listPtr, argc, argv, flags) Tcl_Interp *interp; /* Used for error reporting. */ register Listbox *listPtr; /* 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. */{ int oldExport; oldExport = listPtr->exportSelection; if (Tk_ConfigureWidget(interp, listPtr->tkwin, configSpecs, argc, argv, (char *) listPtr, flags) != TCL_OK) { return TCL_ERROR; } /* * A few options need special processing, such as setting the * background from a 3-D border. */ Tk_SetBackgroundFromBorder(listPtr->tkwin, listPtr->normalBorder); if (listPtr->highlightWidth < 0) { listPtr->highlightWidth = 0; } listPtr->inset = listPtr->highlightWidth + listPtr->borderWidth; /* * Claim the selection if we've suddenly started exporting it and * there is a selection to export. */ if (listPtr->exportSelection && !oldExport && (listPtr->numSelected != 0)) { Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY, ListboxLostSelection, (ClientData) listPtr); } ListboxWorldChanged((ClientData) listPtr); return TCL_OK;}/* *--------------------------------------------------------------------------- * * ListboxWorldChanged -- * * 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: * Listbox will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ static voidListboxWorldChanged(instanceData) ClientData instanceData; /* Information about widget. */{ XGCValues gcValues; GC gc; unsigned long mask; Listbox *listPtr; listPtr = (Listbox *) instanceData; gcValues.foreground = listPtr->fgColorPtr->pixel; gcValues.font = Tk_FontId(listPtr->tkfont); gcValues.graphics_exposures = False; mask = GCForeground | GCFont | GCGraphicsExposures; gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues); if (listPtr->textGC != None) { Tk_FreeGC(listPtr->display, listPtr->textGC); } listPtr->textGC = gc; gcValues.foreground = listPtr->selFgColorPtr->pixel; gcValues.font = Tk_FontId(listPtr->tkfont); mask = GCForeground | GCFont; gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues); if (listPtr->selTextGC != None) { Tk_FreeGC(listPtr->display, listPtr->selTextGC); } listPtr->selTextGC = gc; /* * Register the desired geometry for the window and arrange for * the window to be redisplayed. */ ListboxComputeGeometry(listPtr, 1, 1, 1); listPtr->flags |= UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR; ListboxRedrawRange(listPtr, 0, listPtr->numElements-1);}/* *-------------------------------------------------------------- * * DisplayListbox -- * * This procedure redraws the contents of a listbox window. * * Results: * None. * * Side effects: * Information appears on the screen. * *-------------------------------------------------------------- */static voidDisplayListbox(clientData) ClientData clientData; /* Information about window. */{ register Listbox *listPtr = (Listbox *) clientData; register Tk_Window tkwin = listPtr->tkwin; register Element *elPtr; GC gc; int i, limit, x, y, width, prevSelected; Tk_FontMetrics fm; int left, right; /* Non-zero values here indicate * that the left or right edge of * the listbox is off-screen. */ Pixmap pixmap; listPtr->flags &= ~REDRAW_PENDING; if (listPtr->flags & UPDATE_V_SCROLLBAR) { ListboxUpdateVScrollbar(listPtr); } if (listPtr->flags & UPDATE_H_SCROLLBAR) { ListboxUpdateHScrollbar(listPtr); } listPtr->flags &= ~(REDRAW_PENDING|UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR); if ((listPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } /* * Redrawing is done in a temporary pixmap that is allocated * here and freed at the end of the procedure. All drawing is * done to the pixmap, and the pixmap is copied to the screen * at the end of the procedure. This provides the smoothest * possible visual effects (no flashing on the screen). */ pixmap = Tk_GetPixmap(listPtr->display, Tk_WindowId(tkwin), Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); Tk_Fill3DRectangle(tkwin, pixmap, listPtr->normalBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); /* * Iterate through all of the elements of the listbox, displaying each * in turn. Selected elements use a different GC and have a raised * background. */ limit = listPtr->topIndex + listPtr->fullLines + listPtr->partialLine - 1; if (limit >= listPtr->numElements) { limit = listPtr->numElements-1; } left = right = 0; if (listPtr->xOffset > 0) { left = listPtr->selBorderWidth+1; } if ((listPtr->maxWidth - listPtr->xOffset) > (Tk_Width(listPtr->tkwin) - 2*(listPtr->inset + listPtr->selBorderWidth))) { right = listPtr->selBorderWidth+1; } prevSelected = 0; for (elPtr = listPtr->firstPtr, i = 0; (elPtr != NULL) && (i <= limit); prevSelected = elPtr->selected, elPtr = elPtr->nextPtr, i++) { if (i < listPtr->topIndex) { continue; } x = listPtr->inset; y = ((i - listPtr->topIndex) * listPtr->lineHeight) + listPtr->inset; gc = listPtr->textGC; if (elPtr->selected) { gc = listPtr->selTextGC; width = Tk_Width(tkwin) - 2*listPtr->inset; Tk_Fill3DRectangle(tkwin, pixmap, listPtr->selBorder, x, y, width, listPtr->lineHeight, 0, TK_RELIEF_FLAT); /* * Draw beveled edges around the selection, if there are visible * edges next to this element. Special considerations: * 1. The left and right bevels may not be visible if horizontal * scrolling is enabled (the "left" and "right" variables * are zero to indicate that the corresponding bevel is * visible). * 2. Top and bottom bevels are only drawn if this is the * first or last seleted item. * 3. If the left or right bevel isn't visible, then the "left" * and "right" variables, computed above, have non-zero values * that extend the top and bottom bevels so that the mitered * corners are off-screen. */ if (left == 0) { Tk_3DVerticalBevel(tkwin, pixmap, listPtr->selBorder, x, y, listPtr->selBorderWidth, listPtr->lineHeight, 1, TK_RELIEF_RAISED); } if (right == 0) { Tk_3DVerticalBevel(tkwin, pixmap, listPtr->selBorder, x + width - listPtr->selBorderWidth, y, listPtr->selBorderWidth, listPtr->lineHeight, 0, TK_RELIEF_RAISED); } if (!prevSelected) { Tk_3DHorizontalBevel(tkwin, pixmap, listPtr->selBorder, x-left, y, width+left+right, listPtr->selBorderWidth, 1, 1, 1, TK_RELIEF_RAISED); } if ((elPtr->nextPtr == NULL) || !elPtr->nextPtr->selected) { Tk_3DHorizontalBevel(tkwin, pixmap, listPtr->selBorder, x-left, y + listPtr->lineHeight - listPtr->selBorderWidth, width+left+right, listPtr->selBorderWidth, 0, 0, 0, TK_RELIEF_RAISED); } } Tk_GetFontMetrics(listPtr->tkfont, &fm); y += fm.ascent + listPtr->selBorderWidth; x = listPtr->inset + listPtr->selBorderWidth - elPtr->lBearing - listPtr->xOffset; Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont, elPtr->text, elPtr->textLength, x, y); /* * If this is the active element, underline it. */ if ((i == listPtr->active) && (listPtr->flags & GOT_FOCUS)) { Tk_UnderlineChars(listPtr->display, pixmap, gc, listPtr->tkfont, elPtr->text, x, y, 0, elPtr->textLength); } } /* * Redraw the border for the listbox to make sure that it's on top * of any of the text of the listbox entries. */ Tk_Draw3DRectangle(tkwin, pixmap, listPtr->normalBorder, listPtr->highlightWidth, listPtr->highlightWidth, Tk_Width(tkwin) - 2*listPtr->highlightWidth, Tk_Height(tkwin) - 2*listPtr->highlightWidth, listPtr->borderWidth, listPtr->relief); if (listPtr->highlightWidth > 0) { GC gc; if (listPtr->flags & GOT_FOCUS) { gc = Tk_GCForColor(listPtr->highlightColorPtr, pixmap); } else { gc = Tk_GCForColor(listPtr->highlightBgColorPtr, pixmap); } Tk_DrawFocusHighlight(tkwin, gc, listPtr->highlightWidth, pixmap); } XCopyArea(listPtr->display, pixmap, Tk_WindowId(tkwin), listPtr->textGC, 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0); Tk_FreePixmap(listPtr->display, pixmap);}/* *---------------------------------------------------------------------- * * ListboxComputeGeometry -- * * This procedure is invoked to recompute geometry information * such as the sizes of the elements and the overall dimensions * desired for the listbox. * * Results: * None. * * Side effects: * Geometry information is updated and a new requested size is * registered for the widget. Internal border and gridding * information is also set.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -