So, I am a systems programmer working on a UI (bad idea, maybe, but I think I do ok all things considered). Anyway, my program is an interface to a service running on a remote machine which controls a piece of hardware. The basic model is:
- Send command from the UI.
- Get ACK from remote service, enter busy state.
- Remote service processes request and sends OK or ERROR.
- UI receives response and leaves busy state.
When the UI enters a busy state all controls are disabled (well, all but one, I'll explain that shortly as it is part of the problem). One aspect of the system is to assign arbitrary data to an object (data is a string, object is irrelevant for the purposes of this question). In order to make this process robust and simple, the data will be committed to the remote server when the user presses Enter within the text area or focus leaves the text area.
This however causes a bit of a problem. One button in the UI is always in one of two states; "start" or "stop". When the system is in a busy state this button turns into a stop button and is the only enabled control in the UI. This is necessary in order to cancel long running operations.
However, imagine the following scenario:
- User types into text area in order to assign data to an object but does not press enter to commit.
- User presses the "start" button.
- Because the text area has now lost focus the data is committed. This causes the system to go into a busy state.
- After the data is sent and we are in a busy state the click handler for the start/stop button is invoked. However, the button is now in a stop state because we sent the data when the text area lost focus and we have not yet received an OK response.
If the user clicks start again everything is ok because the UI will not commit duplicate data, only committing when it has changed. However, this is a bug and I need to fix it.
I don't want to get rid of the commit on lost focus because it ensures that, even if the user does not press enter, the data on screen will always be committed and valid. Does anyone else have any ideas here? Is there perhaps a better way of going about this? I can think of some convoluted workarounds, but they are all ugly and really break the encapsulation between various parts of the UI.
So, if anyone else has a simpler, better solution I would love to hear it.