diff options
author | Hans Goudey <h.goudey@me.com> | 2022-04-03 00:17:48 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-04-03 00:17:48 +0300 |
commit | 4537eb0c3b1678a623510570fb7528bf53174b2f (patch) | |
tree | 6d91005449c641b5116cbbf96780159e540b13a1 /source/blender/editors/interface/interface_query.c | |
parent | 351c00d29ab1d41867bfbae77b92625e5bf442e6 (diff) |
Cleanup: Remove interface region files to C++
Moves all `interface_region*` files to C++ except for the tooptip region
which is slightly more complicated. Also move a few other files as well.
This helps to simplify and speed up code, especially through the use
of better C++ data structures. This change builds on all platforms on
the buildbot.
Diffstat (limited to 'source/blender/editors/interface/interface_query.c')
-rw-r--r-- | source/blender/editors/interface/interface_query.c | 809 |
1 files changed, 0 insertions, 809 deletions
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c deleted file mode 100644 index 4703367671d..00000000000 --- a/source/blender/editors/interface/interface_query.c +++ /dev/null @@ -1,809 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup edinterface - * - * Utilities to inspect the interface, extract information. - */ - -#include "BLI_listbase.h" -#include "BLI_math.h" -#include "BLI_rect.h" -#include "BLI_string.h" -#include "BLI_utildefines.h" - -#include "DNA_screen_types.h" - -#include "UI_interface.h" -#include "UI_view2d.h" - -#include "RNA_access.h" - -#include "interface_intern.h" - -#include "WM_api.h" -#include "WM_types.h" - -/* -------------------------------------------------------------------- */ -/** \name Button (#uiBut) State - * \{ */ - -bool ui_but_is_editable(const uiBut *but) -{ - return !ELEM(but->type, - UI_BTYPE_LABEL, - UI_BTYPE_SEPR, - UI_BTYPE_SEPR_LINE, - UI_BTYPE_ROUNDBOX, - UI_BTYPE_LISTBOX, - UI_BTYPE_PROGRESS_BAR); -} - -bool ui_but_is_editable_as_text(const uiBut *but) -{ - return ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_SEARCH_MENU); -} - -bool ui_but_is_toggle(const uiBut *but) -{ - return ELEM(but->type, - UI_BTYPE_BUT_TOGGLE, - UI_BTYPE_TOGGLE, - UI_BTYPE_ICON_TOGGLE, - UI_BTYPE_ICON_TOGGLE_N, - UI_BTYPE_TOGGLE_N, - UI_BTYPE_CHECKBOX, - UI_BTYPE_CHECKBOX_N, - UI_BTYPE_ROW, - UI_BTYPE_TREEROW); -} - -bool ui_but_is_interactive(const uiBut *but, const bool labeledit) -{ - /* NOTE: #UI_BTYPE_LABEL is included for highlights, this allows drags. */ - if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) { - return false; - } - if (ELEM(but->type, UI_BTYPE_ROUNDBOX, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_LISTBOX)) { - return false; - } - if (but->flag & UI_HIDDEN) { - return false; - } - if (but->flag & UI_SCROLLED) { - return false; - } - if ((but->type == UI_BTYPE_TEXT) && - (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) && !labeledit) { - return false; - } - if ((but->type == UI_BTYPE_LISTROW) && labeledit) { - return false; - } - - return true; -} - -bool UI_but_is_utf8(const uiBut *but) -{ - if (but->rnaprop) { - const int subtype = RNA_property_subtype(but->rnaprop); - return !(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING)); - } - return !(but->flag & UI_BUT_NO_UTF8); -} - -#ifdef USE_UI_POPOVER_ONCE -bool ui_but_is_popover_once_compat(const uiBut *but) -{ - return (ELEM(but->type, UI_BTYPE_BUT, UI_BTYPE_DECORATOR) || ui_but_is_toggle(but)); -} -#endif - -bool ui_but_has_array_value(const uiBut *but) -{ - return (but->rnapoin.data && but->rnaprop && - ELEM(RNA_property_subtype(but->rnaprop), - PROP_COLOR, - PROP_TRANSLATION, - PROP_DIRECTION, - PROP_VELOCITY, - PROP_ACCELERATION, - PROP_MATRIX, - PROP_EULER, - PROP_QUATERNION, - PROP_AXISANGLE, - PROP_XYZ, - PROP_XYZ_LENGTH, - PROP_COLOR_GAMMA, - PROP_COORDS)); -} - -static wmOperatorType *g_ot_tool_set_by_id = NULL; -bool UI_but_is_tool(const uiBut *but) -{ - /* very evil! */ - if (but->optype != NULL) { - if (g_ot_tool_set_by_id == NULL) { - g_ot_tool_set_by_id = WM_operatortype_find("WM_OT_tool_set_by_id", false); - } - if (but->optype == g_ot_tool_set_by_id) { - return true; - } - } - return false; -} - -bool UI_but_has_tooltip_label(const uiBut *but) -{ - if ((but->drawstr[0] == '\0') && !ui_block_is_popover(but->block)) { - return UI_but_is_tool(but); - } - return false; -} - -int ui_but_icon(const uiBut *but) -{ - if (!(but->flag & UI_HAS_ICON)) { - return ICON_NONE; - } - - /* Consecutive icons can be toggle between. */ - if (but->drawflag & UI_BUT_ICON_REVERSE) { - return but->icon - but->iconadd; - } - return but->icon + but->iconadd; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Button (#uiBut) Spatial - * \{ */ - -void ui_but_pie_dir(RadialDirection dir, float vec[2]) -{ - float angle; - - BLI_assert(dir != UI_RADIAL_NONE); - - angle = DEG2RADF((float)ui_radial_dir_to_angle[dir]); - vec[0] = cosf(angle); - vec[1] = sinf(angle); -} - -static bool ui_but_isect_pie_seg(const uiBlock *block, const uiBut *but) -{ - const float angle_range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_4 : - M_PI_4 / 2.0; - float vec[2]; - - if (block->pie_data.flags & UI_PIE_INVALID_DIR) { - return false; - } - - ui_but_pie_dir(but->pie_dir, vec); - - if (saacos(dot_v2v2(vec, block->pie_data.pie_dir)) < angle_range) { - return true; - } - - return false; -} - -bool ui_but_contains_pt(const uiBut *but, float mx, float my) -{ - return BLI_rctf_isect_pt(&but->rect, mx, my); -} - -bool ui_but_contains_rect(const uiBut *but, const rctf *rect) -{ - return BLI_rctf_isect(&but->rect, rect, NULL); -} - -bool ui_but_contains_point_px(const uiBut *but, const ARegion *region, const int xy[2]) -{ - uiBlock *block = but->block; - if (!ui_region_contains_point_px(region, xy)) { - return false; - } - - float mx = xy[0], my = xy[1]; - ui_window_to_block_fl(region, block, &mx, &my); - - if (but->pie_dir != UI_RADIAL_NONE) { - if (!ui_but_isect_pie_seg(block, but)) { - return false; - } - } - else if (!ui_but_contains_pt(but, mx, my)) { - return false; - } - - return true; -} - -bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *region, const wmEvent *event) -{ - rcti rect; - int x = event->xy[0], y = event->xy[1]; - - ui_window_to_block(region, but->block, &x, &y); - - BLI_rcti_rctf_copy(&rect, &but->rect); - - if (but->imb || but->type == UI_BTYPE_COLOR) { - /* use button size itself */ - } - else if (but->drawflag & UI_BUT_ICON_LEFT) { - rect.xmax = rect.xmin + (BLI_rcti_size_y(&rect)); - } - else { - const int delta = BLI_rcti_size_x(&rect) - BLI_rcti_size_y(&rect); - rect.xmin += delta / 2; - rect.xmax -= delta / 2; - } - - return BLI_rcti_isect_pt(&rect, x, y); -} - -static uiBut *ui_but_find(const ARegion *region, - const uiButFindPollFn find_poll, - const void *find_custom_data) -{ - LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { - LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) { - if (find_poll && find_poll(but, find_custom_data) == false) { - continue; - } - return but; - } - } - - return NULL; -} - -uiBut *ui_but_find_mouse_over_ex(const ARegion *region, - const int xy[2], - const bool labeledit, - const uiButFindPollFn find_poll, - const void *find_custom_data) -{ - uiBut *butover = NULL; - - if (!ui_region_contains_point_px(region, xy)) { - return NULL; - } - LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { - float mx = xy[0], my = xy[1]; - ui_window_to_block_fl(region, block, &mx, &my); - - LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) { - if (find_poll && find_poll(but, find_custom_data) == false) { - continue; - } - if (ui_but_is_interactive(but, labeledit)) { - if (but->pie_dir != UI_RADIAL_NONE) { - if (ui_but_isect_pie_seg(block, but)) { - butover = but; - break; - } - } - else if (ui_but_contains_pt(but, mx, my)) { - butover = but; - break; - } - } - } - - /* CLIP_EVENTS prevents the event from reaching other blocks */ - if (block->flag & UI_BLOCK_CLIP_EVENTS) { - /* check if mouse is inside block */ - if (BLI_rctf_isect_pt(&block->rect, mx, my)) { - break; - } - } - } - - return butover; -} - -uiBut *ui_but_find_mouse_over(const ARegion *region, const wmEvent *event) -{ - return ui_but_find_mouse_over_ex(region, event->xy, event->modifier & KM_CTRL, NULL, NULL); -} - -uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px) -{ - if (!ui_region_contains_rect_px(region, rect_px)) { - return NULL; - } - - /* Currently no need to expose this at the moment. */ - const bool labeledit = true; - rctf rect_px_fl; - BLI_rctf_rcti_copy(&rect_px_fl, rect_px); - uiBut *butover = NULL; - - LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { - rctf rect_block; - ui_window_to_block_rctf(region, block, &rect_block, &rect_px_fl); - - LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) { - if (ui_but_is_interactive(but, labeledit)) { - /* No pie menu support. */ - BLI_assert(but->pie_dir == UI_RADIAL_NONE); - if (ui_but_contains_rect(but, &rect_block)) { - butover = but; - break; - } - } - } - - /* CLIP_EVENTS prevents the event from reaching other blocks */ - if (block->flag & UI_BLOCK_CLIP_EVENTS) { - /* check if mouse is inside block */ - if (BLI_rctf_isect(&block->rect, &rect_block, NULL)) { - break; - } - } - } - return butover; -} - -uiBut *ui_list_find_mouse_over_ex(const ARegion *region, const int xy[2]) -{ - if (!ui_region_contains_point_px(region, xy)) { - return NULL; - } - LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { - float mx = xy[0], my = xy[1]; - ui_window_to_block_fl(region, block, &mx, &my); - LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) { - if (but->type == UI_BTYPE_LISTBOX && ui_but_contains_pt(but, mx, my)) { - return but; - } - } - } - - return NULL; -} - -uiBut *ui_list_find_mouse_over(const ARegion *region, const wmEvent *event) -{ - if (event == NULL) { - /* If there is no info about the mouse, just act as if there is nothing underneath it. */ - return NULL; - } - return ui_list_find_mouse_over_ex(region, event->xy); -} - -uiList *UI_list_find_mouse_over(const ARegion *region, const wmEvent *event) -{ - uiBut *list_but = ui_list_find_mouse_over(region, event); - if (!list_but) { - return NULL; - } - - return list_but->custom_data; -} - -static bool ui_list_contains_row(const uiBut *listbox_but, const uiBut *listrow_but) -{ - BLI_assert(listbox_but->type == UI_BTYPE_LISTBOX); - BLI_assert(listrow_but->type == UI_BTYPE_LISTROW); - /* The list box and its rows have the same RNA data (active data pointer/prop). */ - return ui_but_rna_equals(listbox_but, listrow_but); -} - -static bool ui_but_is_listbox_with_row(const uiBut *but, const void *customdata) -{ - const uiBut *row_but = customdata; - return (but->type == UI_BTYPE_LISTBOX) && ui_list_contains_row(but, row_but); -} - -uiBut *ui_list_find_from_row(const ARegion *region, const uiBut *row_but) -{ - return ui_but_find(region, ui_but_is_listbox_with_row, row_but); -} - -static bool ui_but_is_listrow(const uiBut *but, const void *UNUSED(customdata)) -{ - return but->type == UI_BTYPE_LISTROW; -} - -uiBut *ui_list_row_find_mouse_over(const ARegion *region, const int xy[2]) -{ - return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_listrow, NULL); -} - -struct ListRowFindIndexData { - int index; - uiBut *listbox; -}; - -static bool ui_but_is_listrow_at_index(const uiBut *but, const void *customdata) -{ - const struct ListRowFindIndexData *find_data = customdata; - - return ui_but_is_listrow(but, NULL) && ui_list_contains_row(find_data->listbox, but) && - (but->hardmax == find_data->index); -} - -uiBut *ui_list_row_find_from_index(const ARegion *region, const int index, uiBut *listbox) -{ - BLI_assert(listbox->type == UI_BTYPE_LISTBOX); - struct ListRowFindIndexData data = { - .index = index, - .listbox = listbox, - }; - return ui_but_find(region, ui_but_is_listrow_at_index, &data); -} - -static bool ui_but_is_treerow(const uiBut *but, const void *UNUSED(customdata)) -{ - return but->type == UI_BTYPE_TREEROW; -} - -uiBut *ui_tree_row_find_mouse_over(const ARegion *region, const int xy[2]) -{ - return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_treerow, NULL); -} - -static bool ui_but_is_active_treerow(const uiBut *but, const void *customdata) -{ - if (!ui_but_is_treerow(but, customdata)) { - return false; - } - - const uiButTreeRow *treerow_but = (const uiButTreeRow *)but; - return UI_tree_view_item_is_active(treerow_but->tree_item); -} - -uiBut *ui_tree_row_find_active(const ARegion *region) -{ - return ui_but_find(region, ui_but_is_active_treerow, NULL); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Button (#uiBut) Relations - * \{ */ - -uiBut *ui_but_prev(uiBut *but) -{ - while (but->prev) { - but = but->prev; - if (ui_but_is_editable(but)) { - return but; - } - } - return NULL; -} - -uiBut *ui_but_next(uiBut *but) -{ - while (but->next) { - but = but->next; - if (ui_but_is_editable(but)) { - return but; - } - } - return NULL; -} - -uiBut *ui_but_first(uiBlock *block) -{ - LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - if (ui_but_is_editable(but)) { - return but; - } - } - return NULL; -} - -uiBut *ui_but_last(uiBlock *block) -{ - uiBut *but; - - but = block->buttons.last; - while (but) { - if (ui_but_is_editable(but)) { - return but; - } - but = but->prev; - } - return NULL; -} - -bool ui_but_is_cursor_warp(const uiBut *but) -{ - if (U.uiflag & USER_CONTINUOUS_MOUSE) { - if (ELEM(but->type, - UI_BTYPE_NUM, - UI_BTYPE_NUM_SLIDER, - UI_BTYPE_TRACK_PREVIEW, - UI_BTYPE_HSVCUBE, - UI_BTYPE_HSVCIRCLE, - UI_BTYPE_CURVE, - UI_BTYPE_CURVEPROFILE)) { - return true; - } - } - - return false; -} - -bool ui_but_contains_password(const uiBut *but) -{ - return but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Button (#uiBut) Text - * \{ */ - -size_t ui_but_drawstr_len_without_sep_char(const uiBut *but) -{ - if (but->flag & UI_BUT_HAS_SEP_CHAR) { - const char *str_sep = strrchr(but->drawstr, UI_SEP_CHAR); - if (str_sep != NULL) { - return (str_sep - but->drawstr); - } - } - return strlen(but->drawstr); -} - -size_t ui_but_drawstr_without_sep_char(const uiBut *but, char *str, size_t str_maxlen) -{ - size_t str_len_clip = ui_but_drawstr_len_without_sep_char(but); - return BLI_strncpy_rlen(str, but->drawstr, min_zz(str_len_clip + 1, str_maxlen)); -} - -size_t ui_but_tip_len_only_first_line(const uiBut *but) -{ - if (but->tip == NULL) { - return 0; - } - - const char *str_sep = strchr(but->tip, '\n'); - if (str_sep != NULL) { - return (str_sep - but->tip); - } - return strlen(but->tip); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Block (#uiBlock) State - * \{ */ - -uiBut *ui_block_active_but_get(const uiBlock *block) -{ - LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - if (but->active) { - return but; - } - } - - return NULL; -} - -bool ui_block_is_menu(const uiBlock *block) -{ - return (((block->flag & UI_BLOCK_LOOP) != 0) && - /* non-menu popups use keep-open, so check this is off */ - ((block->flag & UI_BLOCK_KEEP_OPEN) == 0)); -} - -bool ui_block_is_popover(const uiBlock *block) -{ - return (block->flag & UI_BLOCK_POPOVER) != 0; -} - -bool ui_block_is_pie_menu(const uiBlock *block) -{ - return ((block->flag & UI_BLOCK_RADIAL) != 0); -} - -bool ui_block_is_popup_any(const uiBlock *block) -{ - return (ui_block_is_menu(block) || ui_block_is_popover(block) || ui_block_is_pie_menu(block)); -} - -static const uiBut *ui_but_next_non_separator(const uiBut *but) -{ - for (; but; but = but->next) { - if (!ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) { - return but; - } - } - return NULL; -} - -bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title) -{ - const uiBut *but = block->buttons.first; - if (skip_title) { - /* Skip the first label, since popups often have a title, - * we may want to consider the block empty in this case. */ - but = ui_but_next_non_separator(but); - if (but && but->type == UI_BTYPE_LABEL) { - but = but->next; - } - } - return (ui_but_next_non_separator(but) == NULL); -} - -bool UI_block_is_empty(const uiBlock *block) -{ - return UI_block_is_empty_ex(block, false); -} - -bool UI_block_can_add_separator(const uiBlock *block) -{ - if (ui_block_is_menu(block) && !ui_block_is_pie_menu(block)) { - const uiBut *but = block->buttons.last; - return (but && !ELEM(but->type, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR)); - } - return true; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Block (#uiBlock) Spatial - * \{ */ - -uiBlock *ui_block_find_mouse_over_ex(const ARegion *region, const int xy[2], bool only_clip) -{ - if (!ui_region_contains_point_px(region, xy)) { - return NULL; - } - LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { - if (only_clip) { - if ((block->flag & UI_BLOCK_CLIP_EVENTS) == 0) { - continue; - } - } - float mx = xy[0], my = xy[1]; - ui_window_to_block_fl(region, block, &mx, &my); - if (BLI_rctf_isect_pt(&block->rect, mx, my)) { - return block; - } - } - return NULL; -} - -uiBlock *ui_block_find_mouse_over(const ARegion *region, const wmEvent *event, bool only_clip) -{ - return ui_block_find_mouse_over_ex(region, event->xy, only_clip); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Region (#ARegion) State - * \{ */ - -uiBut *ui_region_find_active_but(ARegion *region) -{ - LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { - uiBut *but = ui_block_active_but_get(block); - if (but) { - return but; - } - } - - return NULL; -} - -uiBut *ui_region_find_first_but_test_flag(ARegion *region, int flag_include, int flag_exclude) -{ - LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { - LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - if (((but->flag & flag_include) == flag_include) && ((but->flag & flag_exclude) == 0)) { - return but; - } - } - } - - return NULL; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Region (#ARegion) Spatial - * \{ */ - -bool ui_region_contains_point_px(const ARegion *region, const int xy[2]) -{ - rcti winrct; - ui_region_winrct_get_no_margin(region, &winrct); - if (!BLI_rcti_isect_pt_v(&winrct, xy)) { - return false; - } - - /* also, check that with view2d, that the mouse is not over the scroll-bars - * NOTE: care is needed here, since the mask rect may include the scroll-bars - * even when they are not visible, so we need to make a copy of the mask to - * use to check - */ - if (region->v2d.mask.xmin != region->v2d.mask.xmax) { - const View2D *v2d = ®ion->v2d; - int mx = xy[0], my = xy[1]; - - ui_window_to_region(region, &mx, &my); - if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) || - UI_view2d_mouse_in_scrollers(region, ®ion->v2d, xy)) { - return false; - } - } - - return true; -} - -bool ui_region_contains_rect_px(const ARegion *region, const rcti *rect_px) -{ - rcti winrct; - ui_region_winrct_get_no_margin(region, &winrct); - if (!BLI_rcti_isect(&winrct, rect_px, NULL)) { - return false; - } - - /* See comment in 'ui_region_contains_point_px' */ - if (region->v2d.mask.xmin != region->v2d.mask.xmax) { - const View2D *v2d = ®ion->v2d; - rcti rect_region; - ui_window_to_region_rcti(region, &rect_region, rect_px); - if (!BLI_rcti_isect(&v2d->mask, &rect_region, NULL) || - UI_view2d_rect_in_scrollers(region, ®ion->v2d, rect_px)) { - return false; - } - } - - return true; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Screen (#bScreen) Spatial - * \{ */ - -ARegion *ui_screen_region_find_mouse_over_ex(bScreen *screen, const int xy[2]) -{ - LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { - rcti winrct; - - ui_region_winrct_get_no_margin(region, &winrct); - - if (BLI_rcti_isect_pt_v(&winrct, xy)) { - return region; - } - } - return NULL; -} - -ARegion *ui_screen_region_find_mouse_over(bScreen *screen, const wmEvent *event) -{ - return ui_screen_region_find_mouse_over_ex(screen, event->xy); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Manage Internal State - * \{ */ - -void ui_interface_tag_script_reload_queries(void) -{ - g_ot_tool_set_by_id = NULL; -} - -/** \} */ |