PBToolboxAI v1 ← Site

statusbar — u_pbt_statusbar #

← Component reference · Guide contents

Status bar made of panels: rich text, icons, fixed or automatic widths, alignment to the left or to the right, clickable panels, a mini progress bar and colored states.

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


At a glance #

Userobjectu_pbt_statusbar
Item classn_pbt_statusbar_panel (panel)
Used forShowing the state of the application at the bottom of the window: context, progress, discreet alerts
Opt-in options

Quick start #

// window open event
// of_add_panel(id, text, icon, alignment, width)
// empty id = purely informative panel ; width 0 = fitted to the text
uo_statut.of_add_panel(/*id*/ "etat",  /*text*/ "Ready",           /*icon_file*/ "", /*align*/ uo_statut.ALIGN_START,  /*width*/ 0)
uo_statut.of_add_panel(/*id*/ "",      /*text*/ "Line 12, Col 4", /*icon_file*/ "", /*align*/ uo_statut.ALIGN_START,  /*width*/ 0)
uo_statut.of_add_panel(/*id*/ "heure", /*text*/ "12:00",          /*icon_file*/ "", /*align*/ uo_statut.ALIGN_END, /*width*/ 140)
// Update a panel at any time, through its identifier
uo_statut.of_item("etat").is_text = "Saving..."

The model: panels with keys #

The bar is a sequence of panels, added in order. A panel is given an identifier when it is created: that is how you find it later to change its text, its icon or its state.

The identifier is an addressing key, not an interactivity switch:

uo_statut.of_item("etat").is_text = "3 records changed"

See Shared foundation · Items.


Properties #

PropertyTypeDefaultPurpose
ib_show_resize_gripbooleanfalseShows the resize grip in the corner at the end of the bar
is_theme_stylestringfluentVisual style of the component (THEME_STYLE_* constants)
is_theme_modestringlightLight or dark variant (THEME_MODE_* constants)
il_theme_accentlong-1Accent color of this component (-1 = the theme accent)
is_tooltipstring""Simple 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 #

MethodPurpose
of_add_panel (string as_id, string as_text, string as_icon_file, string as_align, integer ai_width)Adds a panel at the end of the bar
of_add_sep ( )Adds a vertical separator line between two groups of panels
of_insert_panel (as_id, as_text, as_icon_file, as_align, ai_width, ai_index)Inserts a panel at a specific position (counted from 0)
of_move_panel (string as_id, integer ai_index)Moves an existing panel to another position
of_remove_panel (string as_id)Removes a single panel; the others keep their state
of_item (string as_id)n_pbt_statusbar_panelReturns the handle to a panel (created on first access)
of_flash_panel (string as_id, string as_text, long al_ms)Shows a message for al_ms milliseconds, then puts the previous text back (al_ms ≤ 0 = 2 seconds)
of_set_panel_menu (string as_id, string as_item_ids[], string as_labels[])Turns the panel into a chooser: clicking it opens a drop-down list, and the choice comes back through ue_panel_menu_clicked. An identifier of - inserts a separator; an empty label falls back to the identifier
of_clear_panel_menu (string as_id)Removes the drop-down list; the panel goes back to the behaviour ib_clickable gives it
of_clear ( )Empties the bar: every panel and every separator
of_reset ( )Empties the bar and resets every property to its default

The arguments of of_add_panel #

ArgumentValuesEffect
as_idfree, or ""Key of the panel, the one you find it by later. Empty = a decorative panel, neither addressable nor clickable
as_texttextContent of the panel. Rich text markup is accepted
as_icon_fileimage path, or ""Icon displayed before the text (accepted forms)
as_alignALIGN_START (default) or ALIGN_ENDSide the panel is pushed toward. Logical values: START = start of the reading direction (left in left-to-right writing). The physical aliases "left" / "right" are still accepted
ai_widthpixels, or 0Fixed width. 0 = the panel fits its content

On a panel — n_pbt_statusbar_panel #

MemberTypeDefaultPurpose
is_textstring""Text of the panel, rich text markup accepted
is_imagestring""Icon of the panel, which can be changed at any time
ib_enabledbooleantruePanel grayed out and not clickable
ib_visiblebooleantruePanel hidden, without being removed from the bar
ii_progressintegerMini progress bar inside the panel, from 0 to 100; a negative value makes it disappear
is_statestring""Semantic state of the panel, which colors it: see the constants below
ib_indeterminatebooleanfalseBar animated without a value, for a task whose duration is unknown. Independent of ii_progress, which stays the exact percentage
ib_clickablebooleanfalseDoes the panel answer the click. Opt-in: a panel stays inert until you ask, while keeping its key — it is driven and carries a tooltip. A panel with a drop-down list is clickable already

State constants #

ConstantValueUse
STATE_NONE""No state: normal appearance
STATE_INFO"info"Information
STATE_WARNING"warning"Warning
STATE_ERROR"error"Error
STATE_SUCCESS"success"Success

As with every property that takes predefined values, use the constant rather than the string:

n_pbt_statusbar_panel lnv_panneau
lnv_panneau = uo_statut.of_item("etat")
lnv_panneau.is_state = lnv_panneau.STATE_WARNING

Events #

EventRaised when
ue_panel_clicked (string as_id)A panel whose identifier is supplied is clicked
ue_panel_double_clicked (string as_id)A clickable panel was double-clicked — the classic shortcut behind Line 12, Col 4 that opens a "Go to line"
ue_panel_rclicked (string as_id, long al_x, long al_y)A panel received a right click. al_x and al_y are screen pixels: pass them straight through to open a context menu where the user aimed
ue_panel_menu_clicked (string as_id, string as_item_id)An entry of a panel drop-down list was picked (see of_set_panel_menu)
ue_ready ( )The component has finished loading; everything sent beforehand has been replayed
ue_runtime_missing ( )The WebView2 runtime is missing: the component stays empty
ue_bg_color (long al_color)The component has computed its theme background color; the userobject has already adopted it (backcolor)

Keyboard #

The bar is a single tab stop: only the panels meant to be clicked enter it, and the arrows walk them.

KeyEffect
ArrowsMove to the previous / next interactive panel, wrapping around; display panels and disabled panels are skipped
Home / EndFirst / last interactive panel
Enter or SpaceTriggers the panel — that is, ue_panel_clicked, or the opening of its dropdown if it has one

A panel that merely displays is not a control: it is neither focusable nor announced as one. A clickable but disabled panel, on the other hand, stays announced as unavailable rather than passing for text. A progress bar announces its value, and an indeterminate one announces none — that absence is the meaning of the word.

The focus survives the rebuild of the bar: it is redrawn on every text change, and without this the focus would drop every second on a bar showing a clock.


Examples #

Fixed widths and automatic widths #

// Width 0 : the panel takes exactly the room its text needs
uo_statut.of_add_panel(/*id*/ "", /*text*/ "Panel fitted to its content", /*icon_file*/ "", /*align*/ uo_statut.ALIGN_START, /*width*/ 0)

// Fixed width in pixels : useful when the text changes often,
// so that the neighboring panels do not move on every update
uo_statut.of_add_panel(/*id*/ "pos", /*text*/ "Line 1, Col 1", /*icon_file*/ "", /*align*/ uo_statut.ALIGN_START, /*width*/ 150)

// A panel pushed to the opposite end
uo_statut.of_add_panel(/*id*/ "heure", /*text*/ "12:00", /*icon_file*/ "", /*align*/ uo_statut.ALIGN_END, /*width*/ 140)

Icons and clickable panels #

// A non-empty identifier makes the panel clickable
uo_statut.of_add_panel(/*id*/ "save", /*text*/ "Saved", /*icon_file*/ "mono:img\save.svg", /*align*/ uo_statut.ALIGN_START, /*width*/ 0)
uo_statut.of_add_sep()   // separator line between two groups of panels
uo_statut.of_add_panel(/*id*/ "conn", /*text*/ "Connected",   /*icon_file*/ "mono:img\plug.svg", /*align*/ uo_statut.ALIGN_START, /*width*/ 0)
uo_statut.of_add_panel(/*id*/ "user", /*text*/ "Guillaume",  /*icon_file*/ "mono:img\user.svg", /*align*/ uo_statut.ALIGN_END, /*width*/ 160)
// ue_panel_clicked event of uo_statut
choose case as_id
    case "conn" ; open(w_parametres_connexion)
    case "user" ; open(w_profil)
end choose

Rich text in a panel #

Panels accept rich text markup: styles, colors and small images right inside the text.

uo_statut.of_add_panel(/*id*/ "", /*text*/ "Welcome [b]to[/b] [accent]PBToolboxAI[/accent]", &
                       /*icon_file*/ "", /*align*/ uo_statut.ALIGN_START, /*width*/ 0)

uo_statut.of_add_panel(/*id*/ "", /*text*/ "[green]Online[/green] [picture=mono:img\plug.svg,14,14]", &
                       /*icon_file*/ "", /*align*/ uo_statut.ALIGN_END, /*width*/ 0)
// Rich text works for updates too
uo_statut.of_item("etat").is_text = "[b]" + String(ll_modifies) + "[/b] records changed"

Following a long operation #

n_pbt_statusbar_panel lnv_avance

uo_statut.of_add_panel(/*id*/ "import", /*text*/ "Import", /*icon_file*/ "", /*align*/ uo_statut.ALIGN_START, /*width*/ 220)
lnv_avance = uo_statut.of_item("import")
// Inside the processing loop : the mini bar follows the progress
lnv_avance.ii_progress = ll_pourcentage
lnv_avance.is_text     = "Import " + String(ll_pourcentage) + " %"
// At the end : hide the mini bar and report the result
lnv_avance.ii_progress = -1                       // negative value = bar hidden
lnv_avance.is_text     = "Import complete"
lnv_avance.is_state    = lnv_avance.STATE_SUCCESS

Raising a discreet alert #

n_pbt_statusbar_panel lnv_panneau
lnv_panneau = uo_statut.of_item("conn")

if not ib_connecte then
    lnv_panneau.is_text  = "Offline"
    lnv_panneau.is_state = lnv_panneau.STATE_ERROR
else
    lnv_panneau.is_text  = "Connected"
    lnv_panneau.is_state = lnv_panneau.STATE_NONE   // back to the normal appearance
end if

Adapting the bar to the context #

// Hide a panel without deleting it : it will find its place again later
uo_statut.of_item("user").ib_visible = ib_utilisateur_identifie

// Gray it out when the matching action makes no sense
uo_statut.of_item("save").ib_enabled = ib_document_ouvert

// Reorder : move the status panel to the front (positions counted from 0)
uo_statut.of_move_panel(/*id*/ "etat", /*index*/ 0)

// Remove a panel that is no longer needed
uo_statut.of_remove_panel(/*id*/ "import")

The resize grip #

// On a resizable window, the corner grip is a familiar landmark
uo_statut.ib_show_resize_grip = true

Best practices #


← Component reference · Guide contents