UI: Initial popover support for panels

- UILayout.popover(.. panel_type ..)
  A single panel
- UILayout.popover_group(.. panel categories ..)
  Expands all panels matching args.

Currently used in the topbar for redo and paint options.
This commit is contained in:
2018-04-22 17:16:39 +02:00
parent b8e7991811
commit e6d1fb87c6
13 changed files with 581 additions and 1 deletions

View File

@@ -1824,6 +1824,35 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
static void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_mt)
{
PanelType *pt = (PanelType *)arg_mt;
/* TODO: move into UI_paneltype_draw */
Panel *panel = MEM_callocN(sizeof(Panel), "popover panel");
panel->type = pt;
if (layout->context) {
CTX_store_set(C, layout->context);
}
if (pt->draw_header) {
panel->layout = uiLayoutRow(layout, false);
pt->draw_header(C, panel);
panel->layout = NULL;
}
panel->layout = layout;
pt->draw(C, panel);
panel->layout = NULL;
if (layout->context) {
CTX_store_set(C, NULL);
}
MEM_freeN(panel);
}
static uiBut *ui_item_menu(
uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN,
const char *tip, bool force_menu)
@@ -1901,6 +1930,79 @@ void uiItemM(uiLayout *layout, bContext *UNUSED(C), const char *menuname, const
ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL, TIP_(mt->description), false);
}
/* popover */
void uiItemPopoverPanel_ptr(uiLayout *layout, bContext *UNUSED(C), PanelType *pt, const char *name, int icon)
{
if (!name) {
name = CTX_IFACE_(pt->translation_context, pt->label);
}
if (layout->root->type == UI_LAYOUT_MENU && !icon)
icon = ICON_BLANK1;
uiBut *but = ui_item_menu(layout, name, icon, ui_item_paneltype_func, pt, NULL, NULL, false);
but->type = UI_BTYPE_POPOVER;
}
void uiItemPopoverPanel(
uiLayout *layout, bContext *C,
int space_id, int region_id, const char *panel_type,
const char *name, int icon)
{
SpaceType *st = BKE_spacetype_from_id(space_id);
if (st == NULL) {
RNA_warning("space type not found %d", space_id);
return;
}
ARegionType *art = BKE_regiontype_from_id(st, region_id);
if (art == NULL) {
RNA_warning("region type not found %d", region_id);
return;
}
PanelType *pt;
for (pt = art->paneltypes.first; pt; pt = pt->next) {
if (STREQ(pt->idname, panel_type)) {
break;
}
}
if (pt == NULL) {
RNA_warning("area type not found %s", panel_type);
return;
}
uiItemPopoverPanel_ptr(layout, C, pt, name, icon);
}
void uiItemPopoverPanelFromGroup(
uiLayout *layout, bContext *C,
int space_id, int region_id, const char *context, const char *category)
{
SpaceType *st = BKE_spacetype_from_id(space_id);
if (st == NULL) {
RNA_warning("space type not found %d", space_id);
return;
}
ARegionType *art = BKE_regiontype_from_id(st, region_id);
if (art == NULL) {
RNA_warning("region type not found %d", region_id);
return;
}
for (PanelType *pt = art->paneltypes.first; pt; pt = pt->next) {
/* Causes too many panels, check context. */
if (/* (*context == '\0') || */ STREQ(pt->context, context)) {
if ((*category == '\0') || STREQ(pt->category, category)) {
if (pt->poll == NULL || pt->poll(C, pt)) {
uiItemPopoverPanel_ptr(layout, C, pt, NULL, ICON_NONE);
}
}
}
}
}
/* label item */
static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
{
@@ -3604,6 +3706,18 @@ MenuType *UI_but_menutype_get(uiBut *but)
}
}
/* this is a bit of a hack but best keep it in one place at least */
PanelType *UI_but_paneltype_get(uiBut *but)
{
if (but->menu_create_func == ui_item_paneltype_func) {
return (PanelType *)but->poin;
}
else {
return NULL;
}
}
void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout)
{
Menu menu = {