Jump to content

Partial redraw of widget


steved

Recommended Posts

I have a widget which has to be able to redraw just a fixed part of the area it occupies on the screen (it's displaying a changing value within various fixed information).

Is there an intended way to signal a partial redraw, such that the widget can determine whether it needs to update the whole display area (e.g. due to closing another window) or just the value part?

Link to comment
Share on other sites

For simplicity ugfx widgets always redraw the entire widget. This just keeps code size and ram requirements small. Handling multiple or non window sized clipping regions is very complex.

That being said, there is nothing stopping you from doing a partial draw in response to a signal or event or api call. This would just occur outside the normal redraw handling. An example is the graph window. The graph window does not use the automatic redraw at all. Instead it draws in direct response to a drawing request.

Widgets must have an automatic redraw (graph is a window not a widget) but widgets can still draw outside the automatic redraw.

Link to comment
Share on other sites

Thanks for the reply. I was hoping there was a way to make uGfx handle a partial redraw in the same way as it handles a full redraw (partly to avoid delays/stack demands on the thread which identifies the need for a partial redraw) - as I understand it, that's not possible. I'll have a look at the graph handling.

Link to comment
Share on other sites

Think I've found a way to achieve what I wanted, which might fit fairly well into ugfx:

1. I have a routine which detects whether a partial redraw is required (due to a value change). It triggers an update, thus:

  _gwinUpdate(gw);
((GHandle)gw)->flags |= GWIN_LAST_CONTROL_FLAG; // Have to do this after calling _gwinUpdate()

2. I added a line to the _gWinUpdate() routine:

void _gwinUpdate(GHandle gh) {
// Only redraw if visible
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;

// Mark for redraw
gh->flags |= GWIN_FLG_NEEDREDRAW;
gh->flags &= ~GWIN_LAST_CONTROL_FLAG; // Cancel any partial redraws
RedrawPending |= DOREDRAW_VISIBLES;

// Asynchronous redraw
TriggerRedraw();
}

3. The widget redraw routine can then test the flags to see whether a full or partial redraw is needed:

    uint8_t fullRedraw = (((GHandle)gw)->flags & GWIN_LAST_CONTROL_FLAG) == 0;
((GHandle)gw)->flags &= ~GWIN_LAST_CONTROL_FLAG;

I think there might be small potential for a timing race somewhere - unlikely to be a problem for me.

One suggestion for integrating this better is to add a parameter to _gWinUpdate():

void _gwinUpdate(GHandle gh, uint8_t partial) {
// Only redraw if visible
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;

// Mark for redraw
gh->flags |= GWIN_FLG_NEEDREDRAW;
if (partial)
gh->flags |= GWIN_LAST_CONTROL_FLAG; // Cancel any partial redraws
else
gh->flags &= ~GWIN_LAST_CONTROL_FLAG; // Cancel any partial redraws
RedrawPending |= DOREDRAW_VISIBLES;

// Asynchronous redraw
TriggerRedraw();
}

...then the update is a single call

Link to comment
Share on other sites

We originally had similar code but took it out for a couple of reasons when we did the redraw engine redesign..

1. There are many conditions where the wrong things end up being redrawn. Multi thread is such a pain!

2. It was just more complexity for gains in very few areas.

3. Full redraws are seldom a problem as you are just overwriting unchanged bits. There are no display artifacts other than some wasted cpu cycles and a slightly slower redraw.

4. Code savings made the effort worth while. Instead the code savings were invested in container and z-order based redraw capability.

I will look at your changes in more depth in a week or so (just busy with real life currently). If I can verify they work reliably without any of the original partial update issues I will merge them with the master repository.

Link to comment
Share on other sites

It's always a compromise between features, code size, code complexity, cpu cycles and ram usage. We trade one off against the other all the time with embedded programming.

In this case adding containers and the ability to have overlapping windows (even if it is in limited situations) added a lot of complexity and some code size. By compromising on the "draw once" principle we saved lots of code and in particular a lot of ram (multiple clipping regions uses significant runtime ram).

It may be possible to make minor changes to give a "conditional partial redraw" as you have done with minimal code. It is just going to take me time to ensure that we are not creating incorrect updating in some circumstances by adding it.

I am guessing that you have a particular widget in mind and a particular reason for wanting partial redraws. Can you please fill me in a little on those reasons and the widget concerned as that may help when I look at this?

Link to comment
Share on other sites

It's always a compromise between features, code size, code complexity, cpu cycles and ram usage. We trade one off against the other all the time with embedded programming.

Exactly what prompted this thread.

Can you please fill me in a little on those reasons and the widget concerned as that may help when I look at this?

Yes, its a very specific situation, where basically the redraw routine for the widget just needs to know whether to do a full or a partial redraw - it doesn't need any coordinate information or anything.

I am displaying a value surrounded by supplementary information; when the value changes I need to update the value part of the displayed area. (The value change is detected within the widget). I could do this with several label widgets, so that the value field is independent, but that would take up a fair amount of RAM, since I could be using a fair number of these value display widgets. If I handle this within the widget, there's at least a theoretical possibility of doing a partial redraw when a full redraw is required.

Link to comment
Share on other sites

Why not just draw the change where you detect the value has changed. Then the redraw routine only needs to handle the full redraw situation.

Mostly because the code which detects the change is in a relatively time-critical zone; also concerns about stack space.

Link to comment
Share on other sites

If you do something with this, can I suggest calling it 'Special Redraw Mode' or similar, rather than 'partial redraw', to avoid giving the wrong impression? That perhaps makes it clearer that its up to the widget to do something other than a simple full redraw.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...