12. Migrating from 4.0 to 5.0 #
← Migrating from 3.0 to 4.0 · Contents · Release notes →
5.0 changes no signature of the thirty-seven components of 4.0, nor any event — except the button bar (buttonbar, 12.7) and the ue_link_clicked event of the Markdown viewer (markdownview), which receives a second argument, as_kind (12.5). Three components change words. The progress bar (progressbar) takes those of the gauges — ib_label, il_color and is_label_format disappear in favour of ib_show_value, il_value_color, is_format and is_unit (12.1). The cartesian chart (chartcartesian) writes its numbers through is_format, as the gauges and the pie chart do: of_set_value_format and of_clear_value_format disappear, and ii_point_count of a series becomes il_point_count (12.4). The crosstab (crosstab) takes the same road: of_set_value_format and of_clear_value_format disappear in favour of is_format — on the field, or on one value alone through of_value — and of ib_negative_red (12.8). The compiler shows you every line to rework. The side bar (listbar) changes one event: ue_item_rclicked also receives the screen point of the click, al_x and al_y (12.9). The tiles box (tilesbox) renames one event: ue_tile_context(as_keys) becomes ue_tile_rclicked(as_keys, al_x, al_y), and the position of of_move_tile and of_insert_tile becomes long al_position (12.12). The radial menu (radialmenu) loses four tooltip properties it never showed — is_tooltip, is_super_tooltip_title, is_super_tooltip_text and is_super_tooltip_image (12.5). The calendar (scheduler) changes three gesture events: ue_appointment_changing receives as_kind, ue_appointment_moved and ue_appointment_resized receive the values the appointment had (12.10). The shell explorer (shellexplorer) changes one event: ue_error also receives the path and a constant reason, as_path and as_reason (12.11). The rich text block (statictext) changes one event: ue_hyperlink also receives ab_opened, whether the link really opened (12.5). The tab (tab) changes one event: ue_tab_rclicked also receives the screen point of the click, al_x and al_y (12.13). The sound player (soundplayer) changes three events: ue_started, ue_ended and ue_failed also receive the number of the sound, al_sound (12.14). The toaster (toaster) changes one event: ue_toast_dismissed also receives the reason of the closing, as_reason (12.15). The web browser (webbrowser): of_go_back, of_go_forward and of_stop return a long, and under ib_veto_navigation an address typed by the user is asked about to ue_navigating (12.17). The toolbar (toolbar) changes one event: ue_item_rclicked also receives the screen point of the click, al_x and al_y (12.18). The video player (video) changes one signature: of_stop becomes a function returning a long (12.16) — a call written as a statement still compiles. Three components change a right-click event of an item, which also receives its screen point al_x, al_y: the button bar (ue_button_rclicked), the breadcrumb (breadcrumb, ue_item_rclicked) and the cartesian chart (ue_point_rclicked); the status bar (statusbar) gives that point like the others, no longer multiplied by the scale of the display (12.19). The foundation (12.20): the reason a non-visual component failed is read through of_get_last_error() — the is_last_error property disappears from crypto, restclient, soundplayer, speechout, xml, u_pbt_regex and u_pbt_zip —, and of_stop, of_close and of_reset of the non-visual components return a long.
The rest asks nothing of your code: the data grid (datagrid) and the ribbon (ribbon) gain numeric input masks, and the editor of a numeric column of the grid now opens on the text of the mask (12.2, 12.3). The new components of 5.0 are presented in the release notes.
12.1 progressbar: the words of the gauges #
5.0 brings two gauges, linear (gauge) and dial (angulargauge). A progress bar also shows a value on a scale: the library now speaks a single language for it, and the bar, which said the same thing in other words, takes the words of the gauges. No old name survives: neither a property nor a name accepted by of_set_property.
| What | 4.0 | 5.0 |
|---|---|---|
| Show the readout | uo.ib_label = true | uo.ib_show_value = true |
| Colour of the value (-1 = the theme, unchanged) | uo.il_color = RGB(…) | uo.il_value_color = RGB(…) |
| A readout that writes the value | uo.is_label_format = "{value} of {max} rows" | uo.is_format = "#,##0" + uo.is_unit = "of 500 rows" |
| The percentage (default, unchanged) | uo.is_label_format = "" | uo.is_format = "" |
| Driving by name | of_set_property("label", …), ("label_format", …), ("color", …) | ("show_value", …), ("format", …), ("unit", …), ("value_color", …) |
is_formatis a PowerBuilder display format applied to the value ("#,##0","$#,##0.00"), with the separators of the display language, exactly as for the gauges. Empty, the bar shows the percentage, as before.- The
{percent},{value},{min}and{max}placeholders no longer exist. A label that mixed value and percentage ("{value} of {max} rows ({percent})") has no exact equivalent: choose the value (format and unit) or the percentage (and a unit). The maximum, which your code knows, is written in the unit. is_unitis new: a plain text written after the readout, separated by a space — after the value as after the percentage.of_resetclears it.- A mask that holds
%writes the share done, not the value:is_format = "0.0%"gives "35.0%" for 1,687 rows out of 4,820, rounded down like the percentage — the percentage with decimals that{percent}could not write. - A paused or failed wait turns into a full bar. In 4.0, a busy bar (
ib_indeterminate) givenSTATE_PAUSEDorSTATE_ERRORfroze in its slide, often outside its track: the failure could not be seen. In 5.0 it stops as a full bar (a full ring) in the color of the state, like the Windows taskbar, and the screen reader no longer announces it busy but says its state. of_set_property("tooltip", …)andsuper_tooltip_*return-5: the bar publishes no tooltip, and the door by name, which set one, is closed like the properties.- New, with nothing to rework:
is_orientation(ORIENTATION_VERTICAL: a bar that stands up, in place of aVProgressBar),is_accessible_name(the name the screen reader says), and the text of a wait (is_unitalone while the bar is busy).
// 4.0 : the label wrote the value through placeholders
uo_progress.ib_label = true
uo_progress.il_color = RGB(/*red*/ 0, /*green*/ 120, /*blue*/ 215)
uo_progress.is_label_format = "{value} of {max} rows"
// 5.0 : the words of the gauges - a display format for the value, then a unit
uo_progress.ib_show_value = true
uo_progress.il_value_color = RGB(/*red*/ 0, /*green*/ 120, /*blue*/ 215)
uo_progress.is_format = "#,##0"
uo_progress.is_unit = "of 500 rows"
The recipe: compile; every ib_label, il_color and is_label_format of a progress bar is reported. Replace the first two with ib_show_value and il_value_color. For the third: an empty text stays empty in is_format; a label that wrote the value becomes a format ("#,##0") and a unit; a label that wrote the percentage keeps is_format empty and puts its text in is_unit. An of_set_property that named label, label_format or color now returns -5 and does nothing (of_get_last_error names the property): search your code for these names.
12.2 datagrid: a numeric editor that types through a mask #
No signature changes, and ue_cell_edited still receives the bare number (1234.5). What changes shows on the screen: typing in a numeric column now follows an input mask, in the DataWindow syntax — the one you give through the new is_mask property of the column, otherwise its display format stripped of its literals.
| What | 4.0 | 5.0 |
|---|---|---|
The editor of a cell shown $1,234.50 | opened on the bare number 1234.5; any character was accepted | opens on 1,234.50; the grouping appears as the digits come, the decimals are limited to the mask, letters are refused; a pasted number is read in the display language |
| A four-digit number under a numeric format | not grouped in some languages (1234 in Spanish) | grouped in every language (1.234 in Spanish) |
| A negative number rounded to zero | -0 | 0 |
| Opening then closing the editor without typing | could change a value the format rounds | changes nothing |
| A rating cell read by a screen reader | five star signs | 4 / 5 |
// 5.0 : the input mask of a numeric column - the cell still receives the bare number
uo_grid.of_column(/*key*/ "revenue").is_mask = "#,##0.00"
The recipe: nothing to change. Code that read the typed text never sees it: ue_cell_edited still gives the number. A column whose input must stay free (a code, a part number) is a text column, not a numeric one.
12.3 ribbon: the masks of a spinner #
Nothing changes for a spinner without a mask. Two new properties of its handle, in the PowerBuilder syntax: is_mask, the input mask ("#,##0.00", "0%"), and is_format, the display format with its literals (0 "pt" shows 11 pt, typed 11). id_value and ue_value_changed keep the bare number, the swap between the two raises no event, and the masks follow the spinner into the panel of a collapsed group.
// 5.0 : a font size shown "11 pt", typed "11"
uo_ribbon.of_item(/*keys*/ "home/font/size").is_format = "0 ~"pt~""
The recipe: nothing to change.
12.4 chartcartesian: the number format through is_format #
The cartesian chart wrote its numbers through a function with four arguments (decimals, prefix, suffix, thousands separator). 5.0 puts the charts and the gauges under one language: a PowerBuilder display format, the one of a DataWindow column, in the is_format property — of the whole chart, and of an axis through its handle. The sections positive;negative;zero, the literals and the percentage come with it, and the separators stay those of the display language. No old name survives.
| What | 4.0 | 5.0 |
|---|---|---|
| The format of the chart | uo.of_set_value_format(0, "$", "", true) | uo.is_format = "$#,##0" |
| The format of one axis | uo.of_set_value_format(AXIS_VALUE2, 1, "", " u", false) | uo.of_axis(AXIS_VALUE2).is_format = '0.0" u"' |
| Back to the number as it is | uo.of_clear_value_format() | uo.is_format = "" (and "" on each axis that has its own) |
| Driving by name | — | of_set_property("format", "#,##0") |
| The number of points of a series (read only) | uo.of_item("k").ii_point_count (integer) | uo.of_item("k").il_point_count (long) |
- The format of an axis wins over the chart's, and keeps it. Setting the format of the chart no longer clears that of the axes (the form of
of_set_value_formatwithout an axis did): an axis goes back to the chart's format withis_format = "". - Without a format (empty, or a format that is not a numeric one), the number is written as it is, to the thousandth, with the decimal separator of the display language — as the default format did.
// 4.0 : decimals, prefix, suffix and thousands as four arguments
uo_chart.of_set_value_format(/*decimals*/ 0, /*prefix*/ "$", /*suffix*/ "K", /*thousands*/ true)
uo_chart.of_set_value_format(/*axis*/ u_pbt_chartcartesian.AXIS_VALUE2, /*decimals*/ 1, /*prefix*/ "", /*suffix*/ " u", /*thousands*/ false)
// 5.0 : a display format, written as in a DataWindow - for the chart, then for one axis
uo_chart.is_format = "$#,##0K"
uo_chart.of_axis(/*axis*/ u_pbt_chartcartesian.AXIS_VALUE2).is_format = '0.0" u"'
The recipe: compile; every of_set_value_format and of_clear_value_format is reported. Write the format as in a DataWindow: decimals gives the number of 0 after the point (-1 = #,##0.###), thousands the grouping ,, the prefix and the suffix are written before and after (in quotes when they hold digits or spaces). The format of an axis goes into of_axis(<axis>).is_format.
12.5 Other behaviours you may see #
| What | 4.0 | 5.0 | ||
|---|---|---|---|---|
Native menus of a component that has an accent of its own (il_theme_accent) | the accent only showed in the box of a checked entry | the pointed entry shows it too, as a stripe on its start edge (on the right in RTL) | ||
button: Ctrl, Alt or Shift + Enter (and Ctrl / Alt + Space, Ctrl + Esc) on the button that has the focus | clicked that button | go to the window, as from any other control: the shortcut of another button (is_shortcut = "Ctrl+Enter") fires, the focused button does not; Enter and Space alone still click it | ||
Grayed button with ib_default (or ib_cancel), closest to the focus, in an MDI sheet | Enter (Esc) went to the default button of another sheet | the key stays in its sheet: the field, or the default PB CommandButton, receives it | ||
breadcrumb: ii_max_visible set | an exact number of segments under OVERFLOW_COLLAPSE (the width folded nothing more), ignored under OVERFLOW_SCROLL and OVERFLOW_SHRINK | a ceiling in all three modes; under OVERFLOW_COLLAPSE the width still folds more when the bar is too narrow, and where you are no longer leaves the bar | ||
breadcrumb: of_add_child with an empty text | an empty line in the menu | the branch key, as of_add_children does | ||
breadcrumb: Ctrl+S, F5 and the other shortcuts of the window while the path is typed | did not fire | fire, as from a SingleLineEdit; Enter and Esc stay with the field | ||
breadcrumb: ue_children_needed that never returns | no chevron opened any more until the next of_reset | a click on another chevron abandons the question, and the trail lets it go after 10 seconds | ||
chartcartesian: a band or a threshold without a colour (-1 or NULL) | a solid block of the text colour | a pale wash of the theme accent (a threshold line: the accent); a NULL bound is refused (-5) | ||
chartcartesian: a NULL weight in a heat map | the cell painted in the hottest colour, labelled "NaN" | an empty cell: nothing drawn, labelled or clickable there; a bubble without a weight keeps the default size, outside the scale | ||
chartcartesian: of_remove_series | the following series changed colour; the tooltip of the removed series dressed the next series with the same key | every series keeps the colour taken when it was added; the tooltip and the item colours go with the series | ||
chartcartesian: of_append_values / of_append_categories with ib_animated | the whole chart fell back on its axis and rose again at every push, as long as the window was not full | only the new shape rises, the others slide; the whole arrival only replays when a series is added | ||
chartcartesian: stacked bars on both value axes | the two stacks were drawn on top of each other | side by side in the category | ||
chartcartesian: a markup tag in a category or a value label | written as it stands on the axis, read as markup in the panel | text everywhere: the tag is dropped (the axis, the panel, #x#, #label#) | ||
chartcartesian: Esc with nothing open, Enter on a gap | kept by the chart | go to the window: its Cancel button, its default button | ||
codeeditor: Ctrl+Tab or Alt+Tab in the editor | indented the code: the keyboard could not leave the editor | go to the window (the next page of a tab); Escape then Tab leaves the editor, Ctrl+M or ib_tab_moves_focus let Tab out | ||
codeeditor: of_find on an invalid regular expression | returned 0 | returns -5, as of_replace does | ||
codeeditor: a new is_text during a search | the bar stayed open and raised ue_find_result | the bar closes, raising nothing (a value is silent) | ||
codeeditor: is_syntax = "SQL" read back | "sql" | "SQL", as written | ||
Folded codeeditor: #regionopen, the copy and of_selected_text | shown as #region; the copy gave the display, without the lines of the closed regions | shown as written; the copy and of_selected_text give the source of the range, closed regions included | ||
codeeditor: markers and il_doc_line when lines are added or removed above them | stayed on the same line number | move with their line; a deleted line takes its markers with it | ||
codeeditor: the caret after "Replace all" (of_replace_all) | on the last replacement | stays where it was, moved by what was inserted before it | ||
codeeditor: Ctrl+Z, Ctrl+Y | the browser's history, lost when the text was written with the focus elsewhere | the history of the component (of_undo, of_redo): it also counts what your code does, a new is_text empties it | ||
crypto: of_totp_verify(secret, code, ref al_step) on a code typed with spaces ("864 010") | refused, step 0 | accepted, as by the two-argument form; the spaces are ignored | ||
crypto: of_base64_encode_file of a 32 to 64 MB file in a 32-bit application | promised up to 64 MB; the memory of the process could run out | "" and of_get_last_error() (32 MB at most in 32 bits); of_base64_encode_file_to_file encodes a file of any size to another file | ||
crypto: of_totp_uri of a secret typed by hand ("gezd gnbv", a "0") | written as it stood in the URI | written in base32 capitals, without spaces or =; any other character: "" and of_get_last_error() | ||
crypto: a NULL argument | is_last_error could come back NULL | counts as an empty one; of_get_last_error() is never NULL | ||
crypto: a target \x or C:x (of_base64_decode_to_file, of_encrypt_file, of_decrypt_file) | -5 and a wrong message ("not a base64 value", "all needed") | -5, and of_get_last_error() says the path depends on the current folder of a drive | ||
commandpalette: a search and the recently used commands (is_recent) | a recent command gained up to il_max_recent × 4 points: with a large limit, it passed a better match | it only breaks ties between results that match about as well | ||
commandpalette: a command without a group (as_group = "") declared between two groups | listed under the header of the group declared before it | first in the list, without a header | ||
commandpalette: Home / End in a search box holding text, Shift+Home | moved the selection in the list; Shift+Home selected nothing | move the caret in the box; Ctrl+Home / Ctrl+End reach the list; Shift selects in the box | ||
commandpalette: a right or middle click on a line | ran the command | does nothing | ||
commandpalette: of_command on a key no command has | ib_enabled / ib_visible read true, a write was lost in silence | they read false; a write is lost and of_get_last_error says so | ||
commandpalette: a second palette object that took over a chord is destroyed | the key answered nobody until the first one registered it again | the chord comes back to the first one | ||
commandpalette: is_recent with spaces or repeated keys, a lower il_max_recent | "a, b" kept only a; a twin showed twice; is_recent stayed long | cleaned, cut to the limit and given back clean to is_recent at the opening | ||
dockcontainer: building the dock, restoring a layout | ue_layout_changed at every add, the first one knowing a single panel: a layout saved in the event was overwritten by a half-built one | once for a burst framed by of_set_redraw(false) … (true), at the resume (and for changes less than 40 ms apart); of_set_layout raises it once. Read the saved setting before creating the panels | ||
dockcontainer: the panel at the front of a stack changes without a click on its tab | nothing was raised (a panel stacked by of_add_panel or of_move_panel, the front one closed, floated or removed, a panel docked back) | ue_panel_selected of the panel that came to the front, after ue_panel_closed, ue_panel_floated or ue_panel_docked; a restored layout raises none. n_pbt_dock_panel.ib_front reads it back | ||
dockcontainer: ib_visible = true on a closed panel of a stack | it came back behind the active tab | it comes to the front, and ue_panel_selected follows; in an unpinned group it stays on the rail | ||
dockcontainer: of_move_panel towards the panel itself (as_target = as_key) | returned 0 doing nothing, or split its stack | returns -5; to split a stack, aim at another panel of the stack (of_move_panel("b", "a", POSITION_BOTTOM)) | ||
dockcontainer: a panel moved into an unpinned group, or out of it | ib_pinned changed without an event | ue_panel_pinned follows | ||
dockcontainer: a click without a move on a splitter | raised ue_layout_changed | raises nothing: nothing changed | ||
dockcontainer: of_keys_at with numeric keys | the integer keys first (2, 10, zeta) | the add order (zeta, 10, 2) | ||
dockcontainer destroyed at run time (CloseUserObject) | its controls came back on the window, hidden | they get back the visibility they had before of_add_panel | ||
dockcontainer: of_add_panel of a control that CONTAINS the dock | the windows looped into each other | returns -5, the control stays where it was | ||
crosstab: AGG_COUNT | counted the rows | counts the non-empty values, like Excel's Count; AGG_COUNT_ROWS, new, counts the rows | ||
crosstab: a sum with no value at all; a "difference from the previous one" next to an empty cell | 0 | an empty cell (of_get_cell_value gives NULL) | ||
crosstab: Top N or Bottom N (of_set_value_filter, or the menu) on a field placed under another one of its zone | ranked over the whole table | ranked inside each parent (the best city of each region); at the first level, unchanged; the members tied with the N-th one all stay | ||
crosstab: no field in Columns | a total column that doubled the only column (`Nord | 650 | 650`) | no total column any more; ib_col_grand_total keeps its value |
crosstab: several measures and fields in Columns | one Total column per measure, with no measure name, and not sortable | a "Total" header then one header per measure, sortable | ||
crosstab: ue_layout_changed | raised by the user's gestures, and by is_thousands and of_remove_field only | also raised by every order of the code that changes what of_get_layout returns (of_set_layout included), once per order; only once at the end of a build framed by of_set_redraw(false) … (true); never when nothing changes, nor for of_reset | ||
crosstab: a percentage (SHOW_PCT_*) | 57.9 % in every language | written the way the display language writes it: 57.9% in English, 57,9 % in French | ||
crosstab: the label filter | offered by the chip menu of a numeric field only; on a date, of_set_label_filter compared the year (2025-03-15 was 2025) | offered for every field; on a date, the text overload takes days: LABEL_BEFORE, LABEL_AFTER, LABEL_BETWEEN ("yyyy-mm-dd", days included); the numeric overload, or LABEL_CONTAINS / LABEL_BEGINS / LABEL_ENDS, on a date: -5 | ||
crosstab: of_group_date_field on a field that holds no dates | 0, and a single "(blank)" member | -5 | ||
crosstab: of_add_calc_field / of_add_calc_measure refused by the grid (name already taken, formula that does not compile) | 0; only ue_calc_field_error said so | -5 and the reason in of_get_last_error (ue_calc_field_error is still raised); a name holding / or ` | : -5; a formula accepts .5 and 1e3` | |
crosstab: of_set_value_filter Top or Bottom of less than 1 member; of_expand_to_level below 1 | brought back to 1 | -5 | ||
crosstab: of_get_cell_value called from an event raised during an order of this script | -2, as for a component not created | -4, and of_get_last_error says why: read after the event | ||
crosstab: the Options menu of the grid (the gear) | "Grand total" and "Subtotals" switched both axes from the state of the rows | one entry per axis: grand total row and column, row and column subtotals | ||
crosstab: of_from_datastore — a CHAR column, a decimal, the Format of a column | the padding blanks stayed in the member; the Format was ignored | the padding blanks are removed; a decimal is read with the separator of the workstation; the Format of the column is the default format of its values | ||
datagrid: a selected row the search or a filter hides, or of_remove_row removes | stayed selected, silently (of_selected_keys and ue_row_menu_clicked carried it) | leaves the selection, and ue_selection_changed says so; of_select_rows does not take a hidden row | ||
datagrid: ib_hidden, is_pin, ii_index set to the value they already have; a click on the grip without dragging | raised ue_layout_changed | raise nothing: nothing changed | ||
datagrid: layout changes between of_set_redraw(false) and of_set_redraw(true) | one ue_layout_changed per change | a single one, on resuming, with the final layout | ||
datagrid: a type or a renderer outside the constants (of_add_column, is_renderer, is_selection_mode); of_add_row_menu_item without a created component | accepted and read back as they were, without effect; 0 | of_add_column returns -5 (of_get_last_error says which); an unknown renderer reads back "", an unknown mode SELECT_NONE; -2 | ||
datagrid: of_reload_row or of_update_row of an edited cell | the "modified" mark stayed | it goes: the row holds what the DataStore holds again | ||
datagrid: editing a column with a code table, a date; a time column of a DataStore | the engine's <select> and date box; a time was text | the library's list and calendar (a date can be TYPED too, in the order of the language); a time (TYPE_TIME): sort, filter > 09:00, format, typed 9:5 | ||
datagrid: a filter > 3 on a rating without a type or on a column with a code table | looked for the text "> 3": no row | compares the data (the number, the code) | ||
datagrid: a tree under a search; a row whose parent is not in the grid | the child found stayed hidden; the row never showed | its ancestors are shown, open; the row hangs from the root | ||
datagrid: of_from_datastore / of_load_rows after of_open_source; of_append_rows without a key after of_from_datastore; a CHAR value | the grid stayed on skeletons; the row was refused (-5); kept its padding of spaces | the source is left; the key follows the largest RowID; trimmed | ||
datagrid: of_export_xlsx | dates were written as text; no ceiling | real Excel dates; a workbook too large (beyond about 18 MB) is refused, ue_xlsx_saved says why | ||
messagebox: Esc or Alt+F4 on a box without a cancel button | closed the box and returned 0 — of_info too, which promised 1 | as on Windows: a box with a single button closes through it (of_info returns 1), a Yes / No box does not close — it has to be answered; ib_closable = true gives the 0 of 4.0 back. A = 2 test migrated from a MessageBox no longer lets a deletion through | ||
messagebox: a shortcut (of_info, of_error, of_confirm, of_prompt…) after setting il_accent, is_position, ib_movable, a size or ib_input_password | everything was cleared silently: the password of of_prompt showed in clear | the shortcut only replaces the content (title, message, icon, buttons, checkbox, choices); the appearance and the settings of the field stay. of_reset() clears everything | ||
messagebox: of_reset() after a box | of_get_last_error, of_checked, of_action and of_input_value still spoke of the old box | they are reset | ||
messagebox: a required field filled with spaces | accepted | empty: the default button waits (the value typed comes back as it is) | ||
messagebox: an [action] zone in the title, a label or the footer; a link in a choice; two buttons with the same mnemonic | the zone did nothing; the link opened the browser AND chose; Alt+letter answered with the first button | the zone answers as in the message (of_action); the link opens without choosing; Alt+letter moves the focus from one button to the other, Enter picks | ||
messagebox: Ctrl+C | lost the & of &&, copied the tags of a button, ignored the input | the labels as shown, "label: value" of the field (never a password), the details and the footer | ||
messagebox: a descendant that called xx_set_style_override or xx_clear_style_override (protected) | overrode a theme token of the box | they are gone: il_accent colours the box | ||
json and jsontree: a path level that holds ~0 or ~1 | read as written; a key that holds / had no path | ~1 is a / of the key, ~0 a ~ (JSON Pointer, RFC 6901): paths/~1users reads the key /users; a key that holds a ~ is written ~0 in a path | ||
json: an empty path level (a//b, a/) or a path that starts with / | refused with -5, read as absent | an empty level is the key "", a leading / is the full pointer form: /name is name, / names the key "" of the root | ||
json: of_get_number, of_get_decimal, of_get_longlong on a string such as "12 kg" or "1,5" | read its beginning: 12, 1 | 0: a string counts only when all of it is a JSON number — "12.50" still reads 12.5 | ||
json: of_set_members of a key the document already holds | the key was written a second time: n_pbt_json read the first one, a browser or a server the last one | the value is replaced in place; a key the fragment repeats keeps its last value | ||
json: of_pretty of a document holding an of_set_raw value nested more than 512 levels deep | another document, cut at 512 levels | an empty text | ||
jsontree: a click on a key that holds /, an empty key, or under a duplicate key | a path that read ANOTHER value in n_pbt_json | x~1y for the key x/y, a//b for an empty key; of_selected_addressable returns false under the second of two identical keys | ||
jsontree: Ctrl+C with a piece of text highlighted with the mouse | the whole node | the highlighted piece | ||
jsontree: a JSON text that starts with a BOM | refused (ue_error) | shown, as n_pbt_json reads it; is_json reads back as set | ||
jsontree: the ue_error message in English | Invalid JSON : … | Invalid JSON: … (each language keeps its punctuation); 01, 1., 1e say Bad number | ||
jsontree: of_expand_path during a search | folded again at the next step of the search, without ue_node_toggled | stays open, with the blocks opened above it | ||
jsontree: Space on a selected value | scrolled the tree by a page | does nothing (a block still folds) | ||
xmltree: a blank between two children (<b>x</b> <i>y</i>) | had no line: /p/text()[1] answered -5 | a line of its own, shown ␠, with its path: the line numbers of mixed content change | ||
xmltree: a text between two children (Hello <b>x</b> again) | Hello, again: its edge blanks trimmed | Hello , again: only the layout line breaks go | ||
xmltree: of_select_path of an XPath whose first node is a blank of layout (//text()) | -5 | the first node the tree SHOWS is selected | ||
xmltree: of_selected_value of an element that holds only line breaks (shown <x/>) | "" | those line breaks, as n_pbt_xml reads them | ||
xmltree: Ctrl+C with a piece of text highlighted with the mouse | the XML of the whole node | the highlighted piece | ||
xmltree: the ue_error message in English | Invalid XML : … | Invalid XML: … (each language keeps its punctuation) | ||
xmltree: of_expand_path during a search | folded again at the next step of the search, without ue_node_toggled | stays open, with the elements opened above it | ||
xmltree: Space on a selected leaf | scrolled the tree by a page | does nothing (an element with children still folds) | ||
jsontree, xmltree: a search that closes (Escape in the box, of_clear_search, of_reset, ib_search_enabled = false) | no event: an application's "3 / 12" line stayed wrong | ue_search_result(0, 0), once; nothing when no search was running | ||
PBT_SetDefaultFont with a size: codeeditor, jsontree, xmltree, ribbon, toolbar, crosstab, datagrid, tilesbox, stepbar, listbar, dockcontainer, video, picture, menus and tooltips | the code, the document, the ribbon (its theme size) and many secondary texts kept their size | they follow the size of the application, in their proportions; the size of the application wins over the ribbon size of the theme; an ii_font_size of the codeeditor wins over both | ||
markdownview: ue_link_clicked | (string as_url) | (string as_url, string as_kind): a script already written for the event stays valid; as_kind (LINK_WEB, LINK_MAIL, LINK_DOCUMENT, LINK_FILE, LINK_OTHER) says what the link is — sort by it rather than by the text of the address | ||
markdownview: a picture of a document on a network share | loaded | refused, unless it lies on the share the document was read from, or with ib_network_pictures; a document read from the web shows no file of the workstation | ||
markdownview: a new is_markdown of the same document, of_refresh | the view jumped to the top | the reading position is kept; a new is_source still starts at the top | ||
markdownview: of_toc, of_scroll_to and a search right after is_source | acted on the previous document | the file is read in the background: of_toc returns 0, of_scroll_to and the search wait for it; read the table in ue_loaded | ||
markdownview: a column the author aligned (:--, --:) in a right-to-left application | changed sides | keeps its side; only the default alignment follows the direction | ||
markdownview: ue_load_failed for a text set by is_markdown | never raised | raised (REASON_FAILED, empty as_source) for a text the component cannot read; the previous document stays on screen | ||
menubar: the shortcut of an entry (is_shortcut) | acted on the state the last opening of its menu left | raises ue_menu_opening of its menu first, as Windows does: an entry that event greys does not answer, and ue_menu_closed says so | ||
menubar: an opening given up before it showed (sliding fast, Escape or Alt during ue_menu_opening, the focus lost) | ue_menu_opening without ue_menu_closed; after Escape the dropdown opened anyway | nothing opens, and ue_menu_closed follows: every ue_menu_opening gets exactly one ue_item_selected or one ue_menu_closed | ||
menubar: Alt then Escape, F10 then Escape | Escape went to the window too: its Cancel button | Escape leaves the menu mode and stays with the bar | ||
menubar: a menu opened from the keyboard (Alt+letter, F10 then Enter) | no item highlighted: Enter chose nothing | the first item is highlighted, Enter picks it | ||
menubar: Alt when the bar already has the focus | the menu mode toggled on the key down: Alt+Shift (keyboard layout) turned it on | when Alt is released alone, as on Windows | ||
menubar: a click on a greyed title or on the empty part of the bar | the bar kept the keyboard, the field being edited lost it | the keyboard stays with the control the user was typing in | ||
menubar: is_shortcut set on an address that names no entry | the key was taken in the whole window, even after of_clear | nothing is armed: set it after of_add_item | ||
pdfviewer: ib_allow_save / ib_allow_print of one viewer | applied to every viewer of the application; an of_reset elsewhere gave Save back to a confidential document | each viewer keeps its own setting | ||
pdfviewer: ib_allow_save / ib_allow_print set before is_source | three loads, three ue_load_completed; a document that failed was tried again at each change | a single load; a document that failed is not tried again | ||
pdfviewer: ii_page set while a document is shown, then another is_source | the next document opened at that page | the page was the shown document's: the next one opens at its first page; to open a document on a page, set is_source then ii_page | ||
pdfviewer: the same value set again (ii_page, ii_zoom, is_fit, ib_viewer_toolbar) | reloaded the document and raised ue_load_completed | does nothing | ||
pdfviewer: ii_zoom outside 25 to 500 | passed to the reader as is | brought back into 25 to 500, read back as applied | ||
pdfviewer: an https://name:secret@… address; a source made of blanks | put in the reader, which refused it under a vague reason, the secret travelling back in the events; read back as is, of_refresh returned 0 | refused at once through ue_load_failed (REASON_UNSUPPORTED): download the document with the restclient; read back "", of_refresh returns -4 | ||
picture: id_max_zoom on a picture larger than its frame | the wheel, + and id_zoom went up to the actual size | they stop at the ceiling; only the 1 key goes beyond | ||
picture: a new is_source, or ib_zoomable = false, on a zoomed picture | the zoom came back to 1.0 without a word | ue_zoom_changed(1.0) is raised (of_reset stays silent); set id_zoom after is_source | ||
picture: a path with blanks around it (a CHAR column) | refused, REASON_UNSUPPORTED | displayed; is_source reads back as written | ||
picture: the zoom keys with Ctrl, Alt or Windows held down | Ctrl++ zoomed, Alt+1 showed the actual size | left to your application (shortcuts, mnemonics) | ||
picture: a recoloured picture (mono:, tint:) from another site whose server refuses cross-origin requests | ue_loaded and an empty frame | ue_error with REASON_FAILED, the message says why | ||
radialmenu: is_tooltip, is_super_tooltip_title, is_super_tooltip_text, is_super_tooltip_image | existed, never showed anything: the launcher has no surface | removed: the compiler shows the line, delete it | ||
radialmenu: of_close, a second of_show, of_clear or of_reset while a wheel is open | ue_dismissed came when the wheel left the screen; of_is_open stayed true until then | ue_dismissed at once, once per opening; of_is_open false as soon as the call returns | ||
radialmenu: of_remove_item of a branch the open wheel does not show (hidden) | the wheel closed (ue_dismissed) | the wheel stays open; it closes only when it showed the branch | ||
radialmenu: of_remove_item with a bare key ("csv") | -5 | resolved as of_item does it (the one branch that carries it); -5 when two branches share it | ||
radialmenu: of_show of a wheel with nothing to show while another is open | ue_dismissed, and the old wheel stayed on screen | the old wheel closes too: one ue_dismissed for each opening | ||
radialmenu: il_back_color_hover of a branch without il_text_color_hover | the pointed label kept the text of the theme (white on pale pink in a dark theme) | a text readable on that tint is chosen; a colour you set is never changed | ||
restclient: ib_windows_auth or is_client_certificate, and a redirection to another host | the Windows credentials and the certificate followed the redirection | only the host and port of the request receive them: the other host gets the request without them | ||
restclient: a header value beyond Latin-1 (Greek, Japanese…) | accepted by of_set_header (0), then every request of the object returned -5 | refused by of_set_header itself (-5, of_get_last_error() says why); of_set_basic accepts them: its pair leaves as the base64 of its UTF-8 | ||
restclient: a malformed method ("GE T"), credentials in the URL (https://user:pwd@…), an of_upload field name holding a quote | -4 "request failed: 0"; the credentials vanished without a word; the multipart body was broken | -5, and the reason in of_get_last_error() (for credentials: use of_set_basic) | ||
restclient: a 303, or a 301 or 302 after a POST, that goes on as a GET | kept the Content-Type of the original body | goes without Content-Type | ||
restclient: ue_progress | raised for every async body, never reaching the total: a progress bar stayed at 39 % | raised for every async body (the documentation says so), and the last one, just before ue_response, is the total | ||
restclient: of_response_header of a header sent several times (Link, Set-Cookie) | the first value only | all of them, joined by , — Set-Cookie by a line break | ||
restclient: the User-Agent sent | PBToolboxAI/4.0, written in the code | the version of the library; of_set_header("User-Agent", …) still replaces it | ||
restclient: a request when the HTTP client could not be created | left on a one-off session, without Windows authentication, client certificate or cookies | -2, and il_status says so | ||
restclient: of_set_header("Authorization", …) after of_set_basic | both authentications were sent | one authentication at a time: the Authorization set replaces the Basic one | ||
ribbon: a value written by the code (is_text, id_value) while the field of a combo or a spinner has the focus | the field kept the old text; leaving it raised ue_combo_changed / ue_value_changed with the old value, which replaced yours | the field shows it at once, unless the user is typing (the typing wins); leaving the field without typing raises nothing | ||
ribbon: a label with tags (is_label, the title of a tab, a group, a banner, the application button) | shown as typed, tags included (the panel of a folded group did interpret them) | the rich text markup is interpreted everywhere; a text of your user goes through of_escape_markup | ||
ribbon: the wheel over the ribbon | every small move of a touchpad changed tab; a folded ribbon changed tab too, showing nothing | one tab per notch of the wheel (small moves add up); nothing on a folded ribbon | ||
ribbon: of_add_spinner with a step of 0 or less, or a minimum above the maximum; inconsistent id_min / id_max / id_step | accepted: dead or reversed arrows, a value outside the range shown | of_add_spinner returns -5 and keeps the value within the range; a step of 0 or less is refused (of_get_last_error says why); a bound written past the other one takes it along, as in a NumericUpDown — the order of the two writes no longer matters | ||
ribbon: an is_keytip not made of letters A-Z and digits ("É", "-") | kept and read back, never reachable from the keyboard | refused: nothing changes, of_get_last_error says why | ||
ribbon: Escape at the second level of the key tips (the commands of a tab) | closed all the key tips | goes back to the letters of the tabs, as in Office; a second Escape closes | ||
speechout: of_speak_from(0) or a negative number | read from the first sentence | -5, nothing is read (positions count from 1) | ||
speechout: ii_rate, ii_pitch, ii_volume set out of their range (ii_rate = 1000) | read back the value set (1000) while the voice applied the bound | read back as applied (400) | ||
speechout: a [rate]…[/rate] piece in a sentence | a sentence of its own: its own ue_sentence, its own number, and a full stop after [/rate] became a "sentence" | stays in its sentence: one ue_sentence with the whole text, one number, ue_word counts in that text, of_spoken_text one line per sentence; the punctuation goes with the piece | ||
speechout: [rate=0] | read at 100 % | the slowest rate, 10 % | ||
speechout: a rule of of_add_replacement on a word that is also the name or the value of a tag (total with [mark=total], rate, a word inside [spell]) | rewrote the tag: the mark changed its name, the tag was read aloud, the spelled text changed | the rule rewrites the text between the tags only | ||
speechout: a workstation with no voice at all | ue_error, then a reading "under way": ue_started, every ue_sentence, ue_stopped; of_speak_sync returned 0 | ue_error and nothing else: no reading, no ue_started; of_speak_sync returns -4 | ||
speechout: is_lang without a region ("fr", "en") | ue_voice_fallback at every reading | no fallback for a voice of that language, whatever its region | ||
speechout: of_clear_queue behind an of_speak (the reading under way is not a text of the queue) | ue_queue_done at the end of the reading | no ue_queue_done: no text of the queue was read | ||
speechout: an initial (John F. Kennedy), an abbreviated month (Oct. 10), a dotted acronym (U.S.) | ended the sentence | stays in the sentence (a month or an acronym ends it before a capital, like etc.): the sentence numbers may change | ||
statusbar: a clickable panel that is greyed and carries a tooltip | the tooltip never showed | it shows, to say why the panel is greyed | ||
statusbar: of_count, of_keys_at, of_has on the address of a panel ("enc") | 0, "", false: the entries of its list were not seen | the entries of its list, separators left out | ||
statusbar: a position in a drop-down list (of_insert_menu_item, of_move_menu_item) | counted the separators | counts the entries only, like the positions of the panels | ||
statusbar: a panel or entry key that starts with __ | accepted | refused, -5: it is reserved to the component | ||
statusbar: is_tooltip and the five colours on a list entry (of_menu_item) | kept and read back, without effect | ignored, read back empty (-1 for a colour): the native menu does not show them | ||
statusbar: the grip (ib_show_resize_grip) in an MDI sheet, or a bar that is not at the bottom of its window | it resized the frame, from its corner | it resizes the sheet; no grip when the bar does not sit in the bottom corner | ||
statusbar: the Menu key or Shift+F10 on a focused panel | nothing | ue_panel_rclicked, at the bottom-left corner of the panel | ||
stepbar: Enter or Space on a step, in a window that has a Default button | ue_step_clicked and the Default button ("Next") fired | ue_step_clicked only: the key stays with the bar | ||
stepbar: of_clear_steps while the bar stands on a step | raised nothing | ue_step_changed(rank left, key left, 1, ""), like the removal of the current step; of_reset raises nothing | ||
stepbar: ii_current beyond "everything done" (further than the number of steps + 1) | ue_step_changed announced at once a rank that did not exist; the arrival of the step was silent | nothing is raised while the bar waits; ue_step_changed is raised when the step arrives | ||
stepbar: of_move_step on a bar that stands on "everything done" | could reopen the bar: a step became current again, with ue_step_changed | the bar stays on "everything done", nothing is raised | ||
stepbar: NAV_VISITED, a step inserted or moved in front of the current step | clickable | shown done, but not clickable: it was never reached | ||
stepbar: a step with a warning (STATE_WARNING) | an amber bullet | an amber bullet and a second amber ring: it no longer looks like a done step where the accent is amber | ||
statictext: ue_hyperlink | (string as_url) | (string as_url, boolean ab_opened): a script already written for the event stays valid; ab_opened is FALSE when the link did not open (a scheme other than http, https, mailto — of_get_last_error() says why —, or kept shut by ue_hyperlink_opening) | ||
statictext disabled on a background of its own (il_back_color, a [bk] run) | the text took the theme's grey, unreadable on a dark or coloured background | its colours are kept and attenuated; on the theme's surface, the theme's grey, as before | ||
statictext: PBT_SetDefaultFont with a size | the size stayed 11 pt | the size given applies (11 pt without it, unchanged) | ||
statictext: ii_font_size outside 6 to 200 | applied as it was | brought back to the nearest bound, like the [size] tag, and read back as applied | ||
statictext: double click on a word with ib_selectable | one ue_clicked before ue_double_clicked | two ue_clicked then ue_double_clicked, as the PowerBuilder StaticText; releasing after a drag that selects still raises no click | ||
statictext: of_reset of a text announced cut | nothing | ue_text_overflow(false) | ||
statictext: is_text read after of_append_text, when a line left a tag open | [b]Start[br]two: set again, the bold ran on into the next line | [b]Start[/b][br]two, what the screen shows; an empty line keeps its height; under ib_marquee, the lines scroll as one line | ||
statictext: ib_auto_width and an emptied text | kept the width of the previous text | shrinks to its padding; a theme change measures the width again too | ||
xml: of_count, of_get_values, of_get_attrs, of_get_attr_names when nothing is loaded, a built element is still open or the engine refuses the XPath | returned 0, like a search without result | return -4 (-2 when the page does not answer), of_get_last_error() says why; 0 is always a true zero. A > 0 test does not change; an = 0 test that meant "nothing found" now sees the refusal apart | ||
xml: of_get_attr and of_remove_attr of an absent attribute, of_get_attrs with an empty name | empty with no reason, 0 ("done"), 0 | empty and "no such attribute" in of_get_last_error() (an attribute written empty stays without a reason), -4, -5 | ||
xml: of_set_value, of_set_attr, of_add_child of a text holding a control character (Char(1)) or a CR | written as it was: the document no longer reloaded, the CR came back as LF | the forbidden character is dropped, as the builder does; the CR is written and reads back | ||
xml: builder — a second element at the top, a text with no element open, an attribute after a child | written (two roots) or ignored without a word | left out, and of_get_last_error() says why | ||
xml: of_get_value("sum(//qty)") over a text that is no number; of_get_value("/") | the text NaN; empty | empty and "the expression is not a number"; the text of the document |
The recipe: nothing to change.
12.6 What was added #
None of the following asks you to change your code. The eight new components of 5.0 are presented in the release notes.
| Object | Added |
|---|---|
| progressbar | is_unit: a text written after the readout ("of 500 rows", "MB") |
| datagrid | is_mask of a column (n_pbt_datagrid_column): the input mask of a numeric column; a column without a display format shows its is_mask |
| datagrid | the keyboard of the headers (Arrow up from the first row; Enter sorts, Shift+Enter adds to the sort; Alt+Down or the Menu key opens the menu of the column; Ctrl+Shift+arrows move it, Alt+arrows change its width); TYPE_TIME; of_get_last_error says why a call returned -5 |
| ribbon | is_mask and is_format of a spinner (n_pbt_ribbon_item); is_group: exclusive toggles of a group (n_pbt_ribbon_item) and radio entries of a menu (n_pbt_ribbon_menu_item); ue_item_rclicked (right click on a control, a group, a tab or a Quick Access Toolbar button, with the screen point al_x, al_y; the Menu key and Shift+F10 too) and ue_rclicked (outside any item); is_title of a contextual group (n_pbt_ribbon_ctx_group), whose tooltip shows on the banner; key tips of the Quick Access Toolbar buttons; item colours of the menu entries and the Quick Access Toolbar buttons; accessible names of every control |
| breadcrumb | typing the path becomes an address bar: ib_auto_complete, ue_path_typing and of_add_suggestion (completion while typing), ib_veto_path, ue_path_entering and is_path_error (a refused path keeps the typing) |
| chartcartesian | of_from_datastore (DataStore, DataWindow, DataWindowChild), of_map and the ROLE_* constants, of_reload: the graph of a DataWindow (rows summed by category and series, read again in place); of_set_point_color / of_get_point_color; ue_point_rclicked, ue_rclicked; of_get_categories; of_remove_axis_section |
| codeeditor | of_undo, of_redo, ib_can_undo, ib_can_redo and ue_undo_state_changed (the undo history under control); ue_modified_changed; of_toggle_comment (Ctrl+/); of_next_marker (F8); ib_match_brackets; ib_tab_moves_focus (Ctrl+M) |
| crypto | blobs (of_base64_encode_blob, of_base64_decode_blob, of_hash_blob, of_hmac_blob, of_crc32_blob, of_encrypt_blob, of_decrypt_blob); of_base64_encode_file_to_file; of_jwt_verify_jwks, of_jwk_to_pem, of_pem_to_jwk; the expected claims of of_jwt_verify and il_jwt_leeway_seconds; JWT_HS384/HS512, JWT_RS384/RS512, JWT_PS256/PS384/PS512, JWT_ES384 and KEY_EC_P384; the scheme and hash of of_sign / of_verify (SIGN_PKCS1, SIGN_PSS); the additional data of of_encrypt_with_key / of_decrypt_with_key; the hash of of_rsa_encrypt / of_rsa_decrypt; the settings of of_totp_code, of_totp_verify, of_totp_uri and of_hotp_code; of_password_needs_rehash |
| buttonbar | is_style of a button (STYLE_PRIMARY, STYLE_FLAT, STYLE_DANGER), is_badge (a text badge), il_badge_color, is_mnemonic, ii_image_size and ii_badge_size of the bar, ib_enabled of the whole bar, ue_button_rclicked and ue_rclicked, of_clear_shortcuts |
| commandpalette | of_load_menu(menu): the palette filled from a PowerBuilder menu, read again at every opening; of_loaded_item(as_key) gives the item of a command; of_get_last_error() |
| dockcontainer | ib_front of a panel (n_pbt_dock_panel, read only): the panel its stack shows; the Auto Hide entry of the panel menu, also on the rail handle; Shift+F10 and the Menu key open that menu under the tab; the active panel, the one holding the keyboard: of_active_panel() and ue_active_panel_changed(as_key) |
| crosstab | of_value(position) and its handle n_pbt_crosstab_value (one value of the Values area: is_agg, is_show, is_conditional_formatting, is_format, ib_negative_red, is_label, of_field()); of_value_count, of_remove_value, of_move_value; of_get_cell_rows (the rows of the DataStore behind a cell); is_format of a field; AGG_COUNT_ROWS, LABEL_BEFORE, LABEL_AFTER |
| messagebox | of_messagebox (the arguments of MessageBox(), Question! and YesNo! included) and the BUTTONS_* constants; of_retry_cancel; the default button of of_confirm, of_yes_no, of_yes_no_cancel (al_default); Retry, Abort, Ignore, Close translated; ib_closable, ib_sound; is_details, is_details_label; is_footer, is_footer_icon; ib_input_multiline, il_input_max_length, is_input_pattern, is_input_error; of_prompt that masks and requires; a disabled choice (of_add_choice, ab_enabled) |
| jsontree | of_get_layout, of_set_layout and ue_layout_changed (the folds, the selection, the line at the top); of_selected_addressable, of_selected_type, of_selected_count, of_copy_path; ue_node_rclicked (right click, Menu key); ib_find_decoded (the search in the decoded values, & toggle) |
| xmltree | of_find_xpath (every node of an XPath, walked by of_search_next); of_get_layout, of_set_layout and ue_layout_changed (the folds, the selection, the line at the top); of_selected_kind (KIND_* constants), of_selected_name, of_selected_namespace, of_copy_path; ue_node_rclicked (right click, Menu key); ib_find_decoded (the search in the decoded values, & toggle) |
| json | of_from_datastore and of_to_datastore (DataStore, DataWindow, DataWindowChild): a DataStore as an array of typed objects, and back; ISO 8601 dates (of_set_date, of_set_datetime, of_set_time, of_add_date, of_add_datetime, of_add_time, of_get_date, of_get_datetime, of_get_time); of_get_last_error and of_error_position (where a text is not JSON); of_escape_key |
| listbar | ue_item_invoked (a click on the entry, the one already selected included); ib_search, is_filter, ue_filter_changed (a search); of_from_datastore (DataStore, DataWindow, DataWindowChild), of_map and the ROLE_* constants (one row = one entry) |
| markdownview | is_base_path, ib_allow_html (a short list of inert HTML tags), ib_network_pictures, ib_remote_pictures, ib_tasks_editable and ue_task_toggled, ib_track_heading and ue_heading_visible, is_position, ii_zoom, of_selected_text, of_copy and Ctrl+Insert, the LINK_* constants; GitHub alerts, bare e-mail addresses and emoji |
| menubar | of_load_menu(menu): the whole bar from the PowerBuilder menu of a window, read again at each opening, its Clicked scripts run; of_loaded_item; of_insert_item (an entry at a rank) and of_clear_items (empty a cascade and keep the entry); of_open, of_close, of_is_open |
| pdfviewer | of_load_blob(blob) and of_load_blob(blob, string): a PDF held in a blob (read with SELECTBLOB), shown without a file, whatever its size; is_find (a text highlighted when the document opens); ib_navigation_pane (the reader's side panel); is_destination (open on a named destination of the PDF); ib_allow_search, ib_allow_rotate and ib_allow_fullscreen (the Search, Rotate and Full screen commands of the reader's toolbar) |
| picture | of_set_picture(blob): a picture held in memory (SelectBlob), like SetPicture of the native Picture; ib_clickable: the picture becomes a button for the keyboard (Tab, Enter, Space); the TIFF, WMF, EMF and RLE formats, converted on the fly; a name for screen readers that tells the badge and the failure |
| radialmenu | of_show_over(dragobject ado_control {, boolean ab_keyboard}): the wheel centred on a control, its first branch lit when it comes from the keyboard; on the branch handle, is_image (icon changed in place), is_tone (TONE_* constants of u_pbt_radialmenu) and is_group (radio group) |
| restclient | of_url and of_url_encode (an encoded URL query); of_post_form and of_post_form_async (an HTML form); of_oauth_client_credentials (an OAuth2 token renewed by itself); of_retrieve (DataStore, DataWindow, DataWindowChild: a JSON array as rows); the headers of one request (of_request and of_request_async, fourth argument as_headers); is_last_request; ib_check_revocation |
| statusbar | ib_spring (and a width of -1 in of_add_panel, of_insert_panel): a panel that takes the free room; of_dock_bottom (the bar at the bottom of its window); is_help and is_help_panel (the MicroHelp of a PowerBuilder frame); ib_announce (screen readers); the tooltip of an elided text |
| tilesbox | of_move_tile(as_keys, as_to_key, al_position): a tile sent by the code into another group, with its colours, badge and faces; Escape cancels a drag, the panel scrolls when the pointer nears its edge; a screen reader hears the badge and the band of a tile; an SVG icon stays sharp on a large tile; the header of a group lights up under the pointer; the "less motion" setting of Windows is honoured |
| statictext | ib_mnemonic (the & of a PowerBuilder label), ii_max_lines (at most N lines, "…"), il_max_log_lines and of_clear (a bounded log, emptied), ii_max_width (ceiling of ib_auto_width), ib_veto_links and ue_hyperlink_opening (deciding whether a link opens); a log is announced line by line to screen readers; disabled, the zones of the markup leave the Tab order |
| xml | of_get_number, of_get_decimal, of_get_longlong, of_get_boolean, of_get_date, of_get_datetime: the value at the XPath checked against its XML Schema type and read the same way on every machine (NULL and of_get_last_error() when it is not of that type) |
| xml | decimal, date, datetime, boolean overloads of of_leaf, of_element_attr and of_set_value: written with a point and in ISO 8601 whatever the machine |
12.7 buttonbar: key, label, then icon; the "&" and the chord #
The button bar spoke differently from the rest of the library: the icon before the label, the position as the second argument, and an is_shortcut that meant "Alt letter" where it means "chord" everywhere else — is_shortcut = "Ctrl+S" armed Alt+C. 5.0 aligns it with button, the toolbar and the PowerBuilder CommandButton.
| What | 4.0 | 5.0 |
|---|---|---|
| Add a button | uo.of_add_button("save", "img\save.png", "Save") | uo.of_add_button("save", "&Save", "img\save.png") |
| A text-only button | uo.of_add_button("ok", "", "OK") | uo.of_add_button("ok", "OK") |
| Insert a button | uo.of_insert_button("mid", 2, "", "Mid") | uo.of_insert_button("mid", "Mid", "", 2) |
| The Alt letter of a button | is_shortcut ← "S" (Alt+S) | the label "&Save", or uo.of_button("save").is_mnemonic = "S" |
| A chord on a button | uo.of_register_shortcut("Ctrl+S", "save") | the same, or uo.of_button("save").is_shortcut = "Ctrl+S" — shown in the tooltip |
| A "&" in a label | shown as is | marks the Alt letter; && for a written "&" |
| The badge | uo.of_button("inbox").il_badge = 3 | uo.of_button("inbox").is_badge = "3" (a text: "New", "!"); il_badge is still accepted |
The focused button, without is_default | painted with a full accent | its focus ring only |
is_shortcutof a button is a chord. During 5.0, a single letter is still read there as the Alt letter of 4.0 (it goes tois_mnemonic); write the "&" in the label instead. A chord the window can never fire (a letter alone,Ctrl+Shift) is refused:is_shortcutreads back empty,of_register_shortcutreturns-5.- A greyed button no longer steals a key. The greyed default button of a bar, or the Alt letter of a greyed button, leaves Enter and the letter to the window — they no longer go to the button of ANOTHER bar (two MDI sheets); the chord of a greyed button leaves its key to the window (a menu accelerator, for instance). The arrow keys skip a greyed button.
// 4.0 : the icon before the label
uo_bar.of_add_button(/*key*/ "save", /*image_file*/ "img\save.png", /*text*/ "Save")
// The Alt letter went to is_shortcut (the letter S alone), the chord to of_register_shortcut
uo_bar.of_register_shortcut(/*chord*/ "Ctrl+S", /*key*/ "save")
// 5.0 : key, label, icon - the "&" of the label gives Alt+S
uo_bar.of_add_button(/*key*/ "save", /*text*/ "&Save", /*image*/ "img\save.png")
// The chord is a property of the button, shown in its tooltip
uo_bar.of_button(/*key*/ "save").is_shortcut = "Ctrl+S"
The recipe: compile; a call of of_insert_button is reported (the position goes last). A three-argument of_add_button still compiles: swap the last two (the label, then the icon) — a button whose label is a file path shows you the ones left. Replace every one-letter is_shortcut with a "&" in the label, and double every "&" that must be shown (R&&D).
12.8 crosstab: the format of the values through is_format #
The crosstab wrote the numbers of a measure through a function with four or five arguments (decimals, thousands separator, symbol, symbol before), which held for every value of a field: the same field twice in Values — the amount, and its share of the total — could not have two formats. 5.0 puts it under the language of the charts and the gauges: a PowerBuilder display format in is_format, on the handle of the field (of_field) for all its values, or on the handle of one value (of_value(position), new) for it alone. Empty, a value takes the Format of the DataWindow column. No old name survives.
| What | 4.0 | 5.0 |
|---|---|---|
| The format of every value of a field | uo.of_set_value_format("amount", 2, "locale", "$", true) | uo.of_field("amount").is_format = "$#,##0.00" |
| A symbol after the number | uo.of_set_value_format("amount", 0, "", " EUR") | uo.of_field("amount").is_format = '#,##0" EUR"' |
| The format of one value (the same field twice) | — | uo.of_value(2).is_format = "#,##0.00" |
| Negatives in red | the chip menu only | uo.of_value(1).ib_negative_red = true |
| Back to the default format | uo.of_clear_value_format("amount") | uo.of_field("amount").is_format = "" (the Format of the DataWindow column) |
- The thousands separator of a value with no format stays
is_thousands, like the Options menu of the grid: that is what anof_set_value_formatwith an empty separator did. The currency the chip menu offers staysis_currency_symbol. - A value with no format now shows the Format of its column of the DataWindow, read by
of_from_datastore: an amount whose column carries#,##0.00is shown with two decimals without a line of code.
// 4.0 : decimals, thousands, symbol and its side as arguments - for every value of the field
uo_cross.of_set_value_format(/*field*/ "amount", /*decimals*/ 2, /*thousands*/ "locale", /*suffix*/ "$", /*symbol_before*/ true)
// 5.0 : a display format, written as in a DataWindow - for the field, then for its second value alone
uo_cross.of_field(/*field*/ "amount").is_format = "$#,##0.00"
uo_cross.of_value(/*position*/ 2).is_format = "#,##0"
The recipe: compile; every of_set_value_format and of_clear_value_format is reported. Write the format as in a DataWindow: ai_decimals gives the number of 0 after the point, a thousands separator gives the grouping , ("none": none), the symbol is written before or after (in quotes when it holds digits or spaces). The format of one value alone goes into of_value(<position>).is_format.
12.9 listbar: the right click carries its point, a layout is announced #
The side bar joins the library on three points: the right click of an entry gives its screen point like the one of the trees, the grids and the kanban; an order of the code that changes the layout announces it like a gesture; a greyed entry no longer becomes the selection. It also gains an event for the click on the entry already selected, a search and the building from a DataStore (12.6).
| What | 4.0 | 5.0 |
|---|---|---|
ue_item_rclicked | (string as_keys) | (string as_keys, long al_x, long al_y): the point in screen pixels; the Menu key and Shift+F10 raise it too |
of_set_layout that changes the layout | no event | one ue_layout_changed (never ue_section_toggled) |
of_move_item / of_move_section to the rank already held | ue_layout_changed | nothing: nothing moved |
of_select_item of a greyed entry | 0, it became the selection | -5, without asking ue_selection_changing; greying the entry already selected keeps it |
ib_auto_width read while the bar is in the rail | true | what the application set |
of_item of an address of one level ("nav") | reached the section | a handle that names nothing; a section is reached by of_section |
| The same letter typed twice | a prefix dd, often matching nothing | the next line that starts with it; a Space in the middle of a prefix belongs to it |
| A greyed entry under the pointer | no tooltip | its tooltip shows; the click still does nothing |
// 4.0 : PointerX() of the userobject - the menu opened too high under a ribbon
m_entry.PopMenu(PointerX(), PointerY())
// 5.0 : the pointer of the WINDOW for a PowerBuilder menu (al_x, al_y serve a menu of the library)
m_entry.PopMenu(parent.PointerX(), parent.PointerY())
The recipe: nothing refuses to compile — a script of ue_item_rclicked keeps as_keys. Open your menu at the pointer of the window (parent.PointerX()), or hand al_x, al_y to of_show of a contextmenu. Set the initial selection before switching ib_veto_selection on, and make sure your ue_layout_changed accepts the call of_set_layout now makes to it.
12.10 scheduler: the kind of a change and the values it had #
The calendar joins the Gantt chart: the question asked before a gesture says whether it is a move or a resize, and the events that follow give the values the appointment had — a log, an undo or a confirmation no longer keep their own copy of every appointment. A selection your code takes away is announced, and four calls now refuse what they accepted in silence.
| What | 4.0 | 5.0 |
|---|---|---|
ue_appointment_changing | (string as_key, string as_start, string as_end, string as_resource) | (string as_key, string as_kind, string as_start, string as_end, string as_resource): as_kind is CHANGE_MOVE or CHANGE_RESIZE |
ue_appointment_moved | (string as_key, string as_start, string as_end, string as_resource) | (string as_key, string as_start, string as_end, string as_resource, string as_old_start, string as_old_end, string as_old_resource) |
ue_appointment_resized | (string as_key, string as_start, string as_end) | (string as_key, string as_start, string as_end, string as_old_start, string as_old_end) |
| Your code removes, empties or reloads the selected appointment | no event | ue_selection_changed(""); of_reset stays silent |
of_add_appointment whose end comes before its start | 0, the end became start + 30 min | -5, of_get_last_error says why |
of_scroll_to_time("abc") | 0, nothing scrolled | -5 |
of_set_field on the column playing ROLE_KEY | 0, two appointments of one key | -5: a key changes by reloading |
of_show_appointment of an appointment hidden, filtered out or on a hidden resource | 0, the view left for a day where nothing could be seen | -5, nothing moves |
is_now set after a navigation of the user | brought the view back to its day | the view stays where the user went |
of_clear_appointments | kept the columns of the DataStore for of_map | forgets the DataStore: of_map accepts the columns of the next one |
// 5.0 : ue_appointment_changing event of uo_sched : (string as_key, string as_kind, string as_start, string as_end, string as_resource) returns boolean
// A resize keeps the day : only a move is checked
if as_kind = u_pbt_scheduler.CHANGE_RESIZE then return true
// Nothing on a Saturday or a Sunday : returning false puts the appointment back
if DayNumber(Date(Left(as_start, 10))) = 1 or DayNumber(Date(Left(as_start, 10))) = 7 then return false
return true
The recipe: nothing refuses to compile — a script of ue_appointment_changing, ue_appointment_moved or ue_appointment_resized keeps its arguments, the new ones are added. If your ue_selection_changed enables buttons, it now receives "" when the selected appointment leaves; read again the return codes of of_add_appointment, of_scroll_to_time, of_set_field and of_show_appointment, which may now return -5. To save the gestures without code, see ib_write_back.
12.11 shellexplorer: the error says its reason #
The shell explorer now gives, in ue_error as in ue_path_not_found, a reason your code can test — a REASON_* constant of u_pbt_shellexplorer, the same in every language of Windows. It no longer raises ue_selected for the folder already selected, and announces with ue_collapsed a branch it closes by itself. It also gains the right click on a folder (ue_node_rclicked) and the address of the root.
| What | 4.0 | 5.0 |
|---|---|---|
ue_error | (string as_message) | (string as_path, string as_reason, string as_message): the path ("" for the Desktop), a REASON_* constant, the text of the shell |
as_reason of ue_path_not_found | an English sentence (not found, outside the root, not a branch…) | a REASON_* constant (not_found, outside_root, not_a_branch…); not_shown for a path that exists but that the tree does not show |
| Selecting the folder already selected (a click, Home on the first row) | ue_selected | nothing |
| A branch the tree closes by itself (came back empty, refused by the shell) | no event | ue_collapsed |
ib_show_files, ib_show_hidden, is_file_filter, is_root written with their value | the tree is read again | nothing is read again; is_file_filter set without the files waits for them |
of_collapse of a path drawn twice | every row, one ue_collapsed each | the row of_select reaches, one ue_collapsed |
of_count(""), of_keys_at("", i) | the rows shown, as of_count() | the first level (the root), as of_count(is_root) |
// 5.0 : ue_error event of uo_tree : (string as_path, string as_reason, string as_message)
// Test the reason, never the text of the shell
if as_reason = u_pbt_shellexplorer.REASON_TIMEOUT then
st_status.text = "The network folder " + as_path + " does not answer"
else
st_status.text = as_message
end if
The recipe: nothing refuses to compile — a script of ue_error keeps as_message, the new arguments are added. A test on the TEXT of as_reason in ue_path_not_found ("not found", "outside the root") is written again with a REASON_* constant; an application that reloaded a pane at every ue_selected now does it once per change.
12.12 tilesbox: the right click carries its point, an order of the code is announced, the layout leaves the rights to the application #
The tiles box joins the library: its right click gives the screen point like the one of the trees, the grids and the kanban; an order of the code that moves a tile, folds a group or changes a size raises the same events as a gesture; the layout no longer carries the visibility, which stays the application's business. It also gains moving a tile into another group from the code (12.6).
| What | 4.0 | 5.0 |
|---|---|---|
ue_tile_context | (string as_keys) | ue_tile_rclicked (string as_keys, long al_x, long al_y): the point in screen pixels; the Menu key and Shift+F10 raise it too, at the bottom-left corner of the tile |
of_move_tile, of_insert_tile | integer ai_index | long al_position; an overload of_move_tile(as_keys, as_to_key, al_position) sends the tile into another group |
of_move_tile to another place | nothing | ue_tile_moved, ue_layout_changed |
ib_collapsed of a group set by the code | ue_group_toggled | ue_group_toggled, ue_layout_changed |
is_size set by the code | nothing | ue_layout_changed (never ue_tile_resized, which says the user chose it) |
is_size of an unknown size ("huge") | the tile became medium | refused: nothing is written, of_get_last_error says why; of_add_tile / of_insert_tile return -5 |
The layout (of_get_layout, ue_layout_changed) | carried the visibility of the groups and tiles | no longer carries it: of_set_layout never shows again what your code hid; a 4.0 layout is read without it |
of_set_layout that changes the layout | no event | one ue_layout_changed; -5 on a JSON that is not a layout ({}) |
of_tile / of_group of an address that names nothing | one handle per call, kept | the inert handle, the same for them all: it writes nothing and reads empty |
// 4.0 : the right click of a tile
// ue_tile_context event of uo_tiles : (string as_keys)
// 5.0 : the same script, under the new name, with the screen point
// ue_tile_rclicked event of uo_tiles : (string as_keys, long al_x, long al_y)
The recipe: compile; your script of ue_tile_context stays on an event that no longer exists — move it to ue_tile_rclicked, which keeps as_keys. If your ue_layout_changed saves the layout, it now also sees what your code changes; a ue_tile_moved that must only react to the user ignores the moves your code has just made. If you kept the visibility in the layout, set it from the code at opening (ib_visible), according to the rights.
12.13 tab: the right click carries its point, an applied layout is announced #
The tab joins the library: the right click of a tab, built-in menu off, gives its screen point like the one of the trees, the grids and the kanban, and of_set_layout that changes the layout announces it like a gesture. A drag given back to its place no longer announces anything. It also gains pages created on demand (ue_page_needed, of_supply_page), the double click (ue_tab_double_clicked), ib_cycle_keys, is_close_mode, ii_strip_width and, on a page, ib_modified and is_badge — see the page of the tab.
| What | 4.0 | 5.0 |
|---|---|---|
ue_tab_rclicked | (string as_key) | (string as_key, long al_x, long al_y): the point in screen pixels; the Menu key and Shift+F10 raise it too, at the bottom-left corner of the tab |
of_set_layout that changes the layout | no event | ue_layout_changed, once |
a drag given back to its place, of_move_page to its own place | ue_tab_reordered and ue_layout_changed | nothing: the order did not change |
several moves under of_set_redraw(false) | one ue_layout_changed per move | a single one, at the resume |
| Shift+F10 on a tab, built-in menu | the menu opened under the mouse | under the tab |
| vertical strip and long title | the strip took the width of the title | 40 % of the component at most, ellipsis; ii_strip_width fixes it |
il_accent of a page | the focus ring only | also underlines the active tab |
is_shortcut on the handle of a key no page has | registered: the key was taken for nothing | nothing is registered, of_get_last_error says why |
of_insert_page whose move fails | a negative code, the page stayed | a negative code, the page is taken out again |
// 4.0 : the right click of a tab, built-in menu off
// ue_tab_rclicked event of uo_tabs : (string as_key)
// 5.0 : the same script, with the screen point
// ue_tab_rclicked event of uo_tabs : (string as_key, long al_x, long al_y)
The recipe: nothing refuses to compile — a script of ue_tab_rclicked keeps as_key. Open your menu at the pointer of the window (parent.PointerX()), or hand al_x, al_y to of_show of a contextmenu. Make sure your ue_layout_changed accepts the call of_set_layout now makes to it.
12.14 soundplayer: the number of a sound, a refusal returned at once #
The sound player changes three things your code can see. Its events carry the number of the sound: ue_started, ue_ended and ue_failed receive a last argument, al_sound — the number of_play_over and of_enqueue now return (they returned 0), and that the new of_stop_sound takes. A source refused at once is a code: of_play, of_play_over, of_crossfade and of_preload return -5, the reason in of_get_last_error(), for an empty source, an http:// address, a malformed file:// address or a format refused by its name — and no longer raise ue_failed; the sound playing goes on. In the queue (of_enqueue), the refusal still comes through ue_failed, at its turn. Other -5: of_pause and of_resume with nothing to suspend or resume, of_beep and of_beep_sync at 0 Hz or 0 ms, of_meter out of 1 to 64 bars.
// Local variables
string ls_url
long ll_rc
// The address of the sound, typed by the user
ls_url = sle_url.text
// 4.0 : of_play returned 0, and an http:// address came back later through ue_failed
// 5.0 : the refusal is a code, at once ; of_get_last_error() gives the reason
ll_rc = inv_sound.of_play(/*source*/ ls_url)
if ll_rc = -5 then
MessageBox("Sound", inv_sound.of_get_last_error())
end if
What changes without asking anything of your code: of_stop now dies out over il_fade_ms, as the documentation promised (ue_stopped still comes at once); when il_timeout_ms runs out, only the sound of the synchronous call is cut — the background, the overlays and the queue go on; of_crossfade to a refused source keeps the track playing; of_level is 0 and of_spectrum returns no bar, meter off; of_equalizer(ab_on, ai_gains[]) sets back to 0 a band the array does not reach; of_clear_queue also forgets the sounds the queue already played; the messages of ue_failed follow the display language (as_reason stays the word to test). The player also gains the queue that moves (of_next, of_previous, of_queue_index, ue_source_changed, ib_queue_repeat), the loop without a gap (ib_gapless_loop, REASON_TOO_LONG), the segment (of_play_range), the mute (ib_muted) and the buffering (ue_buffering, of_is_buffering) — see the page of the sound player.
The recipe: nothing refuses to compile — a script of ue_started, ue_ended or ue_failed keeps its arguments, al_sound is added. Read again the return-code tests of of_play_over and of_enqueue (a = 0 becomes > 0), and the code that waited for ue_failed for an http:// address or an empty source: it now tests the -5 of the call.
12.15 toaster: the reason of a closing, a toast closed by the code always says so #
The toaster says why a toast closed: ue_toast_dismissed receives a last argument, as_reason — REASON_TIMEOUT, REASON_USER (its cross), REASON_CODE (of_close, of_close_all) or REASON_OWNER_CLOSED (its window closed). And every toast closed by the code announces it, even closed right after of_show, before it was drawn, or while it waited for room: an application that waited for ue_toast_dismissed to free its state no longer depends on a race.
| What | 4.0 | 5.0 |
|---|---|---|
ue_toast_dismissed | (long al_id, string as_key) | (long al_id, string as_key, string as_reason), constants REASON_* |
of_close of a toast not drawn yet, or waiting for room | nothing was raised | ue_toast_dismissed, REASON_CODE |
of_close of a toast of another toaster | closed it, the announce went to the other one | -5, nothing is closed, of_get_last_error says why |
the window of ipo_owner closes | its toasts went away without a word | ue_toast_dismissed, REASON_OWNER_CLOSED |
| a toaster destroyed, toasts on screen | they stayed, silent | the persistent ones and those with buttons close with it; the others finish on their own |
of_show before the display engine is ready | -6: "runtime missing" | -4: try again; of_get_last_error says why |
| corner of a toast anchored to the window | the whole window: the toast covered the title bar and its buttons | the client area (the frame's, in MDI) |
| a very long title | pushed the cross and the buttons out of the window | capped, it scrolls |
// 4.0
// ue_toast_dismissed event of inv_toaster : (long al_id, string as_key)
// 5.0 : the same script, with the reason
// ue_toast_dismissed event of inv_toaster : (long al_id, string as_key, string as_reason)
The recipe: nothing refuses to compile — a script of ue_toast_dismissed keeps al_id and as_key, as_reason is added. Read again the code that assumed a toast closed at once by of_close would say nothing: it now announces it. Toasts stay tied to the toaster that showed them: an of_close on the id of another toaster returns -5. The toaster also gains of_close_all (close all its toasts) and of_get_last_error — see the page of the toaster.
12.16 video: a refusal returned at once, a film and its subtitles in one call, the same film resumed #
The video player changes five things your code can see. A refusal is returned at once, as in the sound player (12.14): of_play(), of_play(source) and of_play_range return -5, the reason in of_get_last_error(), for an empty source, an http:// address or a format refused by its name (avi, wmv, flv) — and no longer raise ue_failed; the film playing goes on. The is_source property keeps its ue_failed: a property has no return code. The same film is not reloaded: of_play(source) or is_source on the film already loaded resumes it where it is (ue_resumed) instead of starting it over; of_seek(0) starts it over. A seek stays in the segment of of_play_range, the user's as well as of_seek: Home goes to the start of the segment, a click past its end to its end — before, Home left the extract and a click past it stopped the film. A playlist entry that cannot play raises ue_source_changed first, then one ue_failed — it came before, and twice. of_stop becomes a function: it returned nothing (a subroutine), it returns 0, or -2 when the component is not created — like of_stop of the web browser.
// Local variables
string ls_path
long ll_rc
// The film chosen by the user
ls_path = sle_film.text
// 4.0 : of_play returned 0, and an http:// address or an .avi came back later through ue_failed
// 5.0 : the refusal is a code, at once ; the reason is in of_get_last_error
ll_rc = uo_video.of_play(/*source*/ ls_path)
if ll_rc = -5 then
MessageBox("Video", uo_video.of_get_last_error())
end if
What changes without asking anything of your code: a marker reached by a seek WHILE PAUSED no longer raises ue_marker_reached (only ue_seeked); Space and the Play button of a player with no film no longer do anything (they raised ue_failed(REASON_NO_SOURCE)); the subtitle language the user chose follows to the next film of the playlist; an http:// poster is refused and is_poster reads back empty; a refused is_subtitles reads back empty; a subtitle file of the workstation that cannot be found raises ue_subtitles_failed(REASON_NOT_FOUND); the speed menu works at the keyboard and its arrows no longer change the volume; in full screen the bar shows at the keyboard; the remembered position (ib_remember_position) no longer depends on how the path is written, and only the last 200 films are kept (a position of 4.0 is read once more). The player gains of_play(source, subtitles) (the film and ITS subtitles: set before a second film, they went with the first one), ib_forward_seek, of_watched_ms, of_watched_percent, ue_watched_completely and ib_skip_failed — see the page of the video player.
The recipe: nothing refuses to compile. Read again the code that waited for ue_failed after of_play for an http:// address, an empty source or an .avi: it now tests the -5 of the call. Read again too a "Play" button that relied on of_play(source) to start over: add of_seek(0).
12.17 webbrowser: a gesture of the user is asked about, a page of of_show_html has no address #
With ib_veto_navigation = true, ue_navigating is now also asked for a gesture of the user: an address typed in the bar, Open link of the context menu, a new window opened by a click. In 4.0 these three paths did not ask. Only an address set by your code is never asked about, and nor is a redirection of the server: for a list of servers that also holds for redirections, set the new property is_allowed_hosts.
| What | 4.0 | 5.0 |
|---|---|---|
ue_navigating under the veto: address typed, Open link, new window | the page opened without a question | the question is asked; false keeps the page |
is_address, the bar, ue_load_completed after of_show_html | the whole page, encoded (data:text/html;charset=utf-8,…, up to 2 MB) | "" |
is_title of a page without <title> | its address | "" |
of_go_back, of_go_forward, of_stop | no return value | long: 0 once asked, -2 component not created |
ib_private changed after a page | is_address, is_title, the bar and the arrows kept the page before | everything reads empty: the view is new |
| Enter on an empty address bar | the page went blank | nothing |
| A page of the site is loading, address bar shown | Reload stays Reload | Reload becomes Stop, and comes back once the page is done |
The recipe: nothing refuses to compile, an ignored long compiles. A script of ue_navigating written for the links of the site now also sees the addresses typed by the user: if it decides on the address, let it compare its host, as the example of the component page does — or hand the list to is_allowed_hosts. The code that read as_url of ue_load_completed, or is_address, after of_show_html receives an empty string.
12.18 toolbar: the right click carries its point, an order of the code is announced #
The toolbar joins the library: the right click of a tool gives its screen point, like that of the trees, the grids and the tab, and moving a bar by ii_band / ii_index raises ue_bar_reordered like the gesture. Two adds refuse what they accepted silently, and a shortcut set where nothing lives is no longer registered. It also gains is_text on a bar, a name for every tool and field read by a screen reader, and a keyboard that crosses the fields — see the toolbar page.
| What | 4.0 | 5.0 |
|---|---|---|
ue_item_rclicked | (string as_keys) | (string as_keys, long al_x, long al_y): the point in screen pixels; the Menu key and Shift+F10 raise it too, at the bottom-left corner of the tool, and so does the right click of a field |
ii_band / ii_index moving a bar | ue_layout_changed | ue_bar_reordered, ue_layout_changed |
of_add_datepicker with a date that is not yyyy-mm-dd ("31/12/2026") | 0, the date shown as it was | -5, nothing is added |
of_add_menu_separator on an entry that holds no sub-entry | 0: the entry turned grey and could no longer be chosen | -5 |
is_shortcut or of_register_shortcut on an address where nothing lives, an entry holding a cascade or a choice of a list | registered: the key was taken in the whole window | nothing registered; of_register_shortcut returns -5, of_get_last_error says why |
| Ctrl+A, Ctrl+C, Ctrl+V, Ctrl+X, Ctrl+Z, Ctrl+Y in a field of the bar | the tool holding the chord fired | the field edits its text |
is_text of a date picker | kept and read back, never shown | ignored, reads "" |
// 4.0 : the right click of a tool
// ue_item_rclicked event of uo_toolbar : (string as_keys)
// 5.0 : the same script, with the screen point
// ue_item_rclicked event of uo_toolbar : (string as_keys, long al_x, long al_y)
The recipe: nothing refuses to compile — a script of ue_item_rclicked keeps as_keys. Open your menu at the point al_x, al_y (hand it to of_show of a contextmenu). Check that a script of ue_bar_reordered also accepts the moves your code makes, test the return code of of_add_datepicker when the date comes from a regional field, and set is_shortcut after the add of the tool or the entry.
12.19 The right click of an item carries its point: buttonbar, breadcrumb, chartcartesian, statusbar #
One rule for every right click on an item of the library: the event receives the key (or the address) of the item, then al_x, al_y, the point where to open a menu, in screen pixels — the pointer, or, from the keyboard (Menu key, Shift+F10), the bottom-left corner of the item (bottom-right in a right-to-left reading; the middle of a shape that is no rectangle: a point of a chart). A contextmenu of the library opens there as they are: uo_menu.of_show(al_x, al_y). Three events that did not carry it receive it; the status bar multiplied its own by the scale of the display, and a menu opened at that point landed far from the pointer on a display at 125 % or 150 %.
| What | 4.0 | 5.0 |
|---|---|---|
buttonbar · ue_button_rclicked | (string as_key) | (string as_key, long al_x, long al_y) |
breadcrumb · ue_item_rclicked | (string as_keys) | (string as_keys, long al_x, long al_y) |
chartcartesian · ue_point_rclicked | (string as_key, long al_index, double ad_value) | (string as_key, long al_index, double ad_value, long al_x, long al_y) |
statusbar · al_x, al_y of ue_panel_rclicked | multiplied by the scale of the display | the point as the page reads it, like every right click |
// 5.0 : the menu of a button, opened where the user right-clicked it
// ue_button_rclicked event of uo_buttons : (string as_key, long al_x, long al_y)
is_menu_button = as_key
uo_menu.of_show(/*x*/ al_x, /*y*/ al_y)
The recipe: nothing refuses to compile — a script of these events keeps its arguments. Open your menu at the point al_x, al_y (hand it to of_show of a contextmenu); a PowerBuilder menu keeps PopMenu(PointerX(), PointerY()) of your window. A script that corrected the scale of the coordinates of ue_panel_rclicked itself must no longer do it.
12.20 The foundation: a component's error is its own, every verb returns a code #
Five changes touch the whole library, or a whole family of components. Only one refuses to compile: is_last_error of a non-visual component, now of_get_last_error().
| What | 4.0 | 5.0 |
|---|---|---|
of_get_last_error() of a visual component | the last message of the DLL, one for the whole process — often another component's | what happened to this component: a name refused, or a call of this component to the DLL, whose reason is read at the moment it failed; empty otherwise |
The reason a non-visual component failed (crypto, restclient, soundplayer, speechout, xml, u_pbt_regex, u_pbt_zip) | inv.is_last_error | inv.of_get_last_error() |
of_stop, of_close, of_reset of the non-visual components (commandpalette, crypto, messagebox, restclient, soundplayer, speechout, toaster, xml) | no return value | a long, 0 once done — like the visual components |
of_set_property("tooltip", …) and super_tooltip_* on a component without a tooltip (webbrowser, pdfviewer, radialmenu, progressbar) | set a tooltip the documentation says does not exist | -5, and of_get_last_error() says why |
The shortcut of a PowerBuilder menu taken over (of_load_menu of menubar and commandpalette) | Ctrl++, PageUp, Insert (menubar); nothing past F12 (palette) | one writing, the contextmenu's: Ctrl+Plus, PgUp, Ins, F13 to F24, Num 0 to Num 9, Num + |
// Local variables
string ls_why
// 4.0 : ls_why = inv_crypto.is_last_error
// 5.0 : the reason of a failure, by the same method as every component
ls_why = inv_crypto.of_get_last_error()
The recipe: the compiler shows each .is_last_error to replace with .of_get_last_error(). A call to of_stop, of_close or of_reset written as a statement still compiles. A script that read of_get_last_error() of a component to learn the failure of another call (an export of the DLL called directly, another component) now reads that component's own reason, or nothing: ask the one that failed.
Added, nothing to rework: is_accessible_name and is_accessible_description on every visual component — the name and the description a screen reader says (3.4); of_from_datastore of a DataWindow or a DataWindowChild on crosstab and datagrid, as on the other data-bound components; the full form of of_insert_command (commandpalette), which takes the hint, the shortcut and the keywords as of_add_command does, with a long position.