Re: [guppi-list] Re: Plot idl



Havoc Pennington wrote:
> 
> These are very helpful and concrete suggestions. Thanks for taking the
> time to write...

You're very welcome.  Watch out, more suggestions below... :-)

[snip]
> > 3.  Different ValueTypes on the same Axis.  What should a Plot
> > implementation do with an axis that contains both strings and doubles?
> 
> I'm not actually sure what Gnumeric intends to do with the string value
> type, and int can be subsumed by double. So it may be possible to get rid
> of the union entirely.

Regardless, I think plots will need to deal with strings for something
like a bar graph of the populations of different cities.  You would need
strings for the city names.

> 
> Assuming it remains, can I indicate in the IDL that a sequence has to
> have homogeneous type, or is this just something to document?

Well, you can obviously do something like this:

  typedef sequence<double> DoubleSeq;  // Sequence of only doubles

But you probably meant a homogenous sequence of an unspecified type, and
I don't know of a way to do that.  You could document it, but you would
still probably have to check every such sequence before using it to make
sure the caller obeyed.

Actually, I just thought of an even better solution.  You could add the
following methods to the Values interface:

  typedef sequence<double> DoubleSeq;

  // Return the values as a sequence of doubles coercing as necessary.
  DoubleSeq get_as_double_seq(in unsigned long start_index, in unsigned
count)
    raises(OutOfRange,CoercionError);

  // Set the values from a sequence of doubles, coercing as necessary.
  void set_from_double_seq(in unsigned long start_index, in DoubleSeq
seq)
    raises(OutOfRange,CoercionError);

  typedef sequence<int> IntSeq;

  // Return the values as a sequence of ints, coercing as necessary.
  IntSeq get_as_int_seq(in unsigned long start_index, in unsigned count)
    raises(OutOfRange,CoercionError);

  // Set the values from a sequence of ints, coercing as necessary.
  void set_from_int_seq(in unsigned long start_index, in IntSeq seq)
    raises(OutOfRange,CoercionError);

  typedef sequence<string> StringSeq;

  // Return the values as a sequence of strings, coercing as necessary.
  StringSeq get_as_string_seq(in unsigned long start_index, in unsigned
count)
    raises(OutOfRange,CoercionError);

  // Set the values from a sequence of string coercing as necessary.
  void set_from_string_seq(in unsigned long start_index, in StringSeq
seq)
    raises(OutOfRange,CoercionError);

This leaves the coercion with whoever provides the Values interface.  If
you are plotting data from a gnumeric spreadsheet, I'd say gnumeric
should provide the Values interface.  If you are running guppi
stand-alone, guppi is the provider.  In either case, the provider knows
best how to do the coercion.

BTW, when I wrote the last email, I hadn't noticed that Values was an
interface.  I guess I was assuming it was a "typedef sequence<Value>". 
Since it is an interface, my suggested get_values() and set_values()
probably don't make much sense because they will return and pass an
object reference instead of the values themselves.  What I intended was
something like:

  typedef sequence<Value> ValueSeq;  // You call it Data
  ValueSeq get_as_value_seq(in unsigned long start_index, in unsigned
count)
    throws(OutOfRange);
  void set_from_value_seq(in unsigned long start_index, in ValueSeq seq)
    throws(OutOfRange);


> > I recommend having each type of
> > plot consist of the appropriate Axis descriptions (start/stop, auto,
> > tick spacing, etc.) and separate homogeneous values arrays.  For
> > example:
> >
> 
> Oops, you're right. Guppi can actually do multi-axis plots so I don't know
> what I was thinking not exporting that functionality. One thing Guppi
> can't do yet is overlay one plot on another; in that case you have a
> single axis and multiple value arrays. (I guess you are referring to the
> overlay case?)

Yes.

> 
> Anyway, to cover both of these cases, maybe have a sequence of Axis, where
> an Axis has start/stop, categorical/scalar, etc., and each Axis can
> control a sequence of Value to be plotted on that axis? That might work
> well.

You say "sequence of Value" so I'm assuming you mean each Axis would
have its own ValueSeq/Data instead of its own Values object reference
like you had it initially.  I think you are better off using a Values
object reference.  That way, you can just call the appropriate
get_as_*_seq() method to get the data you need to plot from the Values
provider.  Different types of plots would call different methods for
different axes.

It also sound like you are thinking of using a sequence of Axis, each
with one set of values.  This will work, but it means that if you have
many overlays on a simple 2-D plot, you have many Axis objects which are
identical except for the values.  I think you are better off allowing
multiple Values objects per Axis object.  You could do this by storing a
sequence of Values objects within each Axis object instead of just one. 
I recommend against that as well however.  It confuses the model
(Values) with the view (Axis).  Although I can't think of an example
where you would have a Values object without some sort of minimal Axis
object, one may turn up.

Basically, here is what I'm suggesting:

  interface Axis {
    attribute string title;
    attribute string font_name;
    attribute int font_size;
  }

  interface ScalarAxis : Axis {
    attribute double start_value;
    attribute double stop_value;
    attribute double tick_spacing;
  }

  interface CategoricalAxis : Axis {
    // Can't think of anything specific to categorical axes off hand.
  }

  interface TwoDPlot : Plot {
    attribute ScalarAxis x_axis;
    attribute ScalarAxis y_axis;

    attribute Values x_values; // use x_values->get_as_double_seq()
    attribute Values y_values; // use y_values->get_as_double_seq()
  }

  interface MultiTwoDPlot : TwoDPlot {
    attribute ScalarAxis x_axis_top;
    attribute ScalarAxis y_axis_right;

    attribute Values x_values_top; // use
x_values_top->get_as_double_seq()
    attribute Values y_values_right; // use
y_values_right->get_as_double_seq()
  }

  interface BarGraph : Plot {
    attribute CategoricalAxis x_axis;
    attribute ScalarAxis y_axis;
    
    attribute Values x_values;  // use x_values->get_as_string_seq()
    typedef sequence<Values> ValuesSeq;  // Sequence of Values object
references
    attribute ValuesSeq y_values_seq;  // use
y_values_seq[i]->get_as_double_seq()
  }

  interface PieChart : Plot {
    attribute Values categories;  // use categories->get_as_string_seq()
    attribute Values amounts;     // use amounts->get_as_double_seq()
  }


OK.  Thats all I can think of at the moment.  As before, just some
suggestions.

--Dean



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]