NAME

Prima::Grids - grid widgets

SYNOPSIS

use Prima qw(Grids Application);

my $grid = Prima::Grid-> new(
	cells       => [
		[qw(1.First 1.Second 1.Third)],
		[qw(2.First 2.Second 2.Third)],
		[qw(3.First 3.Second 3.Third)],
	],
	onClick     => sub {
		print $_[0]-> get_cell_text( $_[0]-> focusedCell), " is selected\n";
	}
);
run Prima;

DESCRIPTION

The module provides classes for several abstraction layers for the representation of grid widgets. The class hierarchy is as follows:

AbstractGridViewer
	AbstractGrid
	GridViewer
		Grid

The root class, Prima::AbstractGridViewer, provides a common interface, while by itself it is not directly usable. The main difference between classes is in the way the cell data are stored. The simplest organization of a text-only cell, provided by Prima::Grid, stores data as a two-dimensional array of text scalars. More elaborated storage and representation types are not realized, and the programmer is urged to use the more abstract classes to derive their own mechanisms. To organize an item storage different from Prima::Grid it is usually enough to overload either the Stringify, Measure, and DrawCell events, or their method counterparts: get_cell_text, columnWidth, rowHeight, and draw_items.

The grid widget is designed to contain cells of variable extents, of two types, normal and indent. The indent rows and columns are displayed near to the widget borders, and their cells are drawn with distinguished colors. An example usage for a bottom indent row is a sum row in a spreadsheet application; the top indent row can be used for displaying columns' headers. The normal cells can be selected by the user, scrolled, and selected. The cell selection can only contain rectangular areas and therefore is operated with two integer pairs at the beginning and the end of the selection.

The widget operates in two visual scrolling modes; when the space allows, the scrollbars affect the leftmost and the topmost cell. When the widget is not large enough to accommodate at least one cell and all indent cells, the layout is scrolled pixel-wise. These modes are named 'cell' and 'pixel', after the scrolling units.

The widget allows the interactive changing of cell widths and heights by dragging the grid lines between the cells.

Prima::AbstractGridViewer

Prima::AbstractGridViewer, the base for all grid widgets in the module, provides the interface to generic grid browsing functionality, plus some functionality for text-oriented grids. The class is not usable directly.

Prima::AbstractGridViewer is a descendant of Prima::Widget::GroupScroller, and some of its properties are not described here.

Properties

allowChangeCellHeight BOOLEAN

If 1, the user is allowed to change the vertical extents of cells by dragging the horizontal grid lines. The prerequisites are: the lines must be set visible via the drawHGrid property, the constantCellHeight property set to 0, and the changes to the vertical extents can be recorded via the SetExtent notification.

Default value: 0

allowChangeCellWidth BOOLEAN

If 1, the user is allowed to change the horizontal extents of cells by dragging the horizontal grid lines. The prerequisites are: the lines must be set visible via the drawVGrid property, the constantCellWidth property set to 0, and the changes to the horizontal extents can be recorded via the SetExtent notification.

Default value: 0

cellIndents X1, Y1, X2, Y2

Marks the marginal rows and columns as 'indent' cells. The indent cells are drawn with another color pair ( see indentCellColor, indentCellBackColor ), and cannot be selected and scrolled. X1 and X2 correspond to the number of the indent columns, and Y1 and Y2 to the number of the indent rows.

leftCell and topCell do not count the indent cells as the leftmost or topmost visible cells; in other words, X1 and Y1 are minimal values for leftCell and topCell properties.

Default value: 0,0,0,0

clipCells INTEGER

A three-state integer property that manages the way clipping is applied when cells are drawn. Depending on the kind of graphic in cells, the clipping may be necessary, or unnecessary.

If the value is 1, the clipping is applied for every column drawn, as the default drawing routines proceeds column-wise. If the value is 2, the clipping is applied for every cell. This setting reduces the drawing speed significantly. If the value is 0, no clipping is applied.

This property is destined for custom-drawn grid widgets when it is the developer's task to decide what kind of clipping suits better. Text grid widgets, Prima::AbstractGrid and Prima::Grid, are safe with clipCells set to 1.

Default value: 1

columns INTEGER

Sets the number of columns, including the indent columns. The number of columns must be larger than the number of indent columns.

Default value: 0.

columnWidth COLUMN [ WIDTH ]

A run-time property, selects the width of a column. To acquire or set the width, Measure and SetExtent notifications can be invoked. The result of Measure may be cached internally using the cache_geometry_requests method.

The width does not include the widths of eventual vertical grid lines.

If constantCellWidth is defined, the property is used as its alias.

constantCellHeight HEIGHT

If defined, all rows have equal height, HEIGHT pixels. If undef, rows have different heights.

Default value: undef

constantCellWidth WIDTH

If defined, all rows have equal width, WIDTH pixels. If undef, columns have different widths.

Default value: undef

drawHGrid BOOLEAN

If 1, horizontal grid lines between cells are drawn with gridColor.

Default value: 1

drawVGrid

If 1, vertical grid lines between cells are drawn with gridColor.

Default value: 1

dx INTEGER

A run-time property. Selects horizontal offset in pixels of grid layout in pixel mode.

dy INTEGER

A run-time property. Selects vertical offset in pixels of grid layout in pixel mode.

focusedCell X, Y

Selects coordinates or the focused cell.

gridColor COLOR

Selects the color of the grid lines.

Default value: cl::Black .

gridGravity INTEGER

The property selects the breadth of the area around the grid lines that react to the grid-dragging mouse events. The minimal value of 0, marks only grid lines themselves as the dragging areas but makes the operation inconvenient for the user. Larger values make the dragging more convenient, but increase the chance that the user will not be able to select too narrow cells with the mouse.

Default value: 3

indentCellBackColor COLOR

Selects the background color of the indent cells.

Default value: cl::Gray .

indentCellColor

Selects the foreground color of the indent cells.

Default value: cl::Gray .

leftCell INTEGER

Selects the index of the leftmost visible normal cell.

multiSelect BOOLEAN

If 1, the normal cells in an arbitrary rectangular area can be marked as selected ( see selection ). If 0, only one cell at a time can be selected.

Default value: 0

rows INTEGER

Sets the number of rows, including the indent rows. The number of rows must be larger than the number of the indent rows.

Default value: 0.

topCell

Selects the index of the topmost visible normal cell.

rowHeight INTEGER

A run-time property, selects the height of a row. To acquire or set the height, Measure and SetExtent notifications can be invoked. The result of Measure may be cached internally using the cache_geometry_requests method.

The height does not include the heights of eventual horizontal grid lines.

If constantCellHeight is defined, the property is used as its alias.

selection X1, Y1, X2, Y2

If multiSelect is 1, manages the extent of a rectangular area that contains selected cells. If no such area is present, the selection is (-1,-1,-1,-1), and has_selection returns 0 .

If multiSelect is 0, in get-mode returns the focused cell, and ignores the parameters in the set-mode.

Methods

cache_geometry_requests CACHE

If CACHE is 1, starts caching results of the Measure notification, thus making the subsequent columnWidth and rowHeight calls lighter. If CACHE is 0, flushes the cache.

If a significant geometry change happens during the caching, the cache is not updated automatically, so it is the caller's responsibility to flush the cache.

deselect_all

Removes the selection if multiSelect is 1.

draw_cells CANVAS, COLUMNS, ROWS, AREA

A bulk draw routine, called from onPaint to draw individual cells. AREA is an array of four integers in inclusive-inclusive coordinates of the widget inferior without borders and scrollbars ( the result of get_active_area(2) call; see "get_active_area" in Prima::Widget::IntIndents ).

COLUMNS and ROWS are structures that reflect the columns and rows of the cells to be drawn. Each item in these corresponds to a column or row, and is an array with the following layout:

0: column or row index
1: type; 0 - normal cell, 1 - indent cell
2: visible cell breadth
3: visible cell start
4: visible cell end
5: real cell start
6: real cell end

The coordinates are in the inclusive-inclusive coordinate system and do not include eventual grid space, nor gaps between the indent and normal cells. By default, internal arrays {colsDraw} and {rowsDraw} are passed as COLUMNS and ROWS parameters.

In the Prima::AbstractGrid and Prima::Grid classes <draw_cells> is overloaded to transfer the call to std_draw_text_cells, the text-oriented optimized routine.

draw_text_cells SCREEN_RECTANGLES, CELL_RECTANGLES, CELL_INDECES, FONT_HEIGHT

A bulk routine for drawing text cells, is called from std_draw_text_cells .

SCREEN_RECTANGLES and CELL_RECTANGLES are arrays, where each item is a rectangle with an exterior of a cell. SCREEN_RECTANGLES contains rectangles that cover the visible area of the cell; CELL_RECTANGLES contains rectangles that span the cell extent disregarding its eventual partial visibility. For example, a 100-pixel cell with only its left half visible would contain corresponding arrays [150,150,200,250] in SCREEN_RECTANGLES, and [150,150,250,250] in CELL_RECTANGLES.

CELL_INDECES contains arrays of the cell coordinates; each array item is an array of integer pairs where item 0 is the column, and item 1 is the row of the cell.

FONT_HEIGHT is the current font height value, as draw_text_cells is mostly used for text operations and may require vertical text justification.

get_cell_area [ WIDTH, HEIGHT ]

Returns screen area in the inclusive-inclusive pixel coordinates. The area is used to display normal cells. The extensions are related to the current size of a widget, however, can be overridden by specifying WIDTH and HEIGHT.

get_cell_alignment COLUMN, ROW

Returns two ta:: constants for horizontal and vertical cell text alignment. Since the class does not assume the item storage organization, the values are queried via the GetAlignment notification.

get_cell_text COLUMN, ROW

Returns the text string assigned to the cell in COLUMN and ROW. Since the class does not assume the item storage organization, the text is queried via the Stringify notification.

get_range VERTICAL, INDEX

Returns a pair of integers, the minimal and maximal breadth of INDEXth column or row in pixels. If VERTICAL is 1, the rows are queried; if 0, the columns.

The method calls the GetRange notification.

get_screen_cell_info COLUMN, ROW

Returns information about the cell in COLUMN and ROW, if it is currently visible. The returned parameters are indexed by the gsci::XXX constants:

gsci::COL_INDEX - visual column number where the cell is displayed
gsci::ROW_INDEX - visual row number where the cell is displayed
gsci::V_FULL    - cell is fully visible

gsci::V_LEFT    - an inclusive-inclusive rectangle of the visible
gsci::V_BOTTOM      part of the cell. These four indices are grouped
gsci::V_RIGHT       under list constant, gsci::V_RECT.
gsci::V_TOP

gsci::LEFT      - an inclusive-inclusive rectangle of the cell, as if
gsci::BOTTOM        it is fully visible. These four indices are grouped
gsci::RIGHT         under list constant, gsci::RECT. If gsci::V_FULL
gsci::TOP           is 1, these values are identical to those in gsci::V_RECT.

If the cell is not visible, returns an empty array.

has_selection

Returns a boolean value, indicating whether the grid contains a selection (1) or not (0).

point2cell X, Y, [ OMIT_GRID = 0 ]

Returns information about the point X, Y in widget coordinates. The method returns two integers CX and CY with cell coordinates and an eventual HINTS hash that contains more information about the pixel location. If OMIT_GRID is set to 1 but the pixel belongs to the grid, the pixels are treated as part of an adjacent cell. The call syntax is:

($CX, $CY, %HINTS) = $self->point2cell( $X, $Y);

If the pixel lies within the cell boundaries by either coordinate, CX and/or CY are correspondingly set to that cell column and/or row. When the pixel is outside the cell space, CX and/or CY are set to -1.

HINTS may contain the following values:

x and y

If 0, the coordinate lies within the boundaries of a cell.

If -1, the coordinate is on the left/top of the cell body.

If +1, the coordinate is on the right/bottom of the cell body, but within the widget.

If +2, the coordinate is on the right/bottom of the cell body, but outside the widget.

x_type and y_type

Present when x or y values are 0.

If 0, the cell is a normal cell.

If -1, the cell is a left or a top indent cell.

If +1, the cell is a right or a bottom indent cell.

x_grid and y_grid

If 1, the point is at a grid line. This case can only happen when OMIT_GRID is 0. If allowChangeCellHeight and/or allowChangeCellWidth are set, treats also gridGravity-broad pixels strips on both sides of the line as the grid.

Also, values of x_left/x_right or y_bottom/y_top might be set.

x_left/x_right and y_bottom/y_top

Present together with x_grid or y_grid. Contain the indices of the cells adjacent to the grid line.

x_gap and y_gap

If 1, the point is inside a gap between the last normal cell and the first right/bottom indent cell.

normal

If 1, the point lies within the boundaries of a normal cell.

indent

If 1, the point lies within the boundaries of an indent cell.

grid

If 1, the point is at a grid line.

exterior

If 1, the point is in an inoperable area or outside the widget boundaries.

redraw_cell X, Y

Repaints the cell with coordinates X and Y.

reset

Recalculates internal geometry variables.

select_all

Marks all cells as selected if multiSelect is 1.

std_draw_text_cells CANVAS, COLUMNS, ROWS, AREA

An optimized bulk routine for text-oriented grid widgets. The optimization is achieved under the assumption that each cell is drawn with two colors only so that the color switching can be reduced.

The routine itself paints the cells' background and then calls draw_text_cells to draw the cells' content.

For the explanation of COLUMNS, ROWS, and AREA parameters see draw_cells .

Events

DrawCell CANVAS, COLUMN, ROW, INDENT, @SCREEN_RECT, @CELL_RECT, SELECTED, FOCUSED, PRELIGHT

Called when a cell with COLUMN and ROW coordinates is to be drawn on CANVAS. SCREEN_RECT is a cell rectangle in widget coordinates, where the item is to be drawn. CELL_RECT is the same as SCREEN_RECT but calculated as if the cell is fully visible.

SELECTED, FOCUSED, and PRELIGHT are boolean flags, if the cell must be drawn correspondingly in selected, focused, and pre-lighted states.

GetAlignment COLUMN, ROW, HORIZONTAL_ALIGN_REF, VERTICAL_ALIGN_REF

Stores two text alignment ta:: constants, assigned to the cell with COLUMN and ROW coordinates, into HORIZONTAL_ALIGN_REF and VERTICAL_ALIGN_REF scalar references.

GetRange VERTICAL, INDEX, MIN, MAX

Stores minimal and maximal breadth of INDEXth column ( VERTICAL = 0 ) or row ( VERTICAL = 1) in the corresponding MIN and MAX scalar references.

Measure VERTICAL, INDEX, BREADTH

Stores breadth in pixels of the INDEXth column ( VERTICAL = 0 ) or row ( VERTICAL = 1) into BREADTH scalar reference.

This notification by default may be called from within the begin_paint_info/end_paint_info brackets. To disable this feature set the internal flag {NoBulkPaintInfo} to 1.

SelectCell COLUMN, ROW

Called when a cell with COLUMN and ROW coordinates is focused.

SetExtent VERTICAL, INDEX, BREADTH

Reports breadth in pixels of the INDEXth column ( VERTICAL = 0 ) or row ( VERTICAL = 1), as a response to the columnWidth and rowHeight calls.

Stringify COLUMN, ROW, TEXT_REF

Stores the text string, assigned to the cell with COLUMN and ROW coordinates, into the TEXT_REF scalar reference.

Prima::AbstractGrid

The same as its ascendant, Prima::AbstractGridViewer, except that it does not propagate the DrawItem message, assuming that the items must be drawn as text.

Prima::GridViewer

The class implements cell data and geometry storage mechanisms but leaves the data format to the programmer. The cells are accessible via the cells property and several other helper routines.

The cell data are stored in an array, where each item corresponds to a row, and contains an array of scalars, where each corresponds to a column. All data managing routines, that accept two-dimensional arrays, assume that the column arrays are of the same width.

For example, [[1,2,3]]] is a valid one-row, three-column structure, and [[1,2],[2,3],[3,4]] is a valid three-row, two-column structure. The structure [[1],[2,3],[3,4]] is invalid, since its first row has one column, while the others have two.

Prima::GridViewer is derived from Prima::AbstractGridViewer.

Properties

allowChangeCellHeight INTEGER

Default value: 1

allowChangeCellWidth INTEGER

Default value: 1

cell COLUMN, ROW, ITEM

Run-time property. Run-time property. Populates the cell with COLUMN and ROW coordinates with ITEM Example: $grid->cell(0,1,'x');

cells \@ITEMS

Populates the grid cells with items, filling them row by row. Example: # this grid has two rows and three columns $grid->cells([ [qw(x y z)], [qw(z y x)], ]),

columns NUMBER

A read-only property; returns the number of columns.

rows NUMBER

A read-only property; returns the number of rows.

Methods

add_column @ITEMS

Accepts an array of strings (or list) representing a single column. Appends the column to the end of the existing columns. Example: add_column('Row 1 Col 3', 'Row 2 Col 3', 'Row 3 Col 3');

add_columns \@ITEMS, [\@ITEMS, ...]

Accepts one or more array references, each representing a single column. Appends the columns to the end of the existing columns. Example: add_columns(['Row 1 Col 3', 'Row 2 Col 3'], ['Row 1 Col 4', 'Row 2 Col 4']);

add_row @ITEMS

Accepts an array of strings (or list) representing a single row. Appends the row to the end of the existing rows. Example: add_row('Row 2 Col 1', 'Row 2 Col 2', 'Row 2 Col 3');

add_rows \@ITEMS, [\@ITEMS, ...]

Accepts one or more array references, each representing a single row. Appends the rows to the end of the existing rows. Example: add_rows(['Row 2 Col 1', 'Row 2 Col 2'], ['Row 3 Col 1', 'Row 3 Col 2']);

delete_columns OFFSET, COUNT

Removes COUNT columns starting from OFFSET (= index of the first column to remove). Negative OFFSET values are accepted. Example: # removes the second column delete_columns(1, 1);

delete_rows OFFSET, COUNT

Removes COUNT rows starting from OFFSET (= index of the first row to remove). Negative OFFSET values are accepted. Example: # removes the second row delete_rows(1, 1);

insert_column OFFSET, @ITEMS

Inserts an array of strings (or list) representing a single column in column OFFSET. Negative OFFSET values are accepted. Example: my @ITEMS = qw(a b c); # inserts @ITEMS as the first column insert_column(0, @ITEMS);

insert_columns OFFSET \@ITEMS, [\@ITEMS, ...]

Accepts one or more array references, each representing a single column. Inserts the columns in column OFFSET. Negative OFFSET values are accepted. Example: # inserts two columns starting at index 1 insert_columns(1, ['Row 1 Col 3', 'Row 2 Col 3'], ['Row 1 Col 4', 'Row 2 Col 4']);

insert_row OFFSET, @ITEMS

Inserts an array of strings (or list) representing a single row in row OFFSET. Negative OFFSET values are accepted. Example: my @ITEMS = qw(a b c); # inserts @ITEMS as the first row insert_row(0, @ITEMS);

insert_rows OFFSET \@ITEMS, [\@ITEMS, ...]

Accepts one or more array references, each representing a single row. Inserts the rows in row OFFSET. Negative OFFSET values are accepted. Example: # inserts two rows at the beginning (index 0) insert_rows(0, ['Row 2 Col 1', 'Row 2 Col 2'], ['Row 3 Col 1', 'Row 3 Col 2']);

Prima::Grid

Descendant of Prima::GridViewer, declares format of cell data as a single text string. Provides the standard text grid widget that has all the functionality of its ascendants.

Methods

get_cell_alignment COLUMN, ROW

Returns two ta:: constants for horizontal and vertical cell text alignment. Since the item storage organization is implemented, does so without calling the GetAlignment notification.

get_cell_text COLUMN, ROW

Returns text string assigned to the cell in COLUMN and ROW. Since the item storage organization is implemented, does so without calling the Stringify notification.

AUTHOR

Dmitry Karasik, <dmitry@karasik.eu.org>.

SEE ALSO

Prima, Prima::Widget, examples/grid.pl