First, let's factor out a Populate function. This is to be used when the entire contents of container needs to be replaced. In an application this might happen when selecting a different object, or loading a new file. Imagine a video editor, with a timeline of with video and photo clips, and an inspector panel with controls for changing the properties of the selected clip. When you select a clip, the inspector's contents needs to be replaced with the relevant controls for that clip.

We make container a global variable.

Element *container;

And in main(), we only need to create the container before calling Populate().

int main() {
	count = 5;

	// ... create the window

	container = &PanelCreate(&panel->e, ELEMENT_H_FILL | ELEMENT_V_FILL)->e;
	Populate();
	return MessageLoop();
}

Then in Populate, we start by destroying all the children it contains. Then, we add the new UI, and ask the container to relayout.

void Populate() {
	// Destroy the children of the container.
	for (uintptr_t i = 0; i < container->childCount; i++) {
		ElementDestroy(container->children[i]);
	}

	// The UI creation code from the previous article.
	{
		row = PanelCreate(container, PANEL_HORIZONTAL | ELEMENT_H_FILL);

		buttonDecrement = ButtonCreate(&row->e, 0, "-", -1);
		buttonDecrement->e.messageUser = ButtonDecrementMessage;

		char buffer[64];
		snprintf(buffer, sizeof(buffer), "Count: %d", count);
		labelCount = LabelCreate(&row->e, ELEMENT_H_FILL | LABEL_CENTER, buffer, -1);

		buttonIncrement = ButtonCreate(&row->e, 0, "+", -1);
		buttonIncrement->e.messageUser = ButtonIncrementMessage;
	}

	// Layout the container's new children.
	ElementMessage(container, MSG_LAYOUT, 0, 0);
	ElementRepaint(container, NULL);
}

The result of the code is the same as before, but we've made the code a bit easier to work with going forward.

part15.c

Part 14: Changing state manually.

Part 16: Preparing to rewrite.