diff options
Diffstat (limited to 'source/blender/editors/interface/interface_panel.c')
-rw-r--r-- | source/blender/editors/interface/interface_panel.c | 523 |
1 files changed, 194 insertions, 329 deletions
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 5f56a93c5eb..dd3074d6258 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -147,22 +147,22 @@ static int panel_aligned(const ScrArea *area, const ARegion *region) if (area->spacetype == SPACE_PROPERTIES && region->regiontype == RGN_TYPE_WINDOW) { return BUT_VERTICAL; } - else if (area->spacetype == SPACE_USERPREF && region->regiontype == RGN_TYPE_WINDOW) { + if (area->spacetype == SPACE_USERPREF && region->regiontype == RGN_TYPE_WINDOW) { return BUT_VERTICAL; } - else if (area->spacetype == SPACE_FILE && region->regiontype == RGN_TYPE_CHANNELS) { + if (area->spacetype == SPACE_FILE && region->regiontype == RGN_TYPE_CHANNELS) { return BUT_VERTICAL; } - else if (area->spacetype == SPACE_IMAGE && region->regiontype == RGN_TYPE_PREVIEW) { + if (area->spacetype == SPACE_IMAGE && region->regiontype == RGN_TYPE_PREVIEW) { return BUT_VERTICAL; } - else if (ELEM(region->regiontype, - RGN_TYPE_UI, - RGN_TYPE_TOOLS, - RGN_TYPE_TOOL_PROPS, - RGN_TYPE_HUD, - RGN_TYPE_NAV_BAR, - RGN_TYPE_EXECUTE)) { + if (ELEM(region->regiontype, + RGN_TYPE_UI, + RGN_TYPE_TOOLS, + RGN_TYPE_TOOL_PROPS, + RGN_TYPE_HUD, + RGN_TYPE_NAV_BAR, + RGN_TYPE_EXECUTE)) { return BUT_VERTICAL; } @@ -245,20 +245,25 @@ static bool panels_need_realign(ScrArea *area, ARegion *region, Panel **r_panel_ /********* Functions for instanced panels. ***********/ -static Panel *UI_panel_add_instanced_ex( - ScrArea *area, ARegion *region, ListBase *panels, PanelType *panel_type, int list_index) +static Panel *UI_panel_add_instanced_ex(ScrArea *area, + ARegion *region, + ListBase *panels, + PanelType *panel_type, + int list_index, + PointerRNA *custom_data) { Panel *panel = MEM_callocN(sizeof(Panel), "instanced panel"); panel->type = panel_type; BLI_strncpy(panel->panelname, panel_type->idname, sizeof(panel->panelname)); panel->runtime.list_index = list_index; + panel->runtime.custom_data_ptr = custom_data; /* Add the panel's children too. Although they aren't instanced panels, we can still use this * function to create them, as UI_panel_begin does other things we don't need to do. */ LISTBASE_FOREACH (LinkData *, child, &panel_type->children) { PanelType *child_type = child->data; - UI_panel_add_instanced_ex(area, region, &panel->children, child_type, list_index); + UI_panel_add_instanced_ex(area, region, &panel->children, child_type, list_index, custom_data); } /* Make sure the panel is added to the end of the display-order as well. This is needed for @@ -283,8 +288,12 @@ static Panel *UI_panel_add_instanced_ex( * Called in situations where panels need to be added dynamically rather than having only one panel * corresponding to each PanelType. */ -Panel *UI_panel_add_instanced( - ScrArea *area, ARegion *region, ListBase *panels, char *panel_idname, int list_index) +Panel *UI_panel_add_instanced(ScrArea *area, + ARegion *region, + ListBase *panels, + char *panel_idname, + int list_index, + PointerRNA *custom_data) { ARegionType *region_type = region->type; @@ -296,7 +305,7 @@ Panel *UI_panel_add_instanced( return NULL; } - return UI_panel_add_instanced_ex(area, region, panels, panel_type, list_index); + return UI_panel_add_instanced_ex(area, region, panels, panel_type, list_index, custom_data); } /** @@ -332,7 +341,8 @@ static void panel_free_block(ARegion *region, Panel *panel) } /** - * Free a panel and it's children. + * Free a panel and it's children. Custom data is shared by the panel and its children + * and is freed by #UI_panels_free_instanced. * * \note The only panels that should need to be deleted at runtime are panels with the * #PNL_INSTANCED flag set. @@ -354,15 +364,28 @@ static void panel_delete(ARegion *region, ListBase *panels, Panel *panel) MEM_freeN(panel); } +/** + * Remove instanced panels from the region's panel list. + * + * \note Can be called with NULL \a C, but it should be avoided because + * handlers might not be removed. + */ void UI_panels_free_instanced(bContext *C, ARegion *region) { /* Delete panels with the instanced flag. */ LISTBASE_FOREACH_MUTABLE (Panel *, panel, ®ion->panels) { if ((panel->type != NULL) && (panel->type->flag & PNL_INSTANCED)) { /* Make sure the panel's handler is removed before deleting it. */ - if (panel->activedata != NULL) { + if (C != NULL && panel->activedata != NULL) { panel_activate_state(C, panel, PANEL_STATE_EXIT); } + + /* Free panel's custom data. */ + if (panel->runtime.custom_data_ptr != NULL) { + MEM_freeN(panel->runtime.custom_data_ptr); + } + + /* Free the panel and its sub-panels. */ panel_delete(region, ®ion->panels, panel); } } @@ -381,9 +404,19 @@ bool UI_panel_list_matches_data(ARegion *region, ListBase *data, uiListPanelIDFromDataFunc panel_idname_func) { - int data_len = BLI_listbase_count(data); + /* Check for NULL data. */ + int data_len = 0; + Link *data_link = NULL; + if (data == NULL) { + data_len = 0; + data_link = NULL; + } + else { + data_len = BLI_listbase_count(data); + data_link = data->first; + } + int i = 0; - Link *data_link = data->first; LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->type != NULL && panel->type->flag & PNL_INSTANCED) { /* The panels were reordered by drag and drop. */ @@ -487,7 +520,7 @@ static void reorder_instanced_panel_list(bContext *C, ARegion *region, Panel *dr /** * Recursive implementation for #UI_panel_set_expand_from_list_data. * - * \return Whether the closed flag for the panel or any subpanels changed. + * \return Whether the closed flag for the panel or any sub-panels changed. */ static bool panel_set_expand_from_list_data_recursive(Panel *panel, short flag, short *flag_index) { @@ -507,7 +540,7 @@ static bool panel_set_expand_from_list_data_recursive(Panel *panel, short flag, } /** - * Set the expansion of the panel and its subpanels from the flag stored by the list data + * Set the expansion of the panel and its sub-panels from the flag stored by the list data * corresponding to this panel. The flag has expansion stored in each bit in depth first * order. */ @@ -577,6 +610,26 @@ static void set_panels_list_data_expand_flag(const bContext *C, ARegion *region) /****************************** panels ******************************/ +/** + * Set flag state for a panel and its sub-panels. + * + * \return True if this function changed any of the flags, false if it didn't. + */ +static bool panel_set_flag_recursive(Panel *panel, int flag, bool value) +{ + short flag_original = panel->flag; + + SET_FLAG_FROM_TEST(panel->flag, value, flag); + + bool changed = (flag_original != panel->flag); + + LISTBASE_FOREACH (Panel *, child, &panel->children) { + changed |= panel_set_flag_recursive(child, flag, value); + } + + return changed; +} + static void panels_collapse_all(const bContext *C, ScrArea *area, ARegion *region, @@ -586,9 +639,8 @@ static void panels_collapse_all(const bContext *C, const char *category = has_category_tabs ? UI_panel_category_active_get(region, false) : NULL; const int flag = ((panel_aligned(area, region) == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY); const PanelType *from_pt = from_panel->type; - Panel *panel; - for (panel = region->panels.first; panel; panel = panel->next) { + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { PanelType *pt = panel->type; /* close panels with headers in the same context */ @@ -615,10 +667,9 @@ static bool panel_type_context_poll(PanelType *panel_type, const char *context) Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt) { - Panel *panel; const char *idname = pt->idname; - for (panel = lb->first; panel; panel = panel->next) { + LISTBASE_FOREACH (Panel *, panel, lb) { if (STREQLEN(panel->panelname, idname, sizeof(panel->panelname))) { return panel; } @@ -637,7 +688,7 @@ Panel *UI_panel_begin(ScrArea *area, Panel *panel, bool *r_open) { - Panel *panel_last, *panel_next; + Panel *panel_last; const char *drawname = CTX_IFACE_(pt->translation_context, pt->label); const char *idname = pt->idname; const bool newpanel = (panel == NULL); @@ -698,7 +749,7 @@ Panel *UI_panel_begin(ScrArea *area, if (newpanel) { panel->sortorder = (panel_last) ? panel_last->sortorder + 1 : 0; - for (panel_next = lb->first; panel_next; panel_next = panel_next->next) { + LISTBASE_FOREACH (Panel *, panel_next, lb) { if (panel_next != panel && panel_next->sortorder >= panel->sortorder) { panel_next->sortorder++; } @@ -827,79 +878,8 @@ void UI_draw_icon_tri(float x, float y, char dir, const float color[4]) } } -static void ui_draw_anti_x(uint pos, float x1, float y1, float x2, float y2) -{ - - /* set antialias line */ - GPU_line_smooth(true); - GPU_blend(true); - - GPU_line_width(2.0); - - immBegin(GPU_PRIM_LINES, 4); - - immVertex2f(pos, x1, y1); - immVertex2f(pos, x2, y2); - - immVertex2f(pos, x1, y2); - immVertex2f(pos, x2, y1); - - immEnd(); - - GPU_line_smooth(false); - GPU_blend(false); -} - -/* x 'icon' for panel header */ -static void ui_draw_x_icon(uint pos, float x, float y) -{ - - ui_draw_anti_x(pos, x, y, x + 9.375f, y + 9.375f); -} - #define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */ -static void ui_draw_panel_scalewidget(uint pos, const rcti *rect) -{ - float xmin, xmax, dx; - float ymin, ymax, dy; - - xmin = rect->xmax - PNL_HEADER + 2; - xmax = rect->xmax - 3; - ymin = rect->ymin + 3; - ymax = rect->ymin + PNL_HEADER - 2; - - dx = 0.5f * (xmax - xmin); - dy = 0.5f * (ymax - ymin); - - GPU_blend(true); - immUniformColor4ub(255, 255, 255, 50); - - immBegin(GPU_PRIM_LINES, 4); - - immVertex2f(pos, xmin, ymin); - immVertex2f(pos, xmax, ymax); - - immVertex2f(pos, xmin + dx, ymin); - immVertex2f(pos, xmax, ymax - dy); - - immEnd(); - - immUniformColor4ub(0, 0, 0, 50); - - immBegin(GPU_PRIM_LINES, 4); - - immVertex2f(pos, xmin, ymin + 1); - immVertex2f(pos, xmax, ymax + 1); - - immVertex2f(pos, xmin + dx, ymin + 1); - immVertex2f(pos, xmax, ymax - dy + 1); - - immEnd(); - - GPU_blend(false); -} - /* For button layout next to label. */ void UI_panel_label_offset(uiBlock *block, int *r_x, int *r_y) { @@ -926,12 +906,7 @@ static void ui_draw_aligned_panel_header( uchar col_title[4]; /* + 0.001f to avoid flirting with float inaccuracy */ - if (panel->control & UI_PNL_CLOSE) { - pnl_icons = (panel->labelofs + (2.0f * PNL_ICON)) / block->aspect + 0.001f; - } - else { - pnl_icons = (panel->labelofs + (1.1f * PNL_ICON)) / block->aspect + 0.001f; - } + pnl_icons = (panel->labelofs + (1.1f * PNL_ICON)) / block->aspect + 0.001f; /* draw text label */ panel_title_color_get(show_background, col_title); @@ -976,7 +951,7 @@ void ui_draw_aligned_panel(uiStyle *style, * can't be dragged. This may be changed in future. */ show_background); const int panel_col = is_subpanel ? TH_PANEL_SUB_BACK : TH_PANEL_BACK; - const bool draw_box_style = (panel->type && panel->type->flag & (PNL_DRAW_BOX)); + const bool draw_box_style = (panel->type && panel->type->flag & PNL_DRAW_BOX); /* Use the theme for box widgets for box-style panels. */ uiWidgetColors *box_wcol = NULL; @@ -1127,11 +1102,7 @@ void ui_draw_aligned_panel(uiStyle *style, /* in some occasions, draw a border */ if (panel->flag & PNL_SELECT && !is_subpanel) { float radius; - if (panel->control & UI_PNL_SOLID) { - UI_draw_roundbox_corner_set(UI_CNR_ALL); - radius = 8.0f; - } - else if (draw_box_style) { + if (draw_box_style) { UI_draw_roundbox_corner_set(UI_CNR_ALL); radius = box_wcol->roundness * U.widget_unit; } @@ -1156,7 +1127,7 @@ void ui_draw_aligned_panel(uiStyle *style, /* Draw panel backdrop if it wasn't already been drawn by the single opaque round box earlier. * Note: Sub-panels blend with panels, so they can't be opaque. */ if (show_background && !(draw_box_style && !is_subpanel)) { - /* Draw the bottom subpanels . */ + /* Draw the bottom sub-panels. */ if (draw_box_style) { if (panel->next) { immUniformThemeColor(panel_col); @@ -1182,26 +1153,12 @@ void ui_draw_aligned_panel(uiStyle *style, } } - if (panel->control & UI_PNL_SCALE) { - ui_draw_panel_scalewidget(pos, rect); - } - immUnbindProgram(); } uchar col_title[4]; panel_title_color_get(show_background, col_title); - /* draw optional close icon */ - - if (panel->control & UI_PNL_CLOSE) { - const int ofsx = 6; - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor3ubv(col_title); - ui_draw_x_icon(pos, rect->xmin + 2 + ofsx, rect->ymax + 2); - immUnbindProgram(); - } - /* draw collapse icon */ /* itemrect smaller */ @@ -1272,9 +1229,7 @@ static int get_panel_real_ofsy(Panel *panel) if (panel->flag & PNL_CLOSEDY) { return panel->ofsy + panel->sizey; } - else { - return panel->ofsy; - } + return panel->ofsy; } static int get_panel_real_ofsx(Panel *panel) @@ -1282,9 +1237,7 @@ static int get_panel_real_ofsx(Panel *panel) if (panel->flag & PNL_CLOSEDX) { return panel->ofsx + get_panel_header(panel); } - else { - return panel->ofsx + panel->sizex; - } + return panel->ofsx + panel->sizex; } bool UI_panel_is_dragging(const struct Panel *panel) @@ -1312,13 +1265,13 @@ static int find_leftmost_panel(const void *a1, const void *a2) if (ps1->panel->ofsx > ps2->panel->ofsx) { return 1; } - else if (ps1->panel->ofsx < ps2->panel->ofsx) { + if (ps1->panel->ofsx < ps2->panel->ofsx) { return -1; } - else if (ps1->panel->sortorder > ps2->panel->sortorder) { + if (ps1->panel->sortorder > ps2->panel->sortorder) { return 1; } - else if (ps1->panel->sortorder < ps2->panel->sortorder) { + if (ps1->panel->sortorder < ps2->panel->sortorder) { return -1; } @@ -1334,23 +1287,23 @@ static int find_highest_panel(const void *a1, const void *a2) if (ps1->panel->type->flag & PNL_NO_HEADER && ps2->panel->type->flag & PNL_NO_HEADER) { /* skip and check for ofs and sortorder below */ } - else if (ps1->panel->type->flag & PNL_NO_HEADER) { + if (ps1->panel->type->flag & PNL_NO_HEADER) { return -1; } - else if (ps2->panel->type->flag & PNL_NO_HEADER) { + if (ps2->panel->type->flag & PNL_NO_HEADER) { return 1; } if (ps1->panel->ofsy + ps1->panel->sizey < ps2->panel->ofsy + ps2->panel->sizey) { return 1; } - else if (ps1->panel->ofsy + ps1->panel->sizey > ps2->panel->ofsy + ps2->panel->sizey) { + if (ps1->panel->ofsy + ps1->panel->sizey > ps2->panel->ofsy + ps2->panel->sizey) { return -1; } - else if (ps1->panel->sortorder > ps2->panel->sortorder) { + if (ps1->panel->sortorder > ps2->panel->sortorder) { return 1; } - else if (ps1->panel->sortorder < ps2->panel->sortorder) { + if (ps1->panel->sortorder < ps2->panel->sortorder) { return -1; } @@ -1364,7 +1317,7 @@ static int compare_panel(const void *a1, const void *a2) if (ps1->panel->sortorder > ps2->panel->sortorder) { return 1; } - else if (ps1->panel->sortorder < ps2->panel->sortorder) { + if (ps1->panel->sortorder < ps2->panel->sortorder) { return -1; } @@ -1393,14 +1346,13 @@ static void align_sub_panels(Panel *panel) /* returns 1 when it did something */ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, const bool drag) { - Panel *panel; PanelSort *ps, *panelsort, *psnext; int a, tot = 0; bool done; int align = panel_aligned(area, region); /* count active, not tabbed panels */ - for (panel = region->panels.first; panel; panel = panel->next) { + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->runtime_flag & PNL_ACTIVE) { tot++; } @@ -1411,7 +1363,7 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co } /* extra; change close direction? */ - for (panel = region->panels.first; panel; panel = panel->next) { + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->runtime_flag & PNL_ACTIVE) { if ((panel->flag & PNL_CLOSEDX) && (align == BUT_VERTICAL)) { panel->flag ^= PNL_CLOSED; @@ -1426,7 +1378,7 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co panelsort = MEM_callocN(tot * sizeof(PanelSort), "panelsort"); ps = panelsort; - for (panel = region->panels.first; panel; panel = panel->next) { + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->runtime_flag & PNL_ACTIVE) { ps->panel = MEM_dupallocN(panel); ps->orig = panel; @@ -1458,11 +1410,6 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co ps->panel->ofsx = 0; ps->panel->ofsy = -get_panel_size_y(ps->panel); ps->panel->ofsx += ps->panel->runtime.region_ofsx; - /* Extra margin if the panel is a box style panel. */ - if (ps->panel->type && ps->panel->type->flag & PNL_DRAW_BOX) { - ps->panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN; - ps->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN; - } for (a = 0; a < tot - 1; a++, ps++) { psnext = ps + 1; @@ -1472,16 +1419,12 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co bool use_box_next = psnext->panel->type && psnext->panel->type->flag & PNL_DRAW_BOX; psnext->panel->ofsx = ps->panel->ofsx; psnext->panel->ofsy = get_panel_real_ofsy(ps->panel) - get_panel_size_y(psnext->panel); + /* Extra margin for box style panels. */ + ps->panel->ofsx += (use_box) ? UI_PANEL_BOX_STYLE_MARGIN : 0.0f; if (use_box || use_box_next) { psnext->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN; } - if (use_box && !use_box_next) { - psnext->panel->ofsx -= UI_PANEL_BOX_STYLE_MARGIN; - } - else if (!use_box && use_box_next) { - psnext->panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN; - } } else { psnext->panel->ofsx = get_panel_real_ofsx(ps->panel); @@ -1489,6 +1432,10 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co get_panel_size_y(psnext->panel); } } + /* Extra margin for the last panel if it's a box-style panel. */ + if (panelsort[tot - 1].panel->type && panelsort[tot - 1].panel->type->flag & PNL_DRAW_BOX) { + panelsort[tot - 1].panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN; + } /* we interpolate */ done = false; @@ -1506,7 +1453,7 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co } /* set locations for tabbed and sub panels */ - for (panel = region->panels.first; panel; panel = panel->next) { + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->runtime_flag & PNL_ACTIVE) { if (panel->children.first) { align_sub_panels(panel); @@ -1525,13 +1472,12 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co static void ui_panels_size(ScrArea *area, ARegion *region, int *r_x, int *r_y) { - Panel *panel; int align = panel_aligned(area, region); int sizex = 0; int sizey = 0; /* compute size taken up by panels, for setting in view2d */ - for (panel = region->panels.first; panel; panel = panel->next) { + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->runtime_flag & PNL_ACTIVE) { int pa_sizex, pa_sizey; @@ -1617,11 +1563,10 @@ void UI_panels_begin(const bContext *UNUSED(C), ARegion *region) void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) { ScrArea *area = CTX_wm_area(C); - uiBlock *block; Panel *panel, *panel_first; /* offset contents */ - for (block = region->uiblocks.first; block; block = block->next) { + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { if (block->active && block->panel) { ui_offset_panel_block(block); } @@ -1639,7 +1584,7 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) /* tag first panel */ panel_first = NULL; - for (block = region->uiblocks.first; block; block = block->next) { + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { if (block->active && block->panel) { if (!panel_first || block->panel->sortorder < panel_first->sortorder) { panel_first = block->panel; @@ -1657,8 +1602,6 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) void UI_panels_draw(const bContext *C, ARegion *region) { - uiBlock *block; - if (region->alignment != RGN_ALIGN_FLOAT) { UI_ThemeClearColor(TH_BACK); } @@ -1666,13 +1609,13 @@ void UI_panels_draw(const bContext *C, ARegion *region) /* Draw panels, selected on top. Also in reverse order, because * UI blocks are added in reverse order and we need child panels * to draw on top. */ - for (block = region->uiblocks.last; block; block = block->prev) { + LISTBASE_FOREACH_BACKWARD (uiBlock *, block, ®ion->uiblocks) { if (block->active && block->panel && !(block->panel->flag & PNL_SELECT)) { UI_block_draw(C, block); } } - for (block = region->uiblocks.last; block; block = block->prev) { + LISTBASE_FOREACH_BACKWARD (uiBlock *, block, ®ion->uiblocks) { if (block->active && block->panel && (block->panel->flag & PNL_SELECT)) { UI_block_draw(C, block); } @@ -1681,15 +1624,12 @@ void UI_panels_draw(const bContext *C, ARegion *region) void UI_panels_scale(ARegion *region, float new_width) { - uiBlock *block; - uiBut *but; - - for (block = region->uiblocks.first; block; block = block->next) { + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { if (block->panel) { float fac = new_width / (float)block->panel->sizex; block->panel->sizex = new_width; - for (but = block->buttons.first; but; but = but->next) { + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { but->rect.xmin *= fac; but->rect.xmax *= fac; } @@ -1697,48 +1637,6 @@ void UI_panels_scale(ARegion *region, float new_width) } } -/* ------------ panel merging ---------------- */ - -static void check_panel_overlap(ARegion *region, Panel *panel) -{ - Panel *panel_list; - - /* also called with (panel == NULL) for clear */ - - for (panel_list = region->panels.first; panel_list; panel_list = panel_list->next) { - panel_list->flag &= ~PNL_OVERLAP; - if (panel && (panel_list != panel)) { - if (panel_list->runtime_flag & PNL_ACTIVE) { - float safex = 0.2, safey = 0.2; - - if (panel_list->flag & PNL_CLOSEDX) { - safex = 0.05; - } - else if (panel_list->flag & PNL_CLOSEDY) { - safey = 0.05; - } - else if (panel->flag & PNL_CLOSEDX) { - safex = 0.05; - } - else if (panel->flag & PNL_CLOSEDY) { - safey = 0.05; - } - - if (panel_list->ofsx > panel->ofsx - safex * panel->sizex) { - if (panel_list->ofsx + panel_list->sizex < panel->ofsx + (1.0f + safex) * panel->sizex) { - if (panel_list->ofsy > panel->ofsy - safey * panel->sizey) { - if (panel_list->ofsy + panel_list->sizey < - panel->ofsy + (1.0f + safey) * panel->sizey) { - panel_list->flag |= PNL_OVERLAP; - } - } - } - } - } - } - } -} - /************************ panel dragging ****************************/ #define DRAG_REGION_PAD (PNL_HEADER * 0.5) @@ -1779,7 +1677,6 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel) dy += ((float)region->v2d.cur.ymin - data->start_cur_ymin); panel->ofsx = data->startofsx + round_fl_to_int(dx); panel->ofsy = data->startofsy + round_fl_to_int(dy); - check_panel_overlap(region, panel); if (align) { uiAlignPanelStep(area, region, 0.2f, true); @@ -1812,13 +1709,6 @@ static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block, } /* open panel */ else if (!(panel->flag & PNL_CLOSEDY)) { - if (panel->control & UI_PNL_SCALE) { - if (block->rect.xmax - PNL_HEADER <= mx) { - if (block->rect.ymin + PNL_HEADER >= my) { - return PANEL_MOUSE_INSIDE_SCALE; - } - } - } if ((block->rect.xmin <= mx) && (block->rect.xmax >= mx)) { if ((block->rect.ymin <= my) && (block->rect.ymax + PNL_HEADER >= my)) { return PANEL_MOUSE_INSIDE_CONTENT; @@ -1845,10 +1735,9 @@ static void ui_panel_drag_collapse(bContext *C, { ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); - uiBlock *block; Panel *panel; - for (block = region->uiblocks.first; block; block = block->next) { + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { float xy_a_block[2] = {UNPACK2(dragcol_data->xy_init)}; float xy_b_block[2] = {UNPACK2(xy_dst)}; rctf rect = block->rect; @@ -2005,15 +1894,6 @@ static void ui_handle_panel_header( button = 1; } } - else if (block->panel->control & UI_PNL_CLOSE) { - /* whole of header can be used to collapse panel (except top-right corner) */ - if (mx <= block->rect.xmax - 8 - PNL_ICON) { - button = 2; - } - // else if (mx <= block->rect.xmin + 10 + 2 * PNL_ICON + 2) { - // button = 1; - //} - } else if (mx < rect_leftmost) { button = 1; } @@ -2022,14 +1902,28 @@ static void ui_handle_panel_header( if (button == 2) { /* close */ ED_region_tag_redraw(region); } - else { /* collapse */ + else { + /* Collapse and expand panels. */ + if (ctrl) { - /* Only collapse all for parent panels. */ + /* For parent panels, collapse all other panels or toggle children. */ if (block->panel->type != NULL && block->panel->type->parent == NULL) { - panels_collapse_all(C, area, region, block->panel); + if (block->panel->flag & PNL_CLOSED || BLI_listbase_is_empty(&block->panel->children)) { + panels_collapse_all(C, area, region, block->panel); - /* reset the view - we don't want to display a view without content */ - UI_view2d_offset(®ion->v2d, 0.0f, 1.0f); + /* Reset the view - we don't want to display a view without content. */ + UI_view2d_offset(®ion->v2d, 0.0f, 1.0f); + } + else { + const int closed_flag = (align == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY; + /* If a panel has sub-panels and it's open, toggle the expansion + * of the sub-panels (based on the expansion of the first subpanel). */ + Panel *first_child = block->panel->children.first; + BLI_assert(first_child != NULL); + panel_set_flag_recursive( + block->panel, closed_flag, (first_child->flag & PNL_CLOSED) == 0); + block->panel->flag |= closed_flag; + } } } @@ -2160,9 +2054,7 @@ void UI_panel_category_active_set_default(ARegion *region, const char *idname) const char *UI_panel_category_active_get(ARegion *region, bool set_fallback) { - PanelCategoryStack *pc_act; - - for (pc_act = region->panels_category_active.first; pc_act; pc_act = pc_act->next) { + LISTBASE_FOREACH (PanelCategoryStack *, pc_act, ®ion->panels_category_active) { if (UI_panel_category_find(region, pc_act->idname)) { return pc_act->idname; } @@ -2181,9 +2073,7 @@ const char *UI_panel_category_active_get(ARegion *region, bool set_fallback) PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *region, const int x, const int y) { - PanelCategoryDyn *ptd; - - for (ptd = region->panels_category.first; ptd; ptd = ptd->next) { + LISTBASE_FOREACH (PanelCategoryDyn *, ptd, ®ion->panels_category) { if (BLI_rcti_isect_pt(&ptd->rect, x, y)) { return ptd; } @@ -2351,7 +2241,6 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) const uiFontStyle *fstyle = &style->widget; const int fontid = fstyle->uifont_id; short fstyle_points = fstyle->points; - PanelCategoryDyn *pc_dyn; const float aspect = ((uiBlock *)region->uiblocks.first)->aspect; const float zoom = 1.0f / aspect; const int px = max_ii(1, round_fl_to_int(U.pixelsize)); @@ -2428,7 +2317,8 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) } /* calculate tab rect's and check if we need to scale down */ - for (pc_dyn = region->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) { + LISTBASE_FOREACH (PanelCategoryDyn *, pc_dyn, ®ion->panels_category) { + rcti *rct = &pc_dyn->rect; const char *category_id = pc_dyn->idname; const char *category_id_draw = IFACE_(category_id); @@ -2446,7 +2336,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) if (y_ofs > BLI_rcti_size_y(&v2d->mask)) { scaletabs = (float)BLI_rcti_size_y(&v2d->mask) / (float)y_ofs; - for (pc_dyn = region->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) { + LISTBASE_FOREACH (PanelCategoryDyn *, pc_dyn, ®ion->panels_category) { rcti *rct = &pc_dyn->rect; rct->ymin = ((rct->ymin - v2d->mask.ymax) * scaletabs) + v2d->mask.ymax; rct->ymax = ((rct->ymax - v2d->mask.ymax) * scaletabs) + v2d->mask.ymax; @@ -2491,7 +2381,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) const int divider_xmax = is_left ? (v2d->mask.xmin + category_tabs_width) : (v2d->mask.xmax - (category_tabs_width + px)) + px; - for (pc_dyn = region->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) { + LISTBASE_FOREACH (PanelCategoryDyn *, pc_dyn, ®ion->panels_category) { const rcti *rct = &pc_dyn->rect; const char *category_id = pc_dyn->idname; const char *category_id_draw = IFACE_(category_id); @@ -2687,7 +2577,6 @@ int ui_handler_panel_region(bContext *C, ARegion *region, const uiBut *active_but) { - uiBlock *block; Panel *panel; int retval, mx, my; bool has_category_tabs = UI_panel_category_is_visible(region); @@ -2726,7 +2615,7 @@ int ui_handler_panel_region(bContext *C, return retval; } - for (block = region->uiblocks.last; block; block = block->prev) { + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { uiPanelMouseState mouse_state; mx = event->x; @@ -2792,7 +2681,7 @@ int ui_handler_panel_region(bContext *C, retval = WM_UI_HANDLER_BREAK; break; } - else if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(panel->flag & PNL_CLOSED)) { + if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(panel->flag & PNL_CLOSED)) { panel_activate_state(C, panel, PANEL_STATE_DRAG_SCALE); retval = WM_UI_HANDLER_BREAK; break; @@ -2805,51 +2694,6 @@ int ui_handler_panel_region(bContext *C, break; } } - else if (event->type == EVT_ESCKEY) { - /*XXX 2.50*/ -#if 0 - if (block->handler) { - rem_blockhandler(area, block->handler); - ED_region_tag_redraw(region); - retval = WM_UI_HANDLER_BREAK; - } -#endif - } - else if (event->type == EVT_PADPLUSKEY || event->type == EVT_PADMINUS) { -#if 0 /* XXX make float panel exception? */ - int zoom = 0; - - /* if panel is closed, only zoom if mouse is over the header */ - if (panel->flag & (PNL_CLOSEDX | PNL_CLOSEDY)) { - if (inside_header) { - zoom = 1; - } - } - else { - zoom = 1; - } - - if (zoom) { - ScrArea *area = CTX_wm_area(C); - SpaceLink *sl = area->spacedata.first; - - if (area->spacetype != SPACE_PROPERTIES) { - if (!(panel->control & UI_PNL_SCALE)) { - if (event->type == PADPLUSKEY) { - sl->blockscale += 0.1; - } - else { - sl->blockscale -= 0.1; - } - CLAMP(sl->blockscale, 0.6, 1.0); - - ED_region_tag_redraw(region); - retval = WM_UI_HANDLER_BREAK; - } - } - } -#endif - } } } } @@ -2857,6 +2701,56 @@ int ui_handler_panel_region(bContext *C, return retval; } +static void ui_panel_custom_data_set_recursive(Panel *panel, PointerRNA *custom_data) +{ + panel->runtime.custom_data_ptr = custom_data; + + LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { + ui_panel_custom_data_set_recursive(child_panel, custom_data); + } +} + +void UI_panel_custom_data_set(Panel *panel, PointerRNA *custom_data) +{ + BLI_assert(panel->type != NULL); + + /* Free the old custom data, which should be shared among all of the panel's sub-panels. */ + if (panel->runtime.custom_data_ptr != NULL) { + MEM_freeN(panel->runtime.custom_data_ptr); + } + + ui_panel_custom_data_set_recursive(panel, custom_data); +} + +PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wmEvent *event) +{ + ARegion *region = CTX_wm_region(C); + + Panel *panel = NULL; + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { + panel = block->panel; + if (panel == NULL) { + continue; + } + + int mx = event->x; + int my = event->y; + ui_window_to_block(region, block, &mx, &my); + int mouse_state = ui_panel_mouse_state_get(block, panel, mx, my); + if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) { + break; + } + } + + if (panel == NULL) { + return NULL; + } + + PointerRNA *customdata = panel->runtime.custom_data_ptr; + + return customdata; +} + /**************** window level modal panel interaction **************/ /* note, this is modal handler and should not swallow events for animation */ @@ -2897,9 +2791,7 @@ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata) if (data && data->state == PANEL_STATE_ANIMATION) { return WM_UI_HANDLER_CONTINUE; } - else { - return WM_UI_HANDLER_BREAK; - } + return WM_UI_HANDLER_BREAK; } static void ui_handler_remove_panel(bContext *C, void *userdata) @@ -2909,24 +2801,6 @@ static void ui_handler_remove_panel(bContext *C, void *userdata) panel_activate_state(C, panel, PANEL_STATE_EXIT); } -/** - * Set selection state for a panel and its subpanels. The subpanels need to know they are selected - * too so they can be drawn above their parent when it is dragged. - */ -static void set_panel_selection(Panel *panel, bool value) -{ - if (value) { - panel->flag |= PNL_SELECT; - } - else { - panel->flag &= ~PNL_SELECT; - } - - LISTBASE_FOREACH (Panel *, child, &panel->children) { - set_panel_selection(child, value); - } -} - static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state) { uiHandlePanelData *data = panel->activedata; @@ -2939,22 +2813,13 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS bool was_drag_drop = (data && data->state == PANEL_STATE_DRAG); + /* Set selection state for the panel and its sub-panels, which need to know they are selected + * too so they can be drawn above their parent when it's dragged. */ if (state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) { - if (data && data->state != PANEL_STATE_ANIMATION) { - /* XXX: - * - the panel tabbing function call below (test_add_new_tabs()) has been commented out - * "It is too easy to do by accident when reordering panels, - * is very hard to control and use, and has no real benefit." - BillRey - * Aligorith, 2009Sep - */ - // test_add_new_tabs(region); // also copies locations of tabs in dragged panel - check_panel_overlap(region, NULL); /* clears */ - } - - set_panel_selection(panel, false); + panel_set_flag_recursive(panel, PNL_SELECT, false); } else { - set_panel_selection(panel, true); + panel_set_flag_recursive(panel, PNL_SELECT, true); } if (data && data->animtimer) { |