In this article, we're going to take a step back, and remove all the interactivity code we implemented in the previous articles. This will be in preparation for rearchitecting the application. I will repeat again that I don't think this application actually needs rearchitecting, given how simple it is, but I want to use it to demonstrate how you might want to architecture an application that isn't so simple.

We start by reducing the global variables to just the container element and the count.

Element *container;
int count;

We also remove the button message handlers, ButtonIncrementMessage and ButtonDecrementMessage. Instead, we write a single ButtonDisabledMessage handler which we will give to any button that needs to be grayed out. All it does it respond to the MSG_BUTTON_GET_COLOR message.

int ButtonDisabledMessage(Element *element, Message message, int di, void *dp) {
	if (message == MSG_BUTTON_GET_COLOR) {
		*(uint32_t *) dp = 0xCCCCCC; 
	}

	return 0;
}

In Populate, the UI creation code now becomes:

Button *buttonDecrement = ButtonCreate(&row->e, 0, "-", -1);
if (count == 0) buttonDecrement->e.messageUser = ButtonDisabledMessage;

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

Button *buttonIncrement = ButtonCreate(&row->e, 0, "+", -1);
if (count == 10) buttonIncrement->e.messageUser = ButtonDisabledMessage;

The end result is the same as in the previous article, except the buttons now don't do anything.

Alright, alright, enough stalling. In the next article, we're going to start implementing the systems we need to 'upgrade' our application.

part16.c

Part 15: Refactoring out population.

Part 17: The document-object model.