Beispiel #1
0
static void createGUI(lua_State *L)
{
	window *w = malloc(sizeof(window));
	windowInit(w, "main", 300, 400);
	widgetReposition(WIDGET(w), 50, 50);
	widgetShow(WIDGET(w));

	// GL stuff
	widgetEnableGL(WIDGET(w));
	WIDGET(w)->vtbl->doDraw = paintWithGL;
	widgetAddTimerEventHandler(WIDGET(w), EVT_TIMER_SINGLE_SHOT, 3000,
	                           timer, NULL, NULL);
}
Beispiel #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;
}
Beispiel #3
0
static bool widgetAnimationTimerCallback(widget *self, const event *evt,
                                         int handlerId, void *userData)
{
	int i;
	vector *frames = userData;
	animationFrame *currFrame;

	// Regular timer event
	if (evt->type == EVT_TIMER_PERSISTENT)
	{
		bool didInterpolate = false;

		// Currently active keyframes to be interpolated between
		struct
		{
			animationFrame *pre;
			animationFrame *post;
		} interpolateFrames[ANI_TYPE_COUNT] = { { NULL, NULL } };

		// Work out what frames we need to interpolate between
		for (i = 0; i < vectorSize(frames); i++)
		{
			currFrame = vectorAt(frames, i);

			/*
			 * We are only interested in the key frames which either directly
			 * precede now or come directly after. (As it is these frames which
			 * will be interpolated between.)
			 */
			if (currFrame->time <= evt->time)
			{
				interpolateFrames[currFrame->type].pre = currFrame;
			}
			else if (currFrame->time > evt->time
					 && !interpolateFrames[currFrame->type].post)
			{
				interpolateFrames[currFrame->type].post = currFrame;
			}
		}

		// Do the interpolation
		for (i = 0; i < ANI_TYPE_COUNT; i++)
		{
			// If there are frames to interpolate between then do so
			if (interpolateFrames[i].pre && interpolateFrames[i].post)
			{
				// Get the points to interpolate between
				animationFrame k1 = *interpolateFrames[i].pre;
				animationFrame k2 = *interpolateFrames[i].post;

				int time = evt->time;

				switch (i)
				{
					case ANI_TYPE_TRANSLATE:
					{
						// Get the new position
						point pos = widgetAnimationInterpolateTranslate(self, k1,
						                                                k2, time);

						// Set the new position
						widgetReposition(self, pos.x, pos.y);

						break;
					}
					case ANI_TYPE_ROTATE:
						// Update the widgets rotation
						self->rotate = widgetAnimationInterpolateRotate(self, k1,
						                                                k2, time);
						break;
					case ANI_TYPE_SCALE:
						// Update the widgets scale factor
						self->scale = widgetAnimationInterpolateScale(self, k1,
						                                              k2, time);
						break;
					case ANI_TYPE_ALPHA:
						// Update the widgets alpha
						self->alpha = widgetAnimationInterpolateAlpha(self, k1,
						                                              k2, time);
						break;
				}

				// Make a note that we did interpolate
				didInterpolate = true;
			}
		}

		// If there was no interpolation then the animation is over
		if (!didInterpolate)
		{
			// Remove ourself (the event handler)
			widgetRemoveEventHandler(self, handlerId);
		}
	}
	else if (evt->type == EVT_DESTRUCT)
	{
		animationFrame *lastFrame[ANI_TYPE_COUNT] = { NULL };

		// Find the last frame of each animation type
		for (i = 0; i < vectorSize(frames); i++)
		{
			currFrame = vectorAt(frames, i);

			lastFrame[currFrame->type] = currFrame;
		}

		// Set the position/rotation/scale/alpha to that of the final frame
		for (i = 0; i < ANI_TYPE_COUNT; i++)
		{
			if (lastFrame[i]) switch (i)
			{
				case ANI_TYPE_TRANSLATE:
					self->offset = lastFrame[ANI_TYPE_TRANSLATE]->data.translate;
					break;
				case ANI_TYPE_ROTATE:
					self->rotate = lastFrame[ANI_TYPE_ROTATE]->data.rotate;
					break;
				case ANI_TYPE_SCALE:
					self->scale = lastFrame[ANI_TYPE_SCALE]->data.scale;
					break;
				case ANI_TYPE_ALPHA:
					self->alpha = lastFrame[ANI_TYPE_ALPHA]->data.alpha;
					break;
				default:
					break;
			}
		}

		// Free the frames vector
		vectorMapAndDestroy(frames, free);
	}


	return true;
}