Files
test2/source/blender/editors/interface/templates/interface_template_event.cc
Guillermo Venegas 3b1e123361 Refactor: UI: Replace uiItemS and uiItemS_ex with uiLayout::separator
This merges the public `uiItemS` and `uiItemS_ex` functions into an
object oriented API (`uiLayout::separator`), matching the python API.
This reduces the difference between the C++ API with the python version,
its also helps while converting code from python to C++ code
(or vice-versa), making it almost seamless.

Part of: #117604

Pull Request: https://projects.blender.org/blender/blender/pulls/138826
2025-05-13 17:54:26 +02:00

213 lines
6.2 KiB
C++

/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edinterface
*/
#include "BLI_string_ref.hh"
#include "BLT_translation.hh"
#include "WM_keymap.hh"
#include "UI_interface.hh"
#include "interface_intern.hh"
using blender::StringRefNull;
static const wmKeyMapItem *keymap_item_from_enum_item(const wmKeyMap *keymap,
const EnumPropertyItem *item)
{
if (item == nullptr) {
return nullptr;
}
for (wmKeyMapItem *kmi = static_cast<wmKeyMapItem *>(keymap->items.first); kmi; kmi = kmi->next)
{
if (kmi->propvalue == item->value) {
return kmi;
}
}
return nullptr;
}
static bool keymap_item_can_collapse(const wmKeyMapItem *kmi_a, const wmKeyMapItem *kmi_b)
{
return (kmi_a->shift == kmi_b->shift && kmi_a->ctrl == kmi_b->ctrl && kmi_a->alt == kmi_b->alt &&
kmi_a->oskey == kmi_b->oskey && kmi_a->hyper == kmi_b->hyper);
}
int uiTemplateStatusBarModalItem(uiLayout *layout,
const wmKeyMap *keymap,
const EnumPropertyItem *item)
{
const wmKeyMapItem *kmi = keymap_item_from_enum_item(keymap, item);
if (kmi == nullptr) {
return 0;
}
if ((kmi->val == KM_RELEASE) && ISKEYBOARD(kmi->type)) {
/* Assume release events just disable something which was toggled on. */
return 1;
}
/* Try to merge some known triplet items to save horizontal space. */
const EnumPropertyItem *item_y = (item[1].identifier) ? item + 1 : nullptr;
const EnumPropertyItem *item_z = (item_y && item[2].identifier) ? item + 2 : nullptr;
const wmKeyMapItem *kmi_y = keymap_item_from_enum_item(keymap, item_y);
const wmKeyMapItem *kmi_z = keymap_item_from_enum_item(keymap, item_z);
if (kmi_y && kmi_z && keymap_item_can_collapse(kmi, kmi_y) &&
keymap_item_can_collapse(kmi_y, kmi_z))
{
const char *xyz_label = nullptr;
if (STREQ(item->identifier, "AXIS_X") && STREQ(item_y->identifier, "AXIS_Y") &&
STREQ(item_z->identifier, "AXIS_Z"))
{
xyz_label = IFACE_("Axis");
}
else if (STREQ(item->identifier, "PLANE_X") && STREQ(item_y->identifier, "PLANE_Y") &&
STREQ(item_z->identifier, "PLANE_Z"))
{
xyz_label = IFACE_("Plane");
}
if (STREQ(item->identifier, "PROPORTIONAL_SIZE_UP") &&
STREQ(item_y->identifier, "PROPORTIONAL_SIZE_DOWN") &&
STREQ(item_z->identifier, "PROPORTIONAL_SIZE"))
{
xyz_label = IFACE_("Proportional Size");
}
if (xyz_label) {
int icon_mod[KM_MOD_NUM] = {0};
#ifdef WITH_HEADLESS
int icon = 0;
#else
int icon = UI_icon_from_keymap_item(kmi, icon_mod);
#endif
for (int j = 0; j < ARRAY_SIZE(icon_mod) && icon_mod[j]; j++) {
layout->label("", icon_mod[j]);
const float offset = ui_event_icon_offset(icon_mod[j]);
if (offset != 0.0f) {
layout->separator(offset);
}
}
layout->label("", icon);
layout->separator(ui_event_icon_offset(icon));
#ifndef WITH_HEADLESS
icon = UI_icon_from_keymap_item(kmi_y, icon_mod);
#endif
layout->label("", icon);
layout->separator(ui_event_icon_offset(icon));
#ifndef WITH_HEADLESS
icon = UI_icon_from_keymap_item(kmi_z, icon_mod);
#endif
layout->label("", icon);
layout->separator(ui_event_icon_offset(icon));
layout->separator(0.2f);
layout->label(xyz_label, ICON_NONE);
layout->separator(0.6f);
return 3;
}
}
/* Try to merge some known paired items to save horizontal space. */
if (kmi_y && keymap_item_can_collapse(kmi, kmi_y)) {
const char *ab_label = nullptr;
if (STREQ(item->identifier, "PROPORTIONAL_SIZE_UP") &&
STREQ(item_y->identifier, "PROPORTIONAL_SIZE_DOWN"))
{
ab_label = IFACE_("Proportional Size");
}
if (ab_label) {
int icon_mod[KM_MOD_NUM] = {0};
#ifdef WITH_HEADLESS
int icon = 0;
#else
int icon = UI_icon_from_keymap_item(kmi, icon_mod);
#endif
for (int j = 0; j < ARRAY_SIZE(icon_mod) && icon_mod[j]; j++) {
layout->label("", icon_mod[j]);
const float offset = ui_event_icon_offset(icon_mod[j]);
if (offset != 0.0f) {
layout->separator(offset);
}
}
layout->label("", icon);
layout->separator(ui_event_icon_offset(icon));
#ifndef WITH_HEADLESS
icon = UI_icon_from_keymap_item(kmi_y, icon_mod);
#endif
layout->label("", icon);
layout->separator(ui_event_icon_offset(icon));
layout->separator(0.2f);
layout->label(ab_label, ICON_NONE);
layout->separator(0.6f);
return 2;
}
}
/* Single item without merging. */
return uiTemplateEventFromKeymapItem(layout, item->name, kmi, false) ? 1 : 0;
}
bool uiTemplateEventFromKeymapItem(uiLayout *layout,
const StringRefNull text,
const wmKeyMapItem *kmi,
bool text_fallback)
{
bool ok = false;
int icon_mod[KM_MOD_NUM];
#ifdef WITH_HEADLESS
int icon = 0;
#else
const int icon = UI_icon_from_keymap_item(kmi, icon_mod);
#endif
if (icon != 0) {
for (int j = 0; j < ARRAY_SIZE(icon_mod) && icon_mod[j]; j++) {
layout->label("", icon_mod[j]);
const float offset = ui_event_icon_offset(icon_mod[j]);
if (offset != 0.0f) {
layout->separator(offset);
}
}
/* Icon and text separately is closer together with aligned layout. */
layout->label("", icon);
if (icon >= ICON_MOUSE_LMB && icon <= ICON_MOUSE_MMB_SCROLL) {
/* Negative space after narrow mice icons. */
layout->separator(-0.68f);
}
const float offset = ui_event_icon_offset(icon);
if (offset != 0.0f) {
layout->separator(offset);
}
layout->separator(0.2f);
layout->label(CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, text.c_str()), ICON_NONE);
layout->separator(0.6f);
ok = true;
}
else if (text_fallback) {
const char *event_text = WM_key_event_string(kmi->type, true);
layout->label(event_text, ICON_NONE);
layout->label(CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, text.c_str()), ICON_NONE);
layout->separator(0.6f);
ok = true;
}
return ok;
}