📄 tkgrid.c
字号:
slavePtr = slavePtr->nextPtr) { int x, y; /* top left coordinate */ int width, height; /* slot or slave size */ int col = slavePtr->column; int row = slavePtr->row; x = (col>0) ? slotPtr->columnPtr[col-1].offset : 0; y = (row>0) ? slotPtr->rowPtr[row-1].offset : 0; width = slotPtr->columnPtr[slavePtr->numCols+col-1].offset - x; height = slotPtr->rowPtr[slavePtr->numRows+row-1].offset - y; x += slotPtr->startX; y += slotPtr->startY; AdjustForSticky(slavePtr, &x, &y, &width, &height); /* * Now put the window in the proper spot. (This was taken directly * from tkPack.c.) If the slave is a child of the master, then * do this here. Otherwise let Tk_MaintainGeometry do the work. */ if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { if ((width <= 0) || (height <= 0)) { Tk_UnmapWindow(slavePtr->tkwin); } else { if ((x != Tk_X(slavePtr->tkwin)) || (y != Tk_Y(slavePtr->tkwin)) || (width != Tk_Width(slavePtr->tkwin)) || (height != Tk_Height(slavePtr->tkwin))) { Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height); } if (abort) { break; } /* * Don't map the slave if the master isn't mapped: wait * until the master gets mapped later. */ if (Tk_IsMapped(masterPtr->tkwin)) { Tk_MapWindow(slavePtr->tkwin); } } } else { if ((width <= 0) || (height <= 0)) { Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin); Tk_UnmapWindow(slavePtr->tkwin); } else { Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, x, y, width, height); } } } masterPtr->abortPtr = NULL; Tcl_Release((ClientData) masterPtr);}/* *-------------------------------------------------------------- * * ResolveConstraints -- * * Resolve all of the column and row boundaries. Most of * the calculations are identical for rows and columns, so this procedure * is called twice, once for rows, and again for columns. * * Results: * The offset (in pixels) from the left/top edge of this layout is * returned. * * Side effects: * The slot offsets are copied into the SlotInfo structure for the * geometry master. * *-------------------------------------------------------------- */static intResolveConstraints(masterPtr, slotType, maxOffset) Gridder *masterPtr; /* The geometry master for this grid. */ int slotType; /* Either ROW or COLUMN. */ int maxOffset; /* The actual maximum size of this layout * in pixels, or 0 (not currently used). */{ register SlotInfo *slotPtr; /* Pointer to row/col constraints. */ register Gridder *slavePtr; /* List of slave windows in this grid. */ int constraintCount; /* Count of rows or columns that have * constraints. */ int slotCount; /* Last occupied row or column. */ int gridCount; /* The larger of slotCount and constraintCount. */ GridLayout *layoutPtr; /* Temporary layout structure. */ int requiredSize; /* The natural size of the grid (pixels). * This is the minimum size needed to * accomodate all of the slaves at their * requested sizes. */ int offset; /* The pixel offset of the right edge of the * current slot from the beginning of the * layout. */ int slot; /* The current slot. */ int start; /* The first slot of a contiguous set whose * constraints are not yet fully resolved. */ int end; /* The Last slot of a contiguous set whose * constraints are not yet fully resolved. */ /* * For typical sized tables, we'll use stack space for the layout data * to avoid the overhead of a malloc and free for every layout. */ GridLayout layoutData[TYPICAL_SIZE + 1]; if (slotType == COLUMN) { constraintCount = masterPtr->masterDataPtr->columnMax; slotCount = masterPtr->masterDataPtr->columnEnd; slotPtr = masterPtr->masterDataPtr->columnPtr; } else { constraintCount = masterPtr->masterDataPtr->rowMax; slotCount = masterPtr->masterDataPtr->rowEnd; slotPtr = masterPtr->masterDataPtr->rowPtr; } /* * Make sure there is enough memory for the layout. */ gridCount = MAX(constraintCount,slotCount); if (gridCount >= TYPICAL_SIZE) { layoutPtr = (GridLayout *) Tcl_Alloc(sizeof(GridLayout) * (1+gridCount)); } else { layoutPtr = layoutData; } /* * Allocate an extra layout slot to represent the left/top edge of * the 0th slot to make it easier to calculate slot widths from * offsets without special case code. * Initialize the "dummy" slot to the left/top of the table. * This slot avoids special casing the first slot. */ layoutPtr->minOffset = 0; layoutPtr->maxOffset = 0; layoutPtr++; /* * Step 1. * Copy the slot constraints into the layout structure, * and initialize the rest of the fields. */ for (slot=0; slot < constraintCount; slot++) { layoutPtr[slot].minSize = slotPtr[slot].minSize; layoutPtr[slot].weight = slotPtr[slot].weight; layoutPtr[slot].pad = slotPtr[slot].pad; layoutPtr[slot].binNextPtr = NULL; } for(;slot<gridCount;slot++) { layoutPtr[slot].minSize = 0; layoutPtr[slot].weight = 0; layoutPtr[slot].pad = 0; layoutPtr[slot].binNextPtr = NULL; } /* * Step 2. * Slaves with a span of 1 are used to determine the minimum size of * each slot. Slaves whose span is two or more slots don't * contribute to the minimum size of each slot directly, but can cause * slots to grow if their size exceeds the the sizes of the slots they * span. * * Bin all slaves whose spans are > 1 by their right edges. This * allows the computation on minimum and maximum possible layout * sizes at each slot boundary, without the need to re-sort the slaves. */ switch (slotType) { case COLUMN: for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; slavePtr = slavePtr->nextPtr) { int rightEdge = slavePtr->column + slavePtr->numCols - 1; slavePtr->size = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->padX + slavePtr->iPadX + slavePtr->doubleBw; if (slavePtr->numCols > 1) { slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; layoutPtr[rightEdge].binNextPtr = slavePtr; } else { int size = slavePtr->size + layoutPtr[rightEdge].pad; if (size > layoutPtr[rightEdge].minSize) { layoutPtr[rightEdge].minSize = size; } } } break; case ROW: for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; slavePtr = slavePtr->nextPtr) { int rightEdge = slavePtr->row + slavePtr->numRows - 1; slavePtr->size = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->padY + slavePtr->iPadY + slavePtr->doubleBw; if (slavePtr->numRows > 1) { slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; layoutPtr[rightEdge].binNextPtr = slavePtr; } else { int size = slavePtr->size + layoutPtr[rightEdge].pad; if (size > layoutPtr[rightEdge].minSize) { layoutPtr[rightEdge].minSize = size; } } } break; } /* * Step 3. * Determine the minimum slot offsets going from left to right * that would fit all of the slaves. This determines the minimum */ for (offset=slot=0; slot < gridCount; slot++) { layoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset; for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; slavePtr = slavePtr->binNextPtr) { int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; int required = slavePtr->size + layoutPtr[slot - span].minOffset; if (required > layoutPtr[slot].minOffset) { layoutPtr[slot].minOffset = required; } } offset = layoutPtr[slot].minOffset; } /* * At this point, we know the minimum required size of the entire layout. * It might be prudent to stop here if our "master" will resize itself * to this size. */ requiredSize = offset; if (maxOffset > offset) { offset=maxOffset; } /* * Step 4. * Determine the minimum slot offsets going from right to left, * bounding the pixel range of each slot boundary. * Pre-fill all of the right offsets with the actual size of the table; * they will be reduced as required. */ for (slot=0; slot < gridCount; slot++) { layoutPtr[slot].maxOffset = offset; } for (slot=gridCount-1; slot > 0;) { for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; slavePtr = slavePtr->binNextPtr) { int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; int require = offset - slavePtr->size; int startSlot = slot - span; if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) { layoutPtr[startSlot].maxOffset = require; } } offset -= layoutPtr[slot].minSize; slot--; if (layoutPtr[slot].maxOffset < offset) { offset = layoutPtr[slot].maxOffset; } else { layoutPtr[slot].maxOffset = offset; } } /* * Step 5. * At this point, each slot boundary has a range of values that * will satisfy the overall layout size. * Make repeated passes over the layout structure looking for * spans of slot boundaries where the minOffsets are less than * the maxOffsets, and adjust the offsets according to the slot * weights. At each pass, at least one slot boundary will have * its range of possible values fixed at a single value. */ for (start=0; start < gridCount;) { int totalWeight = 0; /* Sum of the weights for all of the * slots in this span. */ int need = 0; /* The minimum space needed to layout * this span. */ int have; /* The actual amount of space that will * be taken up by this span. */ int weight; /* Cumulative weights of the columns in * this span. */ int noWeights = 0; /* True if the span has no weights. */ /* * Find a span by identifying ranges of slots whose edges are * already constrained at fixed offsets, but whose internal * slot boundaries have a range of possible positions. */ if (layoutPtr[start].minOffset == layoutPtr[start].maxOffset) { start++; continue; } for (end=start+1; end<gridCount; end++) { if (layoutPtr[end].minOffset == layoutPtr[end].maxOffset) { break; } } /* * We found a span. Compute the total weight, minumum space required, * for this span, and the actual amount of space the span should * use. */ for (slot=start; slot<=end; slot++) { totalWeight += layoutPtr[slot].weight; need += layoutPtr[slot].minSize; } have = layoutPtr[end].maxOffset - layoutPtr[start-1].minOffset; /* * If all the weights in the span are zero, then distribute the * extra space evenly. */ if (totalWeight == 0) { noWeights++; totalWeight = end - start + 1; } /* * It might not be possible to give the span all of the space * available on this pass without violating the size constraints * of one or more of the internal slot boundaries. * Determine the maximum amount of space that when added to the * entire span, would cause a slot boundary to have its possible * range reduced to one value, and reduce the amount of extra * space allocated on this pass accordingly. * * The calculation is done cumulatively to avoid accumulating * roundoff errors. */ for (weight=0,slot=start; slot<end; slot++) { int diff = layoutPtr[slot].maxOffset - layoutPtr[slot].minOffset; weight += noWeights ? 1 : layoutPtr[slot].weight; if ((noWeights || layoutPtr[slot].weight>0) && (diff*totalWeight/weight) < (have-need)) { have = diff * totalWeight / weight + need; } } /* * Now distribute the extra space among the slots by * adjusting the minSizes and minOffsets. */ for (weight=0,slot=start; slot<end; slot++) { weight += noWeights ? 1 : layoutPtr[slot].weight; layoutPtr[slot].minOffset += (int)((double) (have-need) * weight/totalWeight + 0.5); layoutPtr[slot].minSize = layoutPtr[slot].minOffset - layoutPtr[slot-1].minOffset; } layoutPtr[slot].minSize = layoutPtr[slot].minOffset - layoutPtr[slot-1].minOffset; /* * Having pushed the top/left boundaries of the slots to * take up extra space, the bottom/right space is recalculated * to propagate the new space allocation. */ for (slot=end; slot > start; slot--) { layoutPtr[slot-1].maxOffset = layoutPtr[slot].maxOffset-layoutPtr[slot].minSize; } } /* * Step 6. * All of the space has been apportioned; copy the * layout information back into the master. */ for (slot=0; slot < gridCount; slot++) { slotPtr[slot].offset = layoutPtr[slot].minOffset; } --layoutPtr; if (layoutPtr != layoutData) { Tcl_Free((char *)layoutPtr); } return requiredSize;}/* *-------------------------------------------------------------- * * GetGrid -- * * This internal procedure is used to locate a Grid * structure for a given window, creating one if one * doesn't exist already. * * Results: * The return value is a pointer to the Grid structure * corresponding to tkwin. * * Side effects: * A new grid structure may be created. If so, then * a callback is set up to clean things up when the * window is deleted. * *-------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -