Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-04-03 00:17:48 +0300
committerHans Goudey <h.goudey@me.com>2022-04-03 00:17:48 +0300
commit4537eb0c3b1678a623510570fb7528bf53174b2f (patch)
tree6d91005449c641b5116cbbf96780159e540b13a1 /source/blender/editors/interface/interface_region_menu_popup.c
parent351c00d29ab1d41867bfbae77b92625e5bf442e6 (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_region_menu_popup.c')
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c670
1 files changed, 0 insertions, 670 deletions
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
deleted file mode 100644
index 7d8f4315710..00000000000
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later
- * Copyright 2008 Blender Foundation. All rights reserved. */
-
-/** \file
- * \ingroup edinterface
- *
- * PopUp Menu Region
- */
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_userdef_types.h"
-
-#include "BLI_listbase.h"
-#include "BLI_math.h"
-
-#include "BLI_ghash.h"
-#include "BLI_rect.h"
-#include "BLI_string.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_context.h"
-#include "BKE_report.h"
-#include "BKE_screen.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
-
-#include "UI_interface.h"
-
-#include "BLT_translation.h"
-
-#include "ED_screen.h"
-
-#include "interface_intern.h"
-#include "interface_regions_intern.h"
-
-/* -------------------------------------------------------------------- */
-/** \name Utility Functions
- * \{ */
-
-bool ui_but_menu_step_poll(const uiBut *but)
-{
- BLI_assert(but->type == UI_BTYPE_MENU);
-
- /* currently only RNA buttons */
- return ((but->menu_step_func != NULL) ||
- (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM));
-}
-
-int ui_but_menu_step(uiBut *but, int direction)
-{
- if (ui_but_menu_step_poll(but)) {
- if (but->menu_step_func) {
- return but->menu_step_func(but->block->evil_C, direction, but->poin);
- }
-
- const int curval = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
- return RNA_property_enum_step(
- but->block->evil_C, &but->rnapoin, but->rnaprop, curval, direction);
- }
-
- printf("%s: cannot cycle button '%s'\n", __func__, but->str);
- return 0;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Popup Menu Memory
- *
- * Support menu-memory, a feature that positions the cursor
- * over the previously used menu item.
- *
- * \note This is stored for each unique menu title.
- * \{ */
-
-static uint ui_popup_string_hash(const char *str, const bool use_sep)
-{
- /* sometimes button contains hotkey, sometimes not, strip for proper compare */
- int hash;
- const char *delimit = use_sep ? strrchr(str, UI_SEP_CHAR) : NULL;
-
- if (delimit) {
- hash = BLI_ghashutil_strhash_n(str, delimit - str);
- }
- else {
- hash = BLI_ghashutil_strhash(str);
- }
-
- return hash;
-}
-
-uint ui_popup_menu_hash(const char *str)
-{
- return BLI_ghashutil_strhash(str);
-}
-
-/* but == NULL read, otherwise set */
-static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but)
-{
- static uint mem[256];
- static bool first = true;
-
- const uint hash = block->puphash;
- const uint hash_mod = hash & 255;
-
- if (first) {
- /* init */
- memset(mem, -1, sizeof(mem));
- first = 0;
- }
-
- if (but) {
- /* set */
- mem[hash_mod] = ui_popup_string_hash(but->str, but->flag & UI_BUT_HAS_SEP_CHAR);
- return NULL;
- }
-
- /* get */
- LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) {
- if (mem[hash_mod] ==
- ui_popup_string_hash(but_iter->str, but_iter->flag & UI_BUT_HAS_SEP_CHAR)) {
- return but_iter;
- }
- }
-
- return NULL;
-}
-
-uiBut *ui_popup_menu_memory_get(uiBlock *block)
-{
- return ui_popup_menu_memory__internal(block, NULL);
-}
-
-void ui_popup_menu_memory_set(uiBlock *block, uiBut *but)
-{
- ui_popup_menu_memory__internal(block, but);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Popup Menu with Callback or String
- * \{ */
-
-struct uiPopupMenu {
- uiBlock *block;
- uiLayout *layout;
- uiBut *but;
- ARegion *butregion;
-
- int mx, my;
- bool popup, slideout;
-
- uiMenuCreateFunc menu_func;
- void *menu_arg;
-};
-
-static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
-{
- uiBlock *block;
- uiPopupMenu *pup = arg_pup;
- int minwidth, width, height;
- char direction;
- bool flip;
-
- if (pup->menu_func) {
- pup->block->handle = handle;
- pup->menu_func(C, pup->layout, pup->menu_arg);
- pup->block->handle = NULL;
- }
-
- /* Find block minimum width. */
- if (uiLayoutGetUnitsX(pup->layout) != 0.0f) {
- /* Use the minimum width from the layout if it's set. */
- minwidth = uiLayoutGetUnitsX(pup->layout) * UI_UNIT_X;
- }
- else if (pup->but) {
- /* Minimum width to enforce. */
- if (pup->but->drawstr[0]) {
- minwidth = BLI_rctf_size_x(&pup->but->rect);
- }
- else {
- /* For buttons with no text, use the minimum (typically icon only). */
- minwidth = UI_MENU_WIDTH_MIN;
- }
- }
- else {
- minwidth = UI_MENU_WIDTH_MIN;
- }
-
- /* Find block direction. */
- if (pup->but) {
- if (pup->block->direction != 0) {
- /* allow overriding the direction from menu_func */
- direction = pup->block->direction;
- }
- else {
- direction = UI_DIR_DOWN;
- }
- }
- else {
- direction = UI_DIR_DOWN;
- }
-
- flip = (direction == UI_DIR_DOWN);
-
- block = pup->block;
-
- /* in some cases we create the block before the region,
- * so we set it delayed here if necessary */
- if (BLI_findindex(&handle->region->uiblocks, block) == -1) {
- UI_block_region_set(block, handle->region);
- }
-
- block->direction = direction;
-
- UI_block_layout_resolve(block, &width, &height);
-
- UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
-
- if (pup->popup) {
- int offset[2];
-
- uiBut *but_activate = NULL;
- UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- UI_block_direction_set(block, direction);
-
- /* offset the mouse position, possibly based on earlier selection */
- uiBut *bt;
- if ((block->flag & UI_BLOCK_POPUP_MEMORY) && (bt = ui_popup_menu_memory_get(block))) {
- /* position mouse on last clicked item, at 0.8*width of the
- * button, so it doesn't overlap the text too much, also note
- * the offset is negative because we are inverse moving the
- * block to be under the mouse */
- offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
- offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
-
- if (ui_but_is_editable(bt)) {
- but_activate = bt;
- }
- }
- else {
- /* position mouse at 0.8*width of the button and below the tile
- * on the first item */
- offset[0] = 0;
- LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) {
- offset[0] = min_ii(offset[0],
- -(but_iter->rect.xmin + 0.8f * BLI_rctf_size_x(&but_iter->rect)));
- }
-
- offset[1] = 2.1 * UI_UNIT_Y;
-
- LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) {
- if (ui_but_is_editable(but_iter)) {
- but_activate = but_iter;
- break;
- }
- }
- }
-
- /* in rare cases this is needed since moving the popup
- * to be within the window bounds may move it away from the mouse,
- * This ensures we set an item to be active. */
- if (but_activate) {
- ui_but_activate_over(C, handle->region, but_activate);
- }
-
- block->minbounds = minwidth;
- UI_block_bounds_set_menu(block, 1, offset);
- }
- else {
- /* for a header menu we set the direction automatic */
- if (!pup->slideout && flip) {
- ARegion *region = CTX_wm_region(C);
- if (region) {
- if (RGN_TYPE_IS_HEADER_ANY(region->regiontype)) {
- if (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_BOTTOM) {
- UI_block_direction_set(block, UI_DIR_UP);
- UI_block_order_flip(block);
- }
- }
- }
- }
-
- block->minbounds = minwidth;
- UI_block_bounds_set_text(block, 3.0f * UI_UNIT_X);
- }
-
- /* if menu slides out of other menu, override direction */
- if (pup->slideout) {
- UI_block_direction_set(block, UI_DIR_RIGHT);
- }
-
- return pup->block;
-}
-
-uiPopupBlockHandle *ui_popup_menu_create(
- bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
-{
- wmWindow *window = CTX_wm_window(C);
- const uiStyle *style = UI_style_get_dpi();
- uiPopupBlockHandle *handle;
- uiPopupMenu *pup;
-
- pup = MEM_callocN(sizeof(uiPopupMenu), __func__);
- pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS_PULLDOWN);
- pup->block->flag |= UI_BLOCK_NUMSELECT; /* default menus to numselect */
- pup->layout = UI_block_layout(
- pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
- pup->slideout = but ? ui_block_is_menu(but->block) : false;
- pup->but = but;
- uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN);
-
- if (!but) {
- /* no button to start from, means we are a popup */
- pup->mx = window->eventstate->xy[0];
- pup->my = window->eventstate->xy[1];
- pup->popup = true;
- pup->block->flag |= UI_BLOCK_NO_FLIP;
- }
- /* some enums reversing is strange, currently we have no good way to
- * reverse some enum's but not others, so reverse all so the first menu
- * items are always close to the mouse cursor */
- else {
-#if 0
- /* if this is an rna button then we can assume its an enum
- * flipping enums is generally not good since the order can be
- * important T28786. */
- if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
- pup->block->flag |= UI_BLOCK_NO_FLIP;
- }
-#endif
- if (but->context) {
- uiLayoutContextCopy(pup->layout, but->context);
- }
- }
-
- /* menu is created from a callback */
- pup->menu_func = menu_func;
- pup->menu_arg = arg;
-
- handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL);
-
- if (!but) {
- handle->popup = true;
-
- UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- WM_event_add_mousemove(window);
- }
-
- MEM_freeN(pup);
-
- return handle;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Popup Menu API with begin & end
- * \{ */
-
-uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
- const char *title,
- const char *block_name,
- int icon)
-{
- const uiStyle *style = UI_style_get_dpi();
- uiPopupMenu *pup = MEM_callocN(sizeof(uiPopupMenu), "popup menu");
- uiBut *but;
-
- pup->block = UI_block_begin(C, NULL, block_name, UI_EMBOSS_PULLDOWN);
- pup->block->flag |= UI_BLOCK_POPUP_MEMORY | UI_BLOCK_IS_FLIP;
- pup->block->puphash = ui_popup_menu_hash(title);
- pup->layout = UI_block_layout(
- pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
-
- /* NOTE: this intentionally differs from the menu & sub-menu default because many operators
- * use popups like this to select one of their options -
- * where having invoke doesn't make sense */
- uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
-
- /* create in advance so we can let buttons point to retval already */
- pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
-
- /* create title button */
- if (title[0]) {
- char titlestr[256];
-
- if (icon) {
- BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
- uiDefIconTextBut(pup->block,
- UI_BTYPE_LABEL,
- 0,
- icon,
- titlestr,
- 0,
- 0,
- 200,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- }
- else {
- but = uiDefBut(
- pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- but->drawflag = UI_BUT_TEXT_LEFT;
- }
-
- uiItemS(pup->layout);
- }
-
- return pup;
-}
-
-uiPopupMenu *UI_popup_menu_begin(bContext *C, const char *title, int icon)
-{
- return UI_popup_menu_begin_ex(C, title, __func__, icon);
-}
-
-void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *but)
-{
- pup->but = but;
- pup->butregion = butregion;
-}
-
-void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
-{
- wmWindow *window = CTX_wm_window(C);
- uiPopupBlockHandle *menu;
- uiBut *but = NULL;
- ARegion *butregion = NULL;
-
- pup->popup = true;
- pup->mx = window->eventstate->xy[0];
- pup->my = window->eventstate->xy[1];
-
- if (pup->but) {
- but = pup->but;
- butregion = pup->butregion;
- }
-
- menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL);
- menu->popup = true;
-
- UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
- WM_event_add_mousemove(window);
-
- MEM_freeN(pup);
-}
-
-bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup)
-{
- if (!UI_block_is_empty_ex(pup->block, true)) {
- UI_popup_menu_end(C, pup);
- return true;
- }
- UI_block_layout_resolve(pup->block, NULL, NULL);
- MEM_freeN(pup->block->handle);
- UI_block_free(C, pup->block);
- MEM_freeN(pup);
- return false;
-}
-
-uiLayout *UI_popup_menu_layout(uiPopupMenu *pup)
-{
- return pup->layout;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Standard Popup Menus
- * \{ */
-
-void UI_popup_menu_reports(bContext *C, ReportList *reports)
-{
- uiPopupMenu *pup = NULL;
- uiLayout *layout;
-
- if (!CTX_wm_window(C)) {
- return;
- }
-
- LISTBASE_FOREACH (Report *, report, &reports->list) {
- int icon;
- const char *msg, *msg_next;
-
- if (report->type < reports->printlevel) {
- continue;
- }
-
- if (pup == NULL) {
- char title[UI_MAX_DRAW_STR];
- BLI_snprintf(title, sizeof(title), "%s: %s", IFACE_("Report"), report->typestr);
- /* popup_menu stuff does just what we need (but pass meaningful block name) */
- pup = UI_popup_menu_begin_ex(C, title, __func__, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- }
- else {
- uiItemS(layout);
- }
-
- /* split each newline into a label */
- msg = report->message;
- icon = UI_icon_from_report_type(report->type);
- do {
- char buf[UI_MAX_DRAW_STR];
- msg_next = strchr(msg, '\n');
- if (msg_next) {
- msg_next++;
- BLI_strncpy(buf, msg, MIN2(sizeof(buf), msg_next - msg));
- msg = buf;
- }
- uiItemL(layout, msg, icon);
- icon = ICON_NONE;
- } while ((msg = msg_next) && *msg);
- }
-
- if (pup) {
- UI_popup_menu_end(C, pup);
- }
-}
-
-int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
-{
- uiPopupMenu *pup;
- uiLayout *layout;
- MenuType *mt = WM_menutype_find(idname, true);
-
- if (mt == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Menu \"%s\" not found", idname);
- return OPERATOR_CANCELLED;
- }
-
- if (WM_menutype_poll(C, mt) == false) {
- /* cancel but allow event to pass through, just like operators do */
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
-
- pup = UI_popup_menu_begin(C, IFACE_(mt->label), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- UI_menutype_draw(C, mt, layout);
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Popup Block API
- * \{ */
-
-void UI_popup_block_invoke_ex(
- bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free, bool can_refresh)
-{
- wmWindow *window = CTX_wm_window(C);
- uiPopupBlockHandle *handle;
-
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, arg_free);
- handle->popup = true;
-
- /* It can be useful to disable refresh (even though it will work)
- * as this exists text fields which can be disruptive if refresh isn't needed. */
- handle->can_refresh = can_refresh;
-
- UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first);
- WM_event_add_mousemove(window);
-}
-
-void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free)
-{
- UI_popup_block_invoke_ex(C, func, arg, arg_free, true);
-}
-
-void UI_popup_block_ex(bContext *C,
- uiBlockCreateFunc func,
- uiBlockHandleFunc popup_func,
- uiBlockCancelFunc cancel_func,
- void *arg,
- wmOperator *op)
-{
- wmWindow *window = CTX_wm_window(C);
- uiPopupBlockHandle *handle;
-
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, NULL);
- handle->popup = true;
- handle->retvalue = 1;
- handle->can_refresh = true;
-
- handle->popup_op = op;
- handle->popup_arg = arg;
- handle->popup_func = popup_func;
- handle->cancel_func = cancel_func;
- // handle->opcontext = opcontext;
-
- UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first);
- WM_event_add_mousemove(window);
-}
-
-#if 0 /* UNUSED */
-void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, wmOperatorCallContext opcontext)
-{
- wmWindow *window = CTX_wm_window(C);
- uiPopupBlockHandle *handle;
-
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op, NULL);
- handle->popup = 1;
- handle->retvalue = 1;
- handle->can_refresh = true;
-
- handle->popup_arg = op;
- handle->popup_func = operator_cb;
- handle->cancel_func = confirm_cancel_operator;
- handle->opcontext = opcontext;
-
- UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- WM_event_add_mousemove(C);
-}
-#endif
-
-void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
-{
- /* if loading new .blend while popup is open, window will be NULL */
- if (block->handle) {
- if (win) {
- const bScreen *screen = WM_window_get_active_screen(win);
-
- UI_popup_handlers_remove(&win->modalhandlers, block->handle);
- ui_popup_block_free(C, block->handle);
-
- /* In the case we have nested popups,
- * closing one may need to redraw another, see: T48874 */
- LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
- ED_region_tag_refresh_ui(region);
- }
- }
- }
-}
-
-bool UI_popup_block_name_exists(const bScreen *screen, const char *name)
-{
- LISTBASE_FOREACH (const ARegion *, region, &screen->regionbase) {
- LISTBASE_FOREACH (const uiBlock *, block, &region->uiblocks) {
- if (STREQ(block->name, name)) {
- return true;
- }
- }
- }
- return false;
-}
-
-/** \} */