PBToolboxAI v5 ← Site

gauge — u_pbt_gauge #

← Component reference · Guide contents

Linear gauge: one value read along a straight scale, horizontal or vertical — a bar or a marker, coloured ranges that say whether it is good, a target, a readout in the format of your choice.

▶ See it live — Demo application, Linear gauge tile: the preview, the code behind it and this page, side by side.


In brief #

Userobjectu_pbt_gauge
Item classn_pbt_gauge_range (of_range(key))
Used forReading a quantity at a glance — how full a disk is, the month's sales against their goal, the level of a tank, a volume slider
PrincipleYou give a scale, a value and ranges; the graduations, the numbers, the colours and the animation are ours
FamilyTwin of angulargauge: same methods, same events, and the same properties apart from the geometry — here the orientation and the placement of the ranges, there the angles and the round ends

Quick start #

// Three ranges of the scale, each with the tone of what it means
uo_gauge.of_add_range(/*key*/ "ok", /*from*/ 0, /*to*/ 70)
uo_gauge.of_add_range(/*key*/ "warn", /*from*/ 70, /*to*/ 90)
uo_gauge.of_add_range(/*key*/ "full", /*from*/ 90, /*to*/ 100)
uo_gauge.of_range(/*key*/ "ok").is_tone = u_pbt_gauge.TONE_SUCCESS
uo_gauge.of_range(/*key*/ "warn").is_tone = u_pbt_gauge.TONE_WARN
uo_gauge.of_range(/*key*/ "full").is_tone = u_pbt_gauge.TONE_DANGER

// The title, the unit, and the value : the bar slides to it
uo_gauge.is_title = "Disk usage"
uo_gauge.is_unit = "%"
uo_gauge.id_value = 64

The scale, the value and the ranges #

The scale runs from id_minimum to id_maximum (0 to 100 by default). The value id_value reads back as you gave it: outside the scale it is drawn pegged at the nearest end and the readout still writes it — a gauge that silently rewrote what the application measured would lie twice. Set by the code it raises no event, like SetItem: ue_value_changed says what the user did. NULL is ignored: the previous value stays — test a measure that may be missing (GetItemNumber returns NULL) before you set it.

The numbers follow is_format, the display format of a DataWindow (#,##0.0, $#,##0, 0% writes the PART of the scale — 50 on 0..200 reads 25%, as the progress bar does), with the separators of the display language. Without a format, the scale chooses the decimals of the readout — two for a scale of 0 to 1, none for 0 to 100 —, never the value, which would write 43 one second and 42.55 the next; the numbers of the scale take those of their step.

A range colours a portion of the scale: its colour is the one you give, otherwise that of its tone (TONE_SUCCESS, TONE_WARN, TONE_DANGER, TONE_INFO = the theme accent, TONE_NEUTRAL — one set of colours per light or dark mode), otherwise that of the palette. Ranges overlap in the order they were added; of_current_range() says which one the value is in. They are drawn along the track, under the bar. A range holds its start but not its end: on the end two ranges share (60 between 0–60 and 60–85), the value is in the one that starts there, whatever the order of the adds; the end of the scale belongs to the range that reaches it. The palette colour of a range is fixed when it is added: removing one recolours no other. A range entirely outside the scale is not drawn.


Properties #

PropertyTypeDefaultRole
is_titlestring""The title, at the start of the line of the readout. Markup accepted; it also names the component for a screen reader. Without a title, the plain text of the tooltip names it (is_super_tooltip_title, else is_tooltip), else the word “Gauge” in the display language
id_valuedouble0The value. It slides to its place; outside the scale, drawn pegged and read back as given. Set by the code, silent; NULL is ignored, the previous value stays
id_minimumdouble0The start of the scale. A scale whose minimum is not below its maximum is empty: no graduation, no number, no range, no pointer and no target, and of_current_range() gives an empty string. To turn a scale round, ib_reversed
id_maximumdouble100The end of the scale
is_formatstring""The display format of every number — readout, scale, ends of a range —, in the syntax of a DataWindow format (#,##0.00, $#,##0, 0%), separators of the display language. Empty = the readout takes the decimals of the scale (two for 0 to 1, none for 0 to 100), the numbers of the scale those of their step (0.0, 0.2… 1.0)
is_unitstring""Written after the value in the readout (%, km/h)
ib_show_valuebooleantrueShows the readout — the value and its unit — at the end of the line of the title
id_tick_stepdouble0The step between two numbered graduations. 0 = chosen by the scale: a nice step (1, 2, 2.5 or 5 times a power of ten, then 3, 4.5 or 6) that falls on both ends when one does — 0 to 90 by 10, −50 to 50 by 25, 0 to 360 by 60 —, otherwise counted from the minimum (32 to 212 by 20). A step you give is always counted from the minimum; a step that would draw more than 200 graduations falls back on the automatic one. Each end carries a numbered graduation. When the numbers do not all fit, one in k is written so the step stays regular, and both ends are always written. The numbers take the decimals of their step. The step chosen is never finer than what is_format writes (0 to 3 at #,##0: 0, 1, 2, 3); a step you give stays yours, and the format rounds its numbers
ii_minor_ticksinteger4Small graduations between two numbered ones (0 to 9)
ib_show_ticksbooleantrueShows the graduations
ib_show_labelsbooleantrueShows the numbers of the scale
id_targetdouble0A target — a goal, a threshold —, marked across the track while ib_show_target is true
ib_show_targetbooleanfalseShows the mark of id_target
is_pointerstringbarHow the value is shown (constants POINTER_*): BAR, a bar filled from the minimum; MARKER, a triangle beside the track. Unknown = BAR
il_value_colorlong-1The colour of the value — the bar or the marker; -1 = the theme accent
il_track_colorlong-1The colour of the track; -1 = a tint of the text colour of the theme
ii_thicknessinteger0The thickness of the track, in pixels (0 to 80); 0 = automatic: 14 for a bar, 8 for a marker
ib_reversedbooleanfalseThe maximum at the start of the scale: on the left of a horizontal gauge (on the right in a right-to-left reading), at the bottom of a vertical one. The arrows still move the pointer the way they point
is_orientationstringhorizontalThe direction of the scale (constants ORIENTATION_*). A horizontal scale follows the reading direction: right to left, its minimum is on the right — the Right key still moves the pointer to the right. Unknown = HORIZONTAL
ib_editablebooleanfalseThe user moves the value: drag the bar, click the scale, arrows, Page Up / Down (ten steps), Home and End. The arrows follow the screen: Right moves the value to the right, Up moves it up, whatever turned the scale round (right-to-left, ib_reversed). Each gesture raises ue_value_changed once — a key, like the hand, puts the value at once, and a drag cut short (a message box, Alt+Tab) ends like a release; Escape during a drag gives the value back (a value your code wrote meanwhile stays) without pressing the window's Cancel button; the Menu key names the range the value is in
id_stepdouble0The step of the hand and of the keys; 0 = the precision the readout shows (the decimals of is_format, or those the scale chooses): on a scale of 0 to 7 the hand gives 2.6, never a 2.61 the user did not read; a key moves by a hundredth of the scale, never less than one shown digit. Both ends stay reachable when the step does not divide the scale: from 0 to 100 by 30, the value goes 0, 30, 60, 90, 100
ib_track_dragbooleanfalseWith ib_editable, opt-in: while the user drags the value, ue_value_tracking follows the hand — a volume heard live, a preview redrawn. ue_value_changed still comes once, when the hand lets go; when a drag is cut short (Escape, ib_editable or ib_enabled set to false by the code), ue_value_tracking also says the value it started from
ib_value_tooltipbooleantrueThe panel that names the range under the pointer, with its ends. It is not is_tooltip, the tooltip of the whole component. The tooltip of a range (its is_tooltip) is written in this panel, even at false
ib_pointer_tooltipbooleanfalseOpt-in: the panel also names the value under the mouse — on the bar or the marker — and the target, with their number in the format of the readout. The ranges keep their own panel (ib_value_tooltip)
ib_value_follows_rangebooleanfalseOpt-in: the value — the bar or the marker — takes the colour of the range it is in (the one drawn on top where two overlap): red in the red zone. Outside every range it keeps il_value_color, else the theme accent. While the value slides, the colour follows the value drawn
id_origindouble0Where the bar starts (POINTER_BAR): a value below the origin grows the other way — a gap, a variance, a scale of −50 to 50 that starts at 0. Until it is set — or once set back to NULL — the bar starts at the minimum and follows it, and the property reads the minimum; outside the scale, at the nearest end
is_range_placementstringbesideWhere the ranges are drawn (constants PLACEMENT_*): beside, a band of their own along the track; behind, they fill the track, lighter, and a thinner bar runs over them with the target across — the bullet graph of a dashboard. Unknown = beside, and reads back as such. Behind, the bar keeps a thin edge in the colour of the page: a red bar stays seen on its own red band; the lighter bands are a decoration, the range is read in the panel and by a screen reader
ib_auto_heightbooleanfalseThe component reports its ideal height and the userobject fits it (ue_auto_height). A horizontal gauge says what it draws, title included. A vertical gauge reports nothing: turned from horizontal to vertical, the userobject keeps the last height reported
ib_enabledbooleantrueGreyed out, it keeps showing its value but stops answering: no click, no key, no drag, and it leaves the Tab order
ib_animatedbooleantrueThe value slides to its place, frame by frame — the bar grows —, and arrives from the start of the scale (its minimum) when the component is drawn. A setting changed during the slide (title, unit, colour, size) does not cut it. A workstation set to reduce motion never animates; the user's hand is never animated; a value set under of_set_redraw(false) slides when drawing resumes
ii_anim_durationinteger450Duration of the slide, in milliseconds (0 to 5000)
is_anim_easingstringease-outThe curve of the slide (constants EASING_*, the names of LiveCharts2): back-out goes past then comes back, bounce-out bounces, elastic-out snaps. An overshoot stays on the scale. Unknown = ease-out
is_theme_stylestring""Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change
is_theme_modestring""Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change
il_theme_accentlong-1Accent colour of this component (-1 = the theme's accent)
is_tooltipstring""Plain tooltip shown when hovering the component
is_super_tooltip_titlestring""Title of the rich tooltip (takes precedence over is_tooltip)
is_super_tooltip_textstring""Text of the rich tooltip (rich markup accepted)
is_super_tooltip_imagestring""Image of the rich tooltip

Methods #

MethodRole
of_add_range ( string as_key, double ad_from, double ad_to { , long al_color } )Adds a coloured range from ad_from to ad_to (ends written backwards are drawn the right way round); the overload with a colour sets it, otherwise the tone then the palette. Returns 0 once added, -5 when the key is empty, holds / or `, or is already held (an add never replaces), -2` when the component is not created. The palette colour is given at the add: removing a range recolours no other one
of_clear_ranges ( )Removes every range — their handles go with them —, the value and the settings stay. Returns 0 once done, -2 when the component is not created
of_current_range ( )The key of the range the value is in right now, an empty string when it is in none or when the scale is empty. Where two ranges overlap, the last one added — the one drawn on top — wins. A hidden range is not counted; a range the demo mode does not draw is: what this reads never depends on the licence. A range holds its start but not its end: on the end two ranges share, the value is in the one that starts there, whatever the order of the adds; the end of the scale belongs to the range that reaches it. A range outside the scale (not drawn) counts too
of_range ( string as_key )The n_pbt_gauge_range handle of a range, to read or change its ends, colour, tone, name or visibility
of_remove_range ( string as_key )Removes one range; its handle is destroyed. Returns 0 once removed, -5 when no range has this key, -2 when the component is not created
of_reset ( )Empties the ranges — handles included — and puts every property back to its original value. Returns 0 once done, -2 when the component is not created

Events #

EventRaised when
ue_value_changed (double ad_value)With ib_editable only: the user has moved the value — once per drag (when the button is released, or when the drag is cut short: a message box opened under the hand, Alt+Tab), per click, per key. A value set by your code does not raise it, even during a drag. To follow the hand during the drag: ib_track_drag
ue_value_tracking (double ad_value)With ib_editable and ib_track_drag only, while the user drags the value: each new place of the hand, then — when the drag is cut short: Escape, or ib_editable / ib_enabled set to false by your code — the value it started from. The final value still comes once in ue_value_changed
ue_range_clicked (string as_key)A range was clicked — or confirmed with Enter or Space on the range the keyboard is on (Tab, then the arrows). Not on an editable component: a click there sets the value
ue_range_rclicked (string as_key, long al_x, long al_y)Right-click on a range, or the Menu key (Shift+F10) on the range the keyboard is on — on an editable component, the range the value is in: the place to open a menu; al_x, al_y: where to open the menu, in screen pixels — the pointer, or the middle of the range from the keyboard (Menu key, Shift+F10); a contextmenu opens there as they are (uo_menu.of_show(al_x, al_y))
ue_auto_height (long al_height)With ib_auto_height: the userobject has just been resized to its ideal height

Item properties #

A range is named by its key: uo_gauge.of_range("warn").is_tone = u_pbt_gauge.TONE_WARN.

PropertyTypeDefaultRole
id_fromdouble0The start of the range, on the scale
id_todouble0Its end. Ends written backwards are drawn the right way round and read back as given
il_colorlong-1Its colour; -1 = that of its tone, otherwise of the palette. The inherited item colours (il_accent, il_back_color, il_text_color and their hover twins) have no effect on a range: il_color and is_tone decide
is_tonestring""Its tone (constants TONE_* of the component): SUCCESS, WARN, DANGER, INFO (the theme accent), NEUTRAL — one set per light or dark mode, any case understood. il_color wins; an unknown tone counts as no tone
is_labelstring""Its name, in the panel under the pointer and for a screen reader; empty = its key. Markup accepted
ib_visiblebooleantrueHides the range without removing it; like a check box, raises no event
is_tooltipstring""Its tooltip, written in the panel that names the range under the pointer — never a second bubble. Markup accepted
is_super_tooltip_titlestring""The bold title of its tooltip, written in the panel under its name
is_super_tooltip_textstring""The text of its tooltip, in the panel. Markup accepted
is_super_tooltip_imagestring""An image at the top of its tooltip, in the panel (bundle path, absolute path or resources.dll:name)

Examples #

A live dashboard #

// Local variables
double ld_used

// Timer event of the window : the bar slides to each new reading
ld_used = ids_monitor.GetItemNumber(1, "disk_used")

// A missing reading (NULL) is ignored by the gauge : test it, or the last one stays
if not IsNull(ld_used) then uo_gauge.id_value = ld_used

// Which range is it in now ? An alert outside the good one
st_alert.visible = (uo_gauge.of_current_range() <> "ok")

Sales against their goal #

// Dollars, a number every 50 000, up to 250 000
uo_gauge.id_maximum = 250000
uo_gauge.id_tick_step = 50000
uo_gauge.is_format = "$#,##0"

// The goal : a mark across the bar
uo_gauge.id_target = 200000
uo_gauge.ib_show_target = true

// Point at the bar or at the goal : the panel says its number
uo_gauge.ib_pointer_tooltip = true
uo_gauge.id_value = 168400

A dashboard bullet graph #

// Dollars in thousands, on a scale up to 300
uo_gauge.is_format = "$#,##0k"
uo_gauge.id_maximum = 300

// Three qualitative zones : poor, satisfactory, good
uo_gauge.of_add_range(/*key*/ "poor", /*from*/ 0, /*to*/ 150)
uo_gauge.of_add_range(/*key*/ "fair", /*from*/ 150, /*to*/ 225)
uo_gauge.of_add_range(/*key*/ "good", /*from*/ 225, /*to*/ 300)
uo_gauge.of_range(/*key*/ "poor").is_tone = u_pbt_gauge.TONE_DANGER
uo_gauge.of_range(/*key*/ "fair").is_tone = u_pbt_gauge.TONE_WARN
uo_gauge.of_range(/*key*/ "good").is_tone = u_pbt_gauge.TONE_SUCCESS

// The zones BEHIND a thinner bar, the plan across it
uo_gauge.is_range_placement = u_pbt_gauge.PLACEMENT_BEHIND
uo_gauge.id_target = 250
uo_gauge.ib_show_target = true

// The bar takes the colour of the zone it is in
uo_gauge.ib_value_follows_range = true
uo_gauge.id_value = 212

A gap to a budget #

// A scale centred on zero : the bar starts at 0, to the left below it
uo_gauge.id_minimum = -50
uo_gauge.id_maximum = 50
uo_gauge.id_origin = 0
uo_gauge.id_value = -18

A value the user sets #

// The user moves the value, by steps of 5
uo_gauge.ib_editable = true
uo_gauge.id_step = 5

// Event ue_value_changed of uo_gauge : apply what the user chose
ii_level = Integer(ad_value)

A volume set live #

// The user drags the value, and the sound follows the hand
uo_gauge.ib_editable = true
uo_gauge.ib_track_drag = true

// Event ue_value_tracking of uo_gauge : the volume heard while the hand moves
inv_player.ii_volume = Integer(ad_value)

// Event ue_value_changed of uo_gauge : the volume kept when the hand lets go
ii_saved_volume = Integer(ad_value)

A menu on a range #

// Event ue_range_rclicked of uo_gauge : remember the range, then open the menu
// at the pointer of the window
is_menu_range = as_key
m_range.PopMenu(/*xlocation*/ w_main.PointerX(), /*ylocation*/ w_main.PointerY())

Good practice #


Inherited from the common base #

These members exist on every visual component — they are not specific to this one. They are detailed once, in the transverse chapters; this table only says where to read them.

MembersRoleDetailed in
of_count · of_keys_at · of_hasWalk what the component holds3.2 Items
of_resetPut the component back to zero3.6 Resetting a component: of_reset()
of_register_shortcut · of_clear_shortcutsThe component's keyboard chords3.5 Keyboard shortcuts
of_is_created · of_is_ready · of_get_last_errorWhether it was born, whether it is ready, what failed3.7 Diagnostics
of_save_as_png · of_save_as_jpgExport the rendering as an image3.8 Exporting the rendering as an image
of_set_redrawGroup changes into a single repaint3.10 Best practices
of_preload_iconsIcons shown with no delayInstant display: of_icon
of_set_translationTranslate one of the component's labels5.2 Adapting a label: of_set_translation
of_focus_webviewGive the component the focus6.4 Keyboard and focus
of_print · of_print_to_pdfPrint, or write a PDF6.9 Printing
of_set_property · of_get_property · of_component_nameDriving a property by its name3.1 The property engine
is_accessible_name · is_accessible_descriptionThe name and description a screen reader says3.4 Optional properties and events

Two helpers are not inherited: of_icon and of_escape_markup live on n_pbt_utils. Declare one — n_pbt_utils lnv_utils, nothing to create — and call them on it.

← Component reference · Guide contents