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.