Received: by ATHENA-PO-3.MIT.EDU (5.45/4.7) id AA17317; Sun, 21 Apr 91 11:40:35 EST
Received: from munnari.OZ.AU by ATHENA.MIT.EDU with SMTP
	id AA07605; Sun, 21 Apr 91 12:40:21 EDT
Received: from melba.bby.oz (via ditmela) by munnari.oz.au with SunIII (5.64+1.3.1+0.50)
	id AA28796; Mon, 22 Apr 1991 02:40:10 +1000 (from gnb%bby.oz.au@melba.bby.oz.au)
Received: from baby.bby.oz.au by melba.bby.oz.au (4.0/SMI-4.0/BBY)
	id AA19929; Wed, 17 Apr 91 19:42:53 EST
       (from gnb@bby.oz.au for bug-at%athena.mit.edu@munnari.oz)
Received: by baby.bby.oz.au (4.1/SMI-4.1)
	id AA12939; Wed, 17 Apr 91 19:42:46 EST
Message-Id: <9104170942.AA12939@baby.bby.oz.au>
To: bug-at@ATHENA.MIT.EDU
Subject: Proposed redraw protocol for AtPlotter
Date: Wed, 17 Apr 91 19:42:40 +1000
From: Gregory Bond <gnb@bby.oz.au>

Guys,

I mailed you yesterday with some thoughts on redraw protocols.  I have
spent today doing lots of investigation, including turning up a bug in
XtSetValues (see comp.windows.x).  

Enclosed is my proposed redrawing scheme for the plotter widget.  I
will probably (begin to) attempt to implement this tomorrow (thursday
18/4) to see how practical it is.

Any feedback, hints, thoughts would be most appreciated.

Given that there are a fair number of major changes piling up, should
be consider making a new release (v5?) with all the features that
change interfaces to programs?  Should we make a maintainence release
that fixes the bugs in v4?  At what point do we decide this is
enough, lets release a version and get everyone back working on the
same base source?

Greg,  actually being paid to work in this stuff......

-- 
Gregory Bond, Burdett Buckeridge & Young Ltd, Melbourne, Australia
Internet: gnb@melba.bby.oz.au    non-MX: gnb%melba.bby.oz@uunet.uu.net
Uucp: {uunet,pyramid,ubc-cs,ukc,mcvax,prlb2,nttlab...}!munnari!melba.bby.oz!gnb

---------------- cut here ----------------------------------------

This file describes the proposed redraw protocol for the Plotter widget
-----------------------------------------------------------------------

Some terms to help clarify things:
----------------------------------

Object) Any object that is a subclass of Object.  XtSetValues operates
	on objects.
Widget) Any object that is a subclass of Core and thus has a window.
Graph) The entire display of a Plotter widget.  Includes the widget
	and all children.
Plot) A single data object plotted on a graph.  One subclassed AtPlot
	object per plot, multiple plots per graph.
Refresh) Simply redraw one plot on the graph.  No screen clear or
	redraw of other child objects required.
Redraw) Simply refresh the onscreen image of the whole plotter widget.
	no calculation required.  No scren clear done explicitly (but
	often happens before redraw routine is called).
Relayout) The pixel dimentions of the plot have changed, but not the
	data.  Cause by resizing widget, adding or removing titles,
	etc.
Rescale) The data has changed and the existing axis bounds are not
	sufficient.  New axis bounds are required, but no layout has
	changed and all axes are in the same spot.

A rescale implies a redraw, and a relayout implies a redraw, but
relayout and rescale are orthogonal (i.e. one doesn't imply the other).

A description of the Xt behaviour:
----------------------------------

In the Xt toolkit, redisplay is forced by the set_values or
constraint.set_values widget class routines, which are called by the
XtSetVaues() routine.  When any of the set_values routines (either
normal or constraint or the older set_values_hook, for the widget
class or any superclasses) returns True, Xt clears the widget window
to the background color with a call to XClearArea.  This call results
in an expose event being put into the event queue.  Eventually, the
expose event comes to the head of the queue and the toolkit calls the
widget redraw routine.

If several XtSetValues calls (that return TRUE from a set_values
routine) are made in succession before returning to the main event
loop, several XClearWindow() calls will be made and several exposure
events will happen.  In the normal run of things, all but the first of
these will do nothing interesting.

If the object in question (i.e. the object having the XtSetValues done
in it) is not a widget (i.e. is a subclass of Object but not Widget
and doesn't have any window), then the toolkit obviously cannot do an
XClearArea.  What happens then is that XtSetValues looks up the widget
hierarchy until it finds an ancestor of the object that _is_ a widget,
and then clears the area of the ancestor widget's window that
corresponds to the rectangle layout.  (This is a bug in that SetValues
that assumes all non-widget objects are subclasses of RectObj).  This
means that for non-widget objects, the widget parent (or ancestor)
will get the expose event.  At the moment, all non-RectObj children
have the potential to cause BadValue errors because of this bug, so
Objects should not return True from a set_values routine, and
constraint widgets should not return True from constraint.set_values
routines called on behalf of a non-RectObj child.


Goals:
------

Children never draw anything themselves.  They request redraws from
the parent.

The parent attempts, as much as possible, to batch the redraw operations.

Avoid the Xt bug by not returning True from child object set_values
routine of the plotter constraint.set_values routine.

Avoid the use of XtSetValues unless necessary.  Will require the
addition of some "member functions".  Avoid the axis-to-plotter
callbacks (Ugly!); use member functions.

Split requests for a rescaling from requests for a relayout.  Have a
callback list for each of these so that applications can co-ordinate
the position, scaling etc between multiple instances of the Plotter
widget.  (These callbacks would be called after the "default" layout,
scaling etc has been done, and given an opportunity to change them
before they are acted on.  Should help avoid the cascaded updates!)
If both a relayout and a rescale are to be done, then the defaults for
both are calculated, then the scale callback is called, then the
layout callback is called, then the altered parameters are used to
plot the graph.

Plot and axis objects can clearly request different levels of rescale,
relayout or redraw, and can distinuish between recale and relayout
requests.

Plotter handles child requests intelligently, with the least possible
amount of redrawing.

Clearly define the publically available "member" routines (of both
plotter and axis objects) that can be called from the scaling
callbacks without fear of recursion!

Child objects should cache their pixel coordinate data in a way that
allows rapid redraw by using e.g. XDrawLines() with minimal or no
calculation.

Proposed Design:
----------------

ALL drawing to be done as part of the redraw routine, called ONLY by
the Intrinsics on expose events.  No exceptions.

Object set_values routines always returns false (bug catcher).

Plotter constraint.set_value routine always returns false (bug catcher).

Plotter tries to ensure only one outstanding expose event by returning
false from the set_values routine most of the time. (This will require
state in the widget instance record).  To avoid massive redraws on
simple requests, is will be necessary to forge a null expose event
using SendEvent when a call to the redraw routine is required but
clearing the display is not.  (Again, state is required to determine
if such a synthetic event has taken place.)  Changes requiring a
clearscreen must return TRUE from the set_values routine, even if the
syntheic event has been sent, to get the screen cleared. (Possible to
do an XClearWindow instead if the synthetic event has been sent).

The plotter receives requests from the children and stores enough
local state so that when the redraw routine is eventually called the
required action can take place.  Does no drawing at that time.
Requests a redraw with a synthetic or real expose as appropriate.

The redraw routine should look for the most drastic redraw that is
required and do that, forgetting the requests of any less drastic
actions that will be done in the process.  If there are no pending
requests and the Region is NULL, then it is an extraneous expose and
it is ignored.  If the region is not NULL, it is an expose and a
simple redraw of the entire widget is in order, clipped by the
supplied region. Before returning, should erase all stored requests
(after ensuring they have been satisfied!)

State required:

plotter: 
	rescale required (i.e. axis bounds changed)
	relayout required (i.e. pixel coords changed)
	synthetic expose sent
	real expose sent
	preferred layout

Constrains (held on behalf of the child):

	refresh required (i.e. draw me again but don't need to redraw
			  the whole thing)
	rescale required (i.e. data has changed, and needs to be
			  rescaled to pixel corrdinates once the
			  appropriate scaling factor has been determined).

Plotter routines the child can call: (Many of these functions are
currently done through XtSetvalues - a long way around; some are done
via calls direct to the axis objects - this has confused redraw semantics.)

	plot extended - Data had been added to the plot, but existing
	  data hasn't changed, and here is the new bounding box.
	  Depending on the other plots on the graph, the overall
	  boundingbox may change.  If not, a simple refresh of the
	  plot in question would suffice.  Otherwise, a rescale and
	  redraw will be needed.  Useful for incrementally updating
	  plots (which the current XYPlot won't do).

	data changed - The existing data has been changed and this is
	  the new boundingbox.  If the overall boundingbox is still
	  OK, then a redraw is required, else a rescale followed by a
	  redraw is required.  It is assumed a real - to - pixel
	  conversion will be performed for this widget during the
	  redraw.

	refresh required - Something that can easily be fixed with a
	  refresh has occured (e.g. changed foreground color). It is
	  up to the child to determine whether this is enough (e.g.
	  for an axis, if the grid color changes, then a redraw is
	  probably needed.)

	redraw required - Something that cannot be fixed by refresh
	  has changed (e.g. background color). Again, up to the child
	  to decide.

	relayout required - The withs of an axis object changed and a
	  relayout is needed. Shouldn't be generated from plot objects.

	Scale Changed - An axis object has had the scale changed (and
	  it was not autoscaling).  Will need to rescale.

The layout callback routine:
	Gets passed a copy of the current layout structure (e.g. axis
	positions, legend position, title position, etc).  Can call a set
	layout routine with the desired layout, and don't care items = -1.
	Can call a getlayout routine for any plotter.

The scale callback routine:
	Gets passed the min and max for the three scales, can call a
	set scale routine that changes all six numbers.  Can call a
	getscale routine for any plotter.

Both the set scale and set layout routines can be called at any time
for any plotter, and will generate the appropriate redraw requests.  

When choosing the "default" layout, the plotter will take notice of
any non-negative entries in the prefered layout, otherwise will choose
sensible defaults.

