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:
Diffstat (limited to 'source/blender/editors/interface/interface_panel.c')
-rw-r--r--source/blender/editors/interface/interface_panel.c523
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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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(&region->v2d, 0.0f, 1.0f);
+ /* Reset the view - we don't want to display a view without content. */
+ UI_view2d_offset(&region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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) {