plot-container – Embed plot snips to GUI applications
1 plot-container% Class
plot-container%
new
cell-dimensions
clear-all
set-snip
set-snips
set-snips/  layout
add-floating-snip
set-floating-snip
set-background-message
set-hover-pict
set-hover-pict-at-mouse-event
plot-container-group?
vgroup
hgroup
cgroup
2 Some utility functions to use with plots and plot containers
good-hover?
xposition->histogram-slot
get-snip-location
move-snip-to
7.7

plot-container – Embed plot snips to GUI applications

Alex Harsányi

1 plot-container% Class

 (require plot-container) package: plot-container

class

plot-container% : class?

  superclass: editor-canvas%

The plot-container% class is a GUI container that can be used to embed snip% objects such as plots produced by plot-snip in GUI applications. It supports building interactive GUI applications which display different types of data, for example, when plot snips are combined with using set-mouse-event-callback in 2d-plot-snip% to install on-hover callbacks for the plots. The container has the following features:
Snips will be arranged either using a specified layout (see set-snips/layout) or, by default, in rows and columns such that each occupy an equal amount of space – i.e. all snips have the same size. The snips will be resized dynamically if the container itself changes size or new snips are added. The number of columns is specified when the plot-container% is instantiated and the number of rows will be calculated based on the number of snips and the column count. The plot snips must be any snip%, but this container class was originally intended to display plots produced by plot-snip, thus its name. Plot snips can be added to the container using set-snip or set-snips or set-snips/layout.
Floating snips will show up on top of the plot snips and are not placed in rows and columns, instead the user can drag them around and they can be used to display additional information, such as a plot legend. Use add-floating-snip and set-floating-snip to add floating snips. Just as with the plot snips, any snip% object is a valid floating snip, in particular pict-snip% instances are useful for constructing images based on the pict package.
A Background Message can be set up to be shown when the plot container is empty, see set-background-message. This is useful, as the contents of the plot container can be changed dynamically at runtime.
A Floating Snip can be added using set-hover-pict or set-hover-pict-at-mouse-event. This is intended to support implementing tooltips or displaying additional information when the user hovers the mouse over various plot elements.

constructor

(new plot-container% 
    [parent parent] 
    [[columns columns] 
    [spacing spacing]]) 
  (is-a?/c plot-container%)
  parent : 
(or/c (is-a?/c frame%) (is-a?/c dialog%)
      (is-a?/c panel%) (is-a?/c pane%))
  columns : positive-integer? = 1
  spacing : positive-integer? = 5
Create a new instance of a plot-container% which will arrange plot snip% objects in columns columns with spacing pixels between them. The number of rows will be determined by the number of plot snips added. Additional init argyments can be passed in, they will all go to the editor-canvas% class, see its documentation for what options are available.

method

(send a-plot-container cell-dimensions snip-count)

  
real? real?
  snip-count : positive-integer?
Return the dimensions of a plot snip when this plot-container% would hold snip-count snips. The dimensions will be calculated based on the current size of the canvas plus the number of columns and spacing between snips.

This method can be used to construct the plot snip instances with the correct dimensions and avoid a snip resize operation when these snips are added to the container.

WARNING The cell dimensions are only valid if the snips are arranged in rows and columns by calling add-snips. If a layout is used, as per add-snips/layout, the cell dimensions returned by this method will not correspond to the ones assigned to the snips in the layout.

method

(send a-plot-container clear-all)  any/c

Clear all snips from the container.

method

(send a-plot-container set-snip snip)  any/c

  snip : (is-a?/c snip%)
Set snip as the only snip managed by the container, replacing any previous plot snips.

method

(send a-plot-container set-snips snip ...)  any/c

  snip : (is-a?/c snip%)
Set the contents of the container to the snip instances passed in as paramters, replacing any previous plot snips.

method

(send a-plot-container set-snips/layout group)  any/c

  group : plot-container-group?
Set the contents of the container to the group, which is a group of snips created using hgroup, vgroup and cgroup. This method allows subdividing the contents of the container area in a tree-like fashion.

method

(send a-plot-container add-floating-snip snip    
  x    
  y)  any/c
  snip : (is-a?/c snip%)
  x : real?
  y : real?
Add snip as a floating snip to the container and place it at x, y. Any previous floating snips will be kept as well.

method

(send a-plot-container set-floating-snip snip    
  x    
  y)  any/c
  snip : (is-a?/c snip%)
  x : real?
  y : real?
Remove all existing floating snips, than add snip as a floating snip to the container and place it at x, y.

method

(send a-plot-container set-background-message message)  any/c

  message : (or/c #f string?)
Set a message to be displayed in the plot container when it contains no snips at all. If the message is #f, no message will be displayed.

method

(send a-plot-container set-hover-pict pict    
  x    
  y)  any/c
  pict : (or/c #f pict?)
  x : real?
  y : real?
Set pict to be displayed at locations x, y, or hide the pict when #f. The pict will be displayed on top of all other snips in the container and can be used to implement tool tips for the contents of the container.

method

(send a-plot-container set-hover-pict-at-mouse-event pict 
  event) 
  any/c
  pict : (or/c #f pict?)
  event : (is-a?/c mouse-event%)
Display pict at the location of the mouse event. This method will take the mouse event coordinates, convert them to plot container coordinates and call set-hover-pict.

procedure

(plot-container-group? group)  boolean?

  group : any/c
Check if the argument is a snip group, as produced by vgroup, hgroup or cgroup.

procedure

(vgroup item    
  ...    
  [#:border border    
  #:spacing spacing])  plot-container-group?
  item : (listof (or/c plot-container-group? (is-a?/c snip%)))
  border : (or/c positive? zero?) = 0
  spacing : (or/c positive? zero?) = 5

procedure

(hgroup item    
  ...    
  [#:border border    
  #:spacing spacing])  plot-container-group?
  item : (listof (or/c plot-container-group? (is-a?/c snip%)))
  border : (or/c positive? zero?) = 0
  spacing : (or/c positive? zero?) = 5

procedure

(cgroup columns    
  item ...    
  [#:border border    
  #:spacing spacing])  plot-container-group?
  columns : positive-integer?
  item : (listof (or/c plot-container-group? (is-a?/c snip%)))
  border : (or/c positive? zero?) = 0
  spacing : (or/c positive? zero?) = 5
Arrange all items with a border around all the group and spacing space between items. All items will have the same dimensions and any plot-container-group? items will have this space sub-divided among the items in that group. The result of these functions are intended to be passed to set-snips/layout in plot-container%.

vgroup will place items in one vertical column with the height equally divided between all items.

hgroup will place items in one horizontal row with the width equally divided between all items.

cgroup will place all items in columns, with the number of rows depending on the number of itmes. The width is divided equally between the number of columns and the height is divided equally between the number of rows.

2 Some utility functions to use with plots and plot containers

 (require plot-container/hover-util)
  package: plot-container

This module provides a collection of helper functions for building interactive plots. The plot-snip function returns a snip% representing the plot, and this snip has two additional methods, set-mouse-event-callback and set-overlay-renderers, which help with this. See the plot documentation for 2d-plot-snip% for more details.

procedure

(good-hover? snip x y event)  boolean?

  snip : (is-a?/c snip%)
  x : (or/c real? #f)
  y : (or/c real? #f)
  event : (is-a?/c mouse-event%)
Return #t when the x, y and event passed to a plot snip mouse callback are valid, and hover information should be displayed for the point at x, y.

The parameters are considered valid when the coordinates x and y are not #f, the mouse event is a motion event and the plot snip is directly under the mouse with no other snips above it.

The x, y coordinates can be #f when they are inside the plot snip but not on the plot itself, for example in the axes area.

This function encapsulates all the logic on whether to add or clear overlay renderers from a plot, and allows writing hover callbacks in the following form:

(define (hover-callback snip event x y)
  (if (good-hover? snip x y event)
    ; Need to add overlay renderers for position x,y
    (send snip set-overlay-renderers ...)
    ; Nedd to clear any overlay renderers
    (send snip set-overlay-renderers #f)))

procedure

(xposition->histogram-slot xposition 
  [skip 
  gap]) 
  
(or/c #f exact-nonnegative-integer?)
(or/c #f exact-nonnegative-integer?)
  xposition : number?
  skip : number? = (discrete-histogram-skip)
  gap : number? = (discrete-histogram-gap)
Convert the xposition received by the hover callback in a histogram plot back to the series and the slot withing that series. skip and gap are the #:skip and #:gap arguments passed to the discrete-histogram renderer, they default to discrete-histogram-gap and discrete-histogram-skip parameters, just as they do for the discrete-histogram renderer.

Returns two values, the series, when multiple historams are plotted and the slot within that histogram. Will return (values #f #f) if the X position is between the bars of the histogram.

procedure

(get-snip-location snip)  (or/c #f (cons/c number? number?))

  snip : (or/c #f (is-a?/c snip%))
Return the location of snip as a (cons X Y), or return #f if snip is not added to an editor.

Together with move-snip-to, this function can be used to retrieve and save the location of any hover snips in a plot-container% and restore them at a later time.

procedure

(move-snip-to snip location)  any/c

  snip : (is-a?/c snip%)
  location : (or/c #f (cons/c number? number?))
Move snip to location, adjusting it as necessary to remain fully visible inside the canvas. This is intended to be used with locations retrieved by get-snip-location and unlike the plot-container%’s add-floating-snip, this function will adjust the location so that the snip visible in the container – this is useful if the container has changed size since the location was retrieved and saved.

Assumes the snip is added to an editor.