-
Notifications
You must be signed in to change notification settings - Fork 46
High level drawing api
The graphics specific modules provide a high level interface to the
GtkDrawingArea widget which is compatible with the plplot
library and
at least in simple cases relieves the user of the hassle of managing
redraws. There is also a high level interface to the gdk-pixbuf library
that allows the easy mapping of 2 and 3 dimensional Fortran arrays to
GdkPixbuf objects.
This module provides a high-level drawing interface which automatically handles redrawing on exposure, and bundles the most likely events to be needed.
Note:
This module has undergone a major rewrite which has considerably streamlined the code. To the ordinary user, the most noticable difference is that the backing image is now a cairo image surface rather than a GDK pixbuf. When using PLplot, the "memcairo" device is not readily usable any more, however cumulative plotting (e.g. PLplot's strip charts) now works correctly.
- hl_gtk_drawing_area_new; Create the drawing area.
- hl_gtk_drawing_area_get_surface; Get the backing cairo surface
- hl_gtk_drawing_area_expose_cb; Default callback for expose events.
- hl_gtk_drawing_area_destroy_cb; Default callback for destroy signal
- hl_gtk_drawing_area_resize_cb; Default callback for size-allocate signal
- hl_gtk_drawing_area_cairo_new; Create a cairo context attached to the backing surface.
- hl_gtk_drawing_area_resize: Resize the drawing area and the backing surface
- hl_gtk_drawing_area_cairo_destroy; Destroy the context.
function hl_gtk_drawing_area_new(scroll, size, ssize, expose_event, &
& data_expose, button_press_event, data_button_press, &
& button_release_event, data_button_release, scroll_event, &
& data_scroll, motion_event, data_motion, realize, data_realize, &
& configure_event, data_configure, key_press_event, data_key_press, &
& key_release_event, data_key_release, enter_event, data_enter, &
& leave_event, data_leave, destroy, data_destroy, event_mask, &
& event_exclude, auto_add_mask, &
& tooltip, has_alpha, size_allocate, data_size_allocate) result(plota)
type(c_ptr) :: plota
type(c_ptr), intent(out), optional :: scroll
integer(kind=c_int), intent(in), optional, dimension(2) :: size, ssize
type(c_funptr), optional :: expose_event, button_press_event, &
& button_release_event, scroll_event, key_press_event, &
& key_release_event, motion_event, realize, configure_event,&
& enter_event, leave_event, destroy, size_allocate
type(c_ptr), intent(in), optional :: data_expose, data_button_press, &
& data_button_release, data_scroll, data_motion, data_realize, &
& data_configure, data_key_press, data_key_release, data_enter, &
& data_leave, data_destroy, data_size_allocate
integer(kind=c_int), intent(in), optional :: event_mask, event_exclude
integer(kind=c_int), intent(in), optional :: auto_add_mask
character(kind=c_char), dimension(*), optional, intent(in) :: tooltip
integer(kind=c_int), intent(in), optional :: has_alpha
A high-level drawing area
Argument | Type | Required? | Description |
---|---|---|---|
SCROLL | c_ptr | optional | If present, then the drawing area will be placed in a scrollable window, whose pointer will be returned here. If it is present, then it rather than the drawable should be used for packing. |
SIZE | c_int() | optional | The requested size for the area. If no size is given then a default size of 256x256 is used. |
SSIZE | c_int() : | optional | The requested size for a scrolling window |
EXPOSE_EVENT | c_funptr | optional | Callback for expose-event signal N.B. In GTK3 the signal is called "draw". If this is not given then a default handler is provided which copies the image surface to the drawing area. |
DATA_EXPOSE | c_ptr | optional | Data for expose_event callback |
BUTTON_PRESS_EVENT | c_funptr | optional | Callback for button-press-event signal |
DATA_BUTTON_PRESS | c_ptr | optional | Data for button_press_event callback |
BUTTON_RELEASE_EVENT | c_funptr | optional | Callback for button-release-event signal |
DATA_BUTTON_RELEASE | c_ptr | optional | Data for button_release_event callback |
SCROLL_EVENT | c_funptr | optional | Callback for scroll-event signal |
DATA_SCROLL | c_ptr | optional | Data for scroll_event callback |
REALIZE | c_funptr | optional | Callback for realize signal |
DATA_REALIZE | c_ptr | optional | Data for realize callback |
CONFIGURE_EVENT | c_funptr | optional | Callback for configure-event signal |
DATA_CONFIGURE | c_ptr | optional | Data for configure_event callback |
KEY_PRESS_EVENT | c_funptr | optional | Callback for key-press-event signal |
DATA_KEY_PRESS | c_ptr | optional | Data for key_press_event callback |
KEY_RELEASE_EVENT | c_funptr | optional | Callback for key-release-event signal |
DATA_KEY_RELEASE | c_ptr | optional | Data for key_release_event callback |
MOTION_EVENT | c_funptr | optional | Callback for the motion-notify-event signal |
DATA_MOTION | c_ptr | optional | Data for motion_event |
ENTER_EVENT | c_funptr | optional | Callback for the enter-notify-event signal |
DATA_ENTER | c_ptr | optional | Data for enter_event |
LEAVE_EVENT | c_funptr | optional | Callback for the leave-notify-event signal |
DATA_LEAVE | c_ptr | optional | Data for leave_event |
DESTROY | c_funptr | optional | Callback when the widget is destroyed. |
DATA_DESTROY | c_ptr | optional | Data to pass to the destroy callback. |
EVENT_MASK | c_int | optional | Mask for which events to pass. |
EVENT_EXCLUDE | c_int | optional | Mask for events not to pass (this might be used to prevent auto-enabling an event that should only be enabled by user actions) |
AUTO_ADD_MASK | boolean | optional | Set to FALSE to disable automatically adding events to the event mask if a handler is provided. |
TOOLTIP | string | optional | Tooltip for the drawing area. |
HAS_ALPHA | boolean | optional | If a pixbuf is used, should it have an alpha (transparency) channel (default=FALSE) |
SIZE_ALLOCATE | c_funptr | optional | Callback for the 'size-allocate' signal |
DATA_SIZE_ALLOCATE | c_ptr | optional | Data for size_allocate. |
Odd notes on mask interactions and other things.
- Scroll (wheel) events, are enabled by GDK_SCROLL_MASK or GDK_BUTTON_PRESS_MASK, thus (as far as I can see) there is no way to mask wheel events while allowing button presses to be processed.
- It does not appear to be possible to remove events by unsetting bits in the event mask.
- Adding a tooltip looks to implicitly enable some events.
- An example where an explict EVENT_MASK and EVENT_EXCLUDE might be useful would be to enable motion events only if a button is down.
- If an explicit size is given then the drawing area cannot be made smaller than that by resizing the containing window
function hl_gtk_drawing_area_get_surface(area) result(isurface)
type(c_ptr) :: isurface
type(c_ptr), intent(in) :: area
Convenience routine to get the backing surface of a drawing area.
Argument | Type | Required? | Description |
---|---|---|---|
AREA | c_ptr | required | The drawing area whose surface is required. |
function hl_gtk_drawing_area_expose_cb(area, event, data) bind(c) &
& result(rv)
integer(kind=c_int) :: rv
type(c_ptr), value :: area, event, data
Default callback for exposing a drawing area. For this to be connected no explicit expose callback should be specified.
Argument | Type | Required? | Description |
---|---|---|---|
AREA | c_ptr | required | The drawing area |
EVENT | c_ptr | required | GTK2 = event structure, GTK3 = a cairo context Since this differs between versions, we won't use it. |
DATA | c_ptr | required | A pointer to user data (not used). |
subroutine hl_gtk_drawing_area_destroy_cb(area, data) bind(c)
type(c_ptr), value :: area, data
Default callback for the destroy signal on the drawing area. Just destroys the backing surface.
Argument | Type | Required? | Description |
---|---|---|---|
AREA | c_ptr | required | The drawing area being destroyed. |
DATA | c_ptr | required | User data for the callback (not used) |
subroutine hl_gtk_drawing_area_resize_cb(area, data) bind(c)
type(c_ptr), value :: area, data
Default call back for resizing the drawing area, just copies the old backing store to the new one
Argument | Type | Required? | Description |
---|---|---|---|
AREA | c_ptr | required | The drawing area being destroyed. |
DATA | c_ptr | required | User data for the callback (not used) |
function hl_gtk_drawing_area_cairo_new(area) result(cr)
type(c_ptr) :: cr
type(c_ptr), intent(in) :: area
Create a cairo context which will draw into the backing surface
Argument | Type | Required? | Description |
---|---|---|---|
AREA | c_ptr | required | The drawing area to which we will draw.
After the drawing operations, you should call |
subroutine hl_gtk_drawing_area_cairo_destroy(cr, destroy_surface)
type(c_ptr), intent(inout) :: cr
integer(kind=c_int), intent(in), optional :: destroy_surface
Update the backing surface and destroy the cairo context
Argument | Type | Required? | Description |
---|---|---|---|
CR | c_ptr | required | The cairo context to put in the pixbuf |
DESTROY_SURFACE | boolean | optional | Set to TRUE to destroy the cairo_surface as well as the context. Normally the cairo surface is destroyed by the destroy callback of the drawing area, so does not need to be explicitly destroyed. |
This is called following drawing operations to the context created by
hl_gtk_drawing_area_cairo_new
. N.B. This does not update the window,
use gtk_widget_queue_draw to do that.
subroutine hl_gtk_drawing_area_resize(area, size, copy)
type(c_ptr), intent(in) :: area
integer(kind=c_int), intent(in), optional, dimension(2) :: size
logical, optional, intent(in) :: copy
Resize a drawing area and its backing store.
Argument | Type | Required? | Description |
---|---|---|---|
AREA | c_ptr | required | The area to resize. |
SIZE | int(2) | optional | The new size, if omitted, then the backing store is resized to match the drawing area (e.g. after resizing the containing window). |
Some routines to facilitate the use of GDK pixbufs from Fortran. Allows the use of short-int images to avoid the issues that may result from Fortran's 8-bit integers being signed while GdkPixbuf pixels are unsigned.
function hl_gdk_pixbuf_new_empty(width, height, alpha, bits) &
& result(pixbuf)
type(c_ptr) :: pixbuf
integer(kind=c_int), intent(in) :: width, height
integer(kind=c_int), intent(in), optional :: alpha, bits
Create a new empty pixbuf of the given size
Argument | Type | Required? | Description |
---|---|---|---|
WIDTH | int | required | The width in pixels of the pixbuf |
HEIGHT | int | required | The height in pixels of the pixbuf |
ALPHA | boolean | optional | Whether to include an alpha channel (default=FALSE) |
BITS | int | optional | The nuber of bits per sample (default=8). |
This routine will usually be called via the generic interface hl_gdk_pixbuf_new.
function hl_gdk_pixbuf_new_file(file, width, height, aspect, &
& error) result(pixbuf)
type(c_ptr) :: pixbuf
character(len=*), intent(in) :: file
integer(kind=c_int), optional, intent(in) :: width, height, aspect
character(len=*), optional, intent(out) :: error
Read an image file into a new pixbuf
Argument | Type | Required? | Description |
---|---|---|---|
FILE | string | required | The file to read |
WIDTH | int | optional | The desired width for the pixbuf |
HEIGHT | int | optional | The desired height for the pixbuf |
ASPECT | boolean | optional | If sizing is given then set to TRUE to preserve the aspect ratio, or FALSE not to. If both dimensions are given, then the default is FALSE, if one is given, the default is TRUE. |
ERROR | gerror | optional | The error code & message. |
This routine will usually be called via the generic interface hl_gdk_pixbuf_new.
function hl_gdk_pixbuf_new_data8(data) result(pixbuf)
type(c_ptr) :: pixbuf
integer(kind=c_int8_t), dimension(:,:,:), intent(in) :: data
Create a pixbuf from an RGB(A) array of values.
Argument | Type | Required? | Description |
---|---|---|---|
DATA | int8 | required | The data values as a 1..4 x n x m array. |
This routine will usually be called via the generic interface hl_gdk_pixbuf_new.
function hl_gdk_pixbuf_new_data8g(data) result(pixbuf)
type(c_ptr) :: pixbuf
integer(kind=c_int8_t), dimension(:,:), intent(in) :: data
Create a pixbuf from a greyscale array of values.
Argument | Type | Required? | Description |
---|---|---|---|
DATA | int8 | required | The data values as a n x m array. |
This routine will usually be called via the generic interface hl_gdk_pixbuf_new.
function hl_gdk_pixbuf_new_data16(data) result(pixbuf)
type(c_ptr) :: pixbuf
integer(kind=c_short), dimension(:,:,:), intent(in) :: data
Create a pixbuf from an RGB(A) array of values. This version uses 2-byte integers to avoid the signing issues of the c_int8_t type.
Argument | Type | Required? | Description |
---|---|---|---|
DATA | short | required | The data values as a 1..4 x n x m array. |
This routine will usually be called via the generic interface hl_gdk_pixbuf_new.
function hl_gdk_pixbuf_new_data16g(data) result(pixbuf)
type(c_ptr) :: pixbuf
integer(kind=c_short), dimension(:,:), intent(in) :: data
Create a pixbuf from a greyscale array of values. This version uses 2-byte integers to avoid the signing issues of the c_int8_t type.
Argument | Type | Required? | Description |
---|---|---|---|
DATA | short | required | The data values as a n x m array. |
This routine will usually be called via the generic interface hl_gdk_pixbuf_new.
subroutine hl_gdk_pixbuf_get_pixels8(pixbuf, pixels)
type(c_ptr), intent(in) :: pixbuf
integer(kind=c_int8_t), dimension(:,:,:), allocatable, intent(out) :: pixels
Get the pixels of a pixbuf and return them as a Fortran 3xnxm or 4xnxm array
Argument | Type | Required? | Description |
---|---|---|---|
PIXBUF | c_ptr | required | The pixbuf to read |
PIXELS | int8 | required | Will contain the image. |
This is normally called via the generic hl_gdk_pixbuf_get_pixels interface. Implemented as a subroutine to allow this.
subroutine hl_gdk_pixbuf_get_pixels16(pixbuf, pixels)
type(c_ptr), intent(in) :: pixbuf
integer(kind=c_short), dimension(:,:,:), allocatable, intent(out) :: pixels
Get the pixels of a pixbuf and return them as a Fortran 3xnxm or 4xnxm array. This version returns as a short array to evade the signing issues of 8-bit integers in Fortran
Argument | Type | Required? | Description |
---|---|---|---|
PIXBUF | c_ptr | required | The pixbuf to read |
PIXELS | short | required | Will contain the image. |
This is normally called via the generic hl_gdk_pixbuf_get_pixels interface. Implemented as a subroutine to allow this.
subroutine hl_gdk_pixbuf_set_pixels8(pixbuf, pixels, xoff, yoff)
type(c_ptr), intent(in) :: pixbuf
integer(kind=c_int8_t), dimension(:,:,:), intent(in) :: pixels
integer, intent(in), optional :: xoff, yoff
Set the pixels of a pixbuf from a Fortran array.
Argument | Type | Required? | Description |
---|---|---|---|
PIXBUF | c_ptr | required | The pixbuf to update |
PIXELS | int8 | required | Contains the image to insert. |
XOFF | int | optional | The X-offset at which to write the image. |
YOFF | int | optional | The Y-offset at which to write the image. |
This is normally called via the generic hl_gdk_pixbuf_set_pixels interface. N.B. To leave a gap at the "high" sides of the pixbuf, just use a smaller input array or array slice than the pixbuf size.
subroutine hl_gdk_pixbuf_set_pixels8g(pixbuf, pixels, xoff, yoff)
type(c_ptr), intent(in) :: pixbuf
integer(kind=c_int8_t), dimension(:,:), intent(in) :: pixels
integer, intent(in), optional :: xoff, yoff
Set the pixels of a pixbuf from a Fortran array (greyscale).
Argument | Type | Required? | Description |
---|---|---|---|
PIXBUF | c_ptr | required | The pixbuf to update |
PIXELS | int8 | required | Contains the image to insert. |
XOFF | int | optional | The X-offset at which to write the image. |
YOFF | int | optional | The Y-offset at which to write the image. |
This is normally called via the generic hl_gdk_pixbuf_set_pixels interface. N.B. To leave a gap at the "high" sides of the pixbuf, just use a smaller input array or array slice than the pixbuf size.
subroutine hl_gdk_pixbuf_set_pixels16(pixbuf, pixels, xoff, yoff)
type(c_ptr), intent(in) :: pixbuf
integer(kind=c_short), dimension(:,:,:), intent(in) :: pixels
integer, intent(in), optional :: xoff, yoff
Set the pixels of a pixbuf from a Fortran array (16-bit).
Argument | Type | Required? | Description |
---|---|---|---|
PIXBUF | c_ptr | required | The pixbuf to update |
PIXELS | short | required | Contains the image to insert. |
XOFF | int | optional | The X-offset at which to write the image. |
YOFF | int | optional | The Y-offset at which to write the image. |
This is normally called via the generic hl_gdk_pixbuf_set_pixels interface. N.B. To leave a gap at the "high" sides of the pixbuf, just use a smaller input array or array slice than the pixbuf size.
subroutine hl_gdk_pixbuf_set_pixels16g(pixbuf, pixels, xoff, yoff)
type(c_ptr), intent(in) :: pixbuf
integer(kind=c_short), dimension(:,:), intent(in) :: pixels
integer, intent(in), optional :: xoff, yoff
Set the pixels of a pixbuf from a Fortran array (16-bit, greyscale).
Argument | Type | Required? | Description |
---|---|---|---|
PIXBUF | c_ptr | required | The pixbuf to update |
PIXELS | short | required | Contains the image to insert. |
XOFF | int | optional | The X-offset at which to write the image. |
YOFF | int | optional | The Y-offset at which to write the image. |
This is normally called via the generic hl_gdk_pixbuf_set_pixels interface. N.B. To leave a gap at the "high" sides of the pixbuf, just use a smaller input array or array slice than the pixbuf size.
subroutine hl_gdk_pixbuf_info(pixbuf, nchannels, bits, alpha, &
& height, width, rowstride)
type(c_ptr), intent(in) :: pixbuf
integer(kind=c_int), optional, intent(out) :: nchannels, bits, alpha, &
& height, width, rowstride
Return information about an existing pixbuf.
Argument | Type | Required? | Description |
---|---|---|---|
PIXBUF | c_ptr | required | The pixbuf to be queried. |
NCHANNELS | int | optional | How many channels does the pixbuf have? |
BITS | int | optional | How many bits per pixel? |
ALPHA | boolean | optional | Does the pixbuf have an alpha channel? |
HEIGHT | int | optional | How many rows in the image. |
WIDTH | int | optional | How many columns in the image. |
ROWSTRIDE | int | optional | How many bytes between the start of successive rows. |
subroutine hl_gdk_pixbuf_get_formats(names, writable, description, &
& scalable, license)
character(len=*), intent(out), dimension(:), allocatable :: names
logical, intent(out), dimension(:), allocatable, optional :: writable, &
& scalable
character(len=*), intent(out), dimension(:), allocatable, &
& optional :: license
character(len=*), intent(out), dimension(:), allocatable, &
& optional :: description
Get information about the available file formats for reading/writing pixbufs.
Argument | Type | Required? | Description |
---|---|---|---|
NAMES | f_string() | required | The names found |
WRITABLE | logical() | optional | Whether the formats are writable. |
DESCRIPTION | f_string() | optional | Descriptions of the formats. |
SCALABLE | logical() | optional | Whether the formats are scalable. |
LICENSE | f_string() | optional | The licence of the format module. |
function hl_gdk_pixbuf_format_info(name, mime_types, extensions, &
& writable, scalable, description, license) result(found)
logical :: found
character(len=*), intent(in) :: name
character(len=*), intent(out), optional, allocatable, &
& dimension(:) :: mime_types, extensions
logical, intent(out), optional :: writable, scalable
character(len=*), intent(out), optional :: description, license
Get information about a specific file type.
Argument | Type | Required? | Description |
---|---|---|---|
NAME | string | required | The file type to query. |
MIME_TYPE | fstring() | optional | Will contain a list of mime-types associated with this file type. |
EXTENSIONS | fstring() | optional | Will contain a list of file extensions normally used for this type. |
WRITABLE | logical | optional | Whether the type is writable. |
SCALABLE | logical | optional | Whether the type is scalable. |
DESCRIPTION | f_string | optional | A description of the file type. |
LICENSE | f_string | optional | The license of the module for the file type. |
Returns .true. if the type is found, .false. if it is not.
function hl_gdk_pixbuf_format_find(mime_type, extension) result(name)
character(len=hl_gdk_pixbuf_type_len) :: name
character(len=*), intent(in), optional :: mime_type, extension
Find the format type appropriate to a mime_type or a filename extension.
Argument | Type | Required? | Description |
---|---|---|---|
MIME_TYPE | f_string | optional | The mime-type to match. |
EXTENSION | f_string | optional | The file extension to match. |
If no match is found then an empty string is returned. Mime_type has precedence over extension.
- Installation
- My first gtk-fortran application
- Drawing an image in a PNG file (without GUI)
- A program also usable without GUI
- Using Glade3 and gtkf-sketcher (GTK 3)
- Using gtk-fortran as a fpm dependency
- Debugging with GtkInspector
- Learning from examples
- Video tutorials
- How to start my own project from a gtk-fortran example
- git basics
- CMake basics
- Alternatives to CMake
- How to migrate to GTK 4
- How to contribute to gtk-fortran
- How to hack the cfwrapper with other C libraries