Manipulator: tooltip support

Currently operators and properties are used.
This commit is contained in:
Campbell Barton
2017-12-20 16:40:53 +11:00
parent 3143b2f942
commit 5b364dd780
6 changed files with 209 additions and 0 deletions

View File

@@ -73,6 +73,7 @@ struct bNodeSocket;
struct wmDropBox;
struct wmDrag;
struct wmEvent;
struct wmManipulator;
struct wmMsgBus;
typedef struct uiBut uiBut;
@@ -1137,6 +1138,7 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
/* ui_interface_region_tooltip.c */
struct ARegion *UI_tooltip_create_from_button(struct bContext *C, struct ARegion *butregion, uiBut *but);
struct ARegion *UI_tooltip_create_from_manipulator(struct bContext *C, struct wmManipulator *mpr);
void UI_tooltip_free(struct bContext *C, struct ARegion *ar);
/* How long before a tool-tip shows. */

View File

@@ -620,6 +620,112 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
static uiTooltipData *ui_tooltip_data_from_manipulator(bContext *C, wmManipulator *mpr)
{
uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
/* TODO(campbell): a way for manipulators to have their own descriptions (low priority). */
/* Operator Actions */
{
bool use_drag = mpr->drag_part != -1 && mpr->highlight_part != mpr->drag_part;
const struct {
int part;
const char *prefix;
} mpop_actions[] = {
{
.part = mpr->highlight_part,
.prefix = use_drag ? TIP_("Click") : NULL,
}, {
.part = use_drag ? mpr->drag_part : -1,
.prefix = use_drag ? TIP_("Drag") : NULL,
},
};
for (int i = 0; i < ARRAY_SIZE(mpop_actions); i++) {
wmManipulatorOpElem *mpop = (mpop_actions[i].part != -1) ? WM_manipulator_operator_get(mpr, mpop_actions[i].part) : NULL;
if (mpop != NULL) {
/* Description */
const char *info = RNA_struct_ui_description(mpop->type->srna);
if (!(info && info[0])) {
info = RNA_struct_ui_name(mpop->type->srna);
}
if (info && info[0]) {
char *text = NULL;
if (mpop_actions[i].prefix != NULL) {
text = BLI_sprintfN("%s: %s", mpop_actions[i].prefix, info);
}
else {
text = BLI_strdup(info);
}
if (text != NULL) {
uiTooltipField *field = text_field_add(
data, &(uiTooltipFormat){
.style = UI_TIP_STYLE_HEADER,
.color_id = UI_TIP_LC_VALUE,
.is_pad = true,
});
field->text = text;
}
}
/* Shortcut */
{
bool found = false;
IDProperty *prop = mpop->ptr.data;
char buf[128];
if (WM_key_event_operator_string(
C, mpop->type->idname, WM_OP_INVOKE_DEFAULT, prop, true,
buf, ARRAY_SIZE(buf)))
{
found = true;
}
uiTooltipField *field = text_field_add(
data, &(uiTooltipFormat){
.style = UI_TIP_STYLE_NORMAL,
.color_id = UI_TIP_LC_VALUE,
.is_pad = true,
});
field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None");
}
}
}
}
/* Property Actions */
if (mpr->type->target_property_defs_len) {
wmManipulatorProperty *mpr_prop_array = WM_manipulator_target_property_array(mpr);
for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
/* TODO(campbell): function callback descriptions. */
wmManipulatorProperty *mpr_prop = &mpr_prop_array[i];
if (mpr_prop->prop != NULL) {
const char *info = RNA_property_ui_description(mpr_prop->prop);
if (info && info[0]) {
uiTooltipField *field = text_field_add(
data, &(uiTooltipFormat){
.style = UI_TIP_STYLE_NORMAL,
.color_id = UI_TIP_LC_VALUE,
.is_pad = true,
});
field->text = BLI_strdup(info);
}
}
}
}
if (data->fields_len == 0) {
MEM_freeN(data);
return NULL;
}
else {
return data;
}
}
static ARegion *ui_tooltip_create_with_data(
bContext *C, uiTooltipData *data,
const float init_position[2],
@@ -827,6 +933,23 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
return ui_tooltip_create_with_data(C, data, init_position, aspect);
}
ARegion *UI_tooltip_create_from_manipulator(bContext *C, wmManipulator *mpr)
{
wmWindow *win = CTX_wm_window(C);
const float aspect = 1.0f;
float init_position[2];
uiTooltipData *data = ui_tooltip_data_from_manipulator(C, mpr);
if (data == NULL) {
return NULL;
}
init_position[0] = win->eventstate->x;
init_position[1] = win->eventstate->y;
return ui_tooltip_create_with_data(C, data, init_position, aspect);
}
void UI_tooltip_free(bContext *C, ARegion *ar)
{
ui_region_temp_remove(C, CTX_wm_screen(C), ar);

View File

@@ -2251,13 +2251,32 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wm_manipulatormap_handler_context(C, handler);
wm_region_mouse_co(C, event);
if (event->type == MOUSEMOVE) {
WM_manipulatormap_tooltip_clear(C, mmap);
}
/* handle manipulator highlighting */
if (event->type == MOUSEMOVE && !wm_manipulatormap_modal_get(mmap)) {
int part;
mpr = wm_manipulatormap_highlight_find(mmap, C, event, &part);
wm_manipulatormap_highlight_set(mmap, C, mpr, part);
if (mpr != NULL) {
WM_manipulatormap_tooltip_timer_init(C, mmap);
}
}
/* handle user configurable manipulator-map keymap */
else if ((event->type == TIMER) &&
(event->customdata == WM_manipulatormap_tooltip_timer_get(mmap)))
{
if (mpr) {
if (mpr->state & WM_MANIPULATOR_STATE_MODAL) {
WM_manipulatormap_tooltip_clear(C, mmap);
}
else {
WM_manipulatormap_tooltip_create(C, mmap);
}
}
}
else {
/* Either we operate on a single highlighted item
* or groups attached to the selected manipulators.

View File

@@ -259,6 +259,15 @@ bool WM_manipulatormap_minmax(
const struct wmManipulatorMap *mmap, bool use_hidden, bool use_select,
float r_min[3], float r_max[3]);
void WM_manipulatormap_tooltip_create(
struct bContext *C, struct wmManipulatorMap *mmap);
void WM_manipulatormap_tooltip_clear(
struct bContext *C, struct wmManipulatorMap *mmap);
void WM_manipulatormap_tooltip_timer_init(
struct bContext *C, struct wmManipulatorMap *mmap);
const void *WM_manipulatormap_tooltip_timer_get(
struct wmManipulatorMap *mmap);
/* -------------------------------------------------------------------- */
/* wmManipulatorMapType */

View File

@@ -115,6 +115,9 @@ struct wmManipulatorMap {
/* cursor location at point of entering modal (see: WM_MANIPULATOR_GRAB_CURSOR) */
int event_xy[2];
short event_grabcursor;
struct ARegion *tooltip;
struct wmTimer *tooltip_timer;
} mmap_context;
};

View File

@@ -51,6 +51,9 @@
#include "WM_types.h"
#include "wm_event_system.h"
/* for tool-tips */
#include "UI_interface.h"
#include "DEG_depsgraph.h"
/* own includes */
@@ -888,6 +891,8 @@ void wm_manipulatormap_modal_set(
BLI_assert(mmap->mmap_context.modal == NULL);
wmWindow *win = CTX_wm_window(C);
WM_manipulatormap_tooltip_clear(C, mmap);
/* For now only grab cursor for 3D manipulators. */
int retval = OPERATOR_RUNNING_MODAL;
@@ -996,6 +1001,54 @@ void WM_manipulatormap_message_subscribe(
/** \} */ /* wmManipulatorMap */
/* -------------------------------------------------------------------- */
/** \name Tooltip Handling
*
* \{ */
void WM_manipulatormap_tooltip_create(
bContext *C, wmManipulatorMap *mmap)
{
WM_manipulatormap_tooltip_clear(C, mmap);
if (mmap->mmap_context.highlight) {
mmap->mmap_context.tooltip = UI_tooltip_create_from_manipulator(C, mmap->mmap_context.highlight);
}
}
void WM_manipulatormap_tooltip_clear(
bContext *C, wmManipulatorMap *mmap)
{
if (mmap->mmap_context.tooltip_timer != NULL) {
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
WM_event_remove_timer(wm, win, mmap->mmap_context.tooltip_timer);
mmap->mmap_context.tooltip_timer = NULL;
}
if (mmap->mmap_context.tooltip != NULL) {
UI_tooltip_free(C, mmap->mmap_context.tooltip);
mmap->mmap_context.tooltip = NULL;
}
}
void WM_manipulatormap_tooltip_timer_init(
bContext *C, wmManipulatorMap *mmap)
{
if (mmap->mmap_context.tooltip_timer == NULL) {
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
/* TODO: BUTTON_TOOLTIP_DELAY */
mmap->mmap_context.tooltip_timer = WM_event_add_timer(wm, win, TIMER, UI_TOOLTIP_DELAY);
}
}
const void *WM_manipulatormap_tooltip_timer_get(wmManipulatorMap *mmap)
{
return mmap->mmap_context.tooltip_timer;
}
/** \} */ /* wmManipulatorMapType */
/* -------------------------------------------------------------------- */
/** \name wmManipulatorMapType
*