Пример #1
0
void widgetResizeImpl(widget *self, int w, int h)
{
	const size minSize = widgetGetMinSize(self);
	const size maxSize = widgetGetMaxSize(self);

	// Create an event
	eventResize evtResize;
	evtResize.event = widgetCreateEvent(EVT_RESIZE);

	// Save the current size in the event
	evtResize.oldSize = self->size;

	assert(minSize.x <= w);
	assert(minSize.y <= h);
	assert(w <= maxSize.x);
	assert(h <= maxSize.y);

	self->size.x = w;
	self->size.y = h;

	// Re-create the cairo context at this new size
	widgetCairoCreate(&self->cr, CAIRO_FORMAT_ARGB32, w, h);

	// If a mask is enabled; re-create it also
	if (self->maskEnabled)
	{
		widgetCairoCreate(&self->maskCr, CAIRO_FORMAT_A1, w, h);

		// Re-draw the mask (only done on resize)
		widgetDrawMask(self);
	}

	// If OpenGL is enabled disable and re-enable it
	if (self->openGLEnabled)
	{
		widgetDisableGL(self);
		widgetEnableGL(self);
	}

	// Set the needs redraw flag
	self->needsRedraw = true;

	// If we have any children, we need to redo their layout
	if (vectorSize(self->children))
	{
		widgetDoLayout(self);
	}

	// Fire any EVT_RESIZE callbacks
	widgetFireCallbacks(self, (event *) &evtResize);
}
Пример #2
0
bool tableDoLayoutImpl(widget *self)
{
	table *selfTable = TABLE(self);
	
	const int numChildren = vectorSize(self->children);
	
	const int numRows = tableGetRowCount(selfTable);
	const int numColumns = tableGetColumnCount(selfTable);
	
	int i;
	int dx, dy;
	
	int *minColumnWidth = alloca(sizeof(int) * numColumns);
	int *maxColumnWidth = alloca(sizeof(int) * numColumns);
	
	int *minRowHeight = alloca(sizeof(int) * numRows);
	int *maxRowHeight = alloca(sizeof(int) * numRows);
	
	// Syntatic sugar
	int *columnWidth = minColumnWidth;
	int *rowHeight = minRowHeight;
	
	// Get the minimum and maximum cell sizes
	tableGetMinimumCellSizes(selfTable, minRowHeight, minColumnWidth);
	tableGetMaximumCellSizes(selfTable, maxRowHeight, maxColumnWidth);
	
	// Calculate how much space we have left to fill
	dx = self->size.x - tablePartialSum(minColumnWidth, 0, numColumns);
	dy = self->size.y - tablePartialSum(minRowHeight, 0, numRows);
	
	// Increase the column size until we run out of space
	for (i = 0; dx; i = (i + 1) % numColumns)
	{
		// If the column is not maxed out, increases its size by one
		if (columnWidth[i] < maxColumnWidth[i])
		{
			columnWidth[i]++;
			dx--;
		}
	}
	
	// Increase the row size until we run out of space
	for (i = 0; dy; i = (i + 1) % numRows)
	{
		// If the row is not maxed out, increase its size by one
		if (rowHeight[i] < minRowHeight[i])
		{
			rowHeight[i]++;
			dy--;
		}
	}
	
	// Now we need to position the children, taking padding into account
	for (i = 0; i < numChildren; i++)
	{
		// Get the child and its position info
		widget *child = vectorAt(self->children, i);
		const childPositionInfo *pos = vectorAt(selfTable->childPositions, i);
		size maxChildSize = widgetGetMaxSize(child);
		
		// left is the sum of all of the preceding columns
		int left = tablePartialSum(columnWidth, 0, pos->column);
		
		// top is the sum of all of the preceding rows
		int top = tablePartialSum(rowHeight, 0, pos->row);
		
		// cellWidth is the sum of the columns we span
		int cellWidth = tablePartialSum(columnWidth, pos->column - 1, pos->colspan);
		
		// cellHeight is the sum of the rows we span
		int cellHeight = tablePartialSum(rowHeight, pos->row - 1, pos->rowspan);
		
		// Final width and height of the child
		int w, h;
		
		// Final x,y offsets of the child
		int x, y;
		
		// If we are not the last row/column, subtract the row/column padding
		if (pos->column + pos->colspan - 1 != numColumns)
		{
			cellWidth -= selfTable->columnPadding;
		}
		if (pos->row + pos->rowspan - 1 != numRows)
		{
			cellHeight -= selfTable->rowPadding;
		}
		
		// Compute the final width and height of the child
		w = MIN(cellWidth, maxChildSize.x);
		h = MIN(cellHeight, maxChildSize.y);
		
		// Pad out any remaining space
		switch (pos->hAlignment)
		{
			case LEFT:
				x = left;
				break;
			case CENTRE:
				x = left + (cellWidth - w) / 2;
				break;
			case RIGHT:
				x = left + cellWidth - w;
				break;
		}
		
		switch (pos->vAlignment)
		{
			case TOP:
				y = top;
				break;
			case MIDDLE:
				y = top + (cellHeight - h) / 2;
				break;
			case BOTTOM:
				y = top + cellHeight - h;
				break;
		}
		
		// Resize and reposition the widget
		widgetResize(child, w, h);
		widgetReposition(child, x, y);
	}
	
	return true;
}
Пример #3
0
/**
 * Computes the maximum row/column size for each row/column in the table. It is
 * important to note that the widths/heights are inclusive of padding. Therefore
 * all but the rightmost column and bottom row will have either self->rowPadding
 * or self->columnPadding added onto their sizes.
 *
 * @param self  The table to get the minimum cell sizes of.
 * @param maxRowHeight  The array to place the maximum row heights for the table
 *                      into; assumed to be tableGetRowCount(self) in size.
 * @param maxColumnWidth    The array to place the maximum column widths for the
 *                          table into; assumed to be tableGetColumnCount(self)
 *                          in size.
 */
static void tableGetMaximumCellSizes(const table *self, int *maxRowHeight,
                                     int *maxColumnWidth)
{
	int i;
	int spanningIndex;
	
	const int numChildren = vectorSize(WIDGET(self)->children);
	const int numRows = tableGetRowCount(self);
	const int numColumns = tableGetColumnCount(self);
	
	size *maxChildSize = alloca(sizeof(size) * numChildren);
	
	// Zero the min row/column sizes
	memset(maxRowHeight, '\0', sizeof(int) * numRows);
	memset(maxColumnWidth, '\0', sizeof(int) * numColumns);
	
	// Get the maximum row/column sizes for single-spanning cells
	for (i = 0; i < numChildren; i++)
	{
		const childPositionInfo *pos = vectorAt(self->childPositions, i);
		const int row = pos->row - 1;
		const int col  = pos->column - 1;
		
		// Get the maximum size of the cell
		maxChildSize[i] = widgetGetMaxSize(vectorAt(WIDGET(self)->children, i));
		
		// If the row has a rowspan of 1; see if it is the highest thus far
		if (pos->rowspan == 1)
		{
			maxRowHeight[row] = MAX(maxRowHeight[row], maxChildSize[i].y);
		}
		
		// If the column has a colspan of 1; see if it is the widest thus far
		if (pos->colspan == 1)
		{
			maxColumnWidth[col] = MAX(maxColumnWidth[col], maxChildSize[i].x);
		}
	}
	
	// Handle spanning rows
	while ((spanningIndex = tableGetMostOversizedRow(self,
	                                                 maxRowHeight,
	                                                 maxChildSize)) != -1)
	{
		int i;
		const childPositionInfo *pos = vectorAt(self->childPositions, spanningIndex);
		
		// Calculate how much larger we need to make the spanned rows
		int delta = maxChildSize[spanningIndex].y - tablePartialSum(maxRowHeight,
																	pos->row - 1,
																	pos->rowspan);
		
		// Loop over the rows spanned increasing their height by 1
		for (i = pos->row; delta; i = pos->row + (i + 1) % pos->rowspan, delta--)
		{
			maxRowHeight[i]++;
		}
	}
	
	// Handle spanning columns
	while ((spanningIndex = tableGetMostOversizedColumn(self,
	                                                    maxColumnWidth,
	                                                    maxChildSize)) != -1)
	{
		int i;
		const childPositionInfo *pos = vectorAt(self->childPositions, spanningIndex);
		
		// Calculate how much larger we need to make the spanned columns
		int delta = maxChildSize[spanningIndex].x - tablePartialSum(maxColumnWidth, 
		                                                            pos->column - 1,
		                                                            pos->colspan);
		
		for (i = pos->column; delta; i = pos->column + (i + 1) % pos->colspan, delta--)
		{
			maxColumnWidth[i]++;
		}
	}
}