Remap user dialog - where to go digging to make this resizable?

I’ve been forced to use this part of blender a lot recently and it’s annoying me that the dialog isn’t resizable, and the default size is frustratingly small. I wondered if there was a design reason for this, and if not, where should I go digging to explore making this wider by-default and also resizable. I’ve only poked the UI code very lightly (for the ocean modifier work), so I thought asking here was perhaps wiser than just going in uninformed.

Which “user dialog” are you talking about? Because the sizes are chosen to fit the content. Well, at least for the English interface.

That’s the label attached when I go to the

Outliner / Blender File view

expand the images section.

Right click an image and ‘remap user’. In 3.0, it looks like the label changed, but the resulting dialog remains problematic. It’s not resizable, it doesn’t resize itself to fit the content and you cannot tell anything useful without hovering over the NewID section until a tooltip shows up, where the associated value then pops up :


I was hoping it might be ~straightforward to locate this code and figure out how to make it resizable, or at least resize itself to fit the content (up to some reasonable maximum dimension to handle pathological cases)

As an aside, it’s not clear whether this works with multi-selections and it seems to pick a ‘New ID’ value somewhat at random.

1 Like

I don’t really see a big problem with this particular dialog. You just open the selector and see the full names. Well, that is, there is no reason for you to scale this particular dialog.

In general, of course, it’s nice to be able to resize dialogs manually.

If I were you, I would first take a look at “ui_handle_menu_event”, see “USE_DRAG_POPUP”, this allows you to move the dialog. I guess resizing should work in a similar way.

The issue is about what the new ID is set to before you click OK. When you can’t see it, you can’t visually confirm that the selection is correct. I’ve been rewiring a lot of stuff recently and this has been quite frustrating / time consuming so that’s where I’m coming from. I’ll see how far I can get; I’m just getting the development environment re-established (looks like the server is quite slow at the moment to deliver the sources).

So digging around, I find the creation code here :

static int outliner_id_remap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
  ARegion *region = CTX_wm_region(C);
  float fmval[2];

  if (!RNA_property_is_set(op->ptr, RNA_struct_find_property(op->ptr, "id_type"))) {
    UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);

    outliner_id_remap_find_tree_element(C, op, &space_outliner->tree, fmval[1]);

  return WM_operator_props_dialog_popup(C, op, 200);

where 200 is the width.

Poking deeper into the related code, I find :

void OUTLINER_OT_id_remap(wmOperatorType *ot)
  PropertyRNA *prop;

  /* identifiers */
  ot->name = "Outliner ID Data Remap";
  ot->idname = "OUTLINER_OT_id_remap";

  /* callbacks */
  ot->invoke = outliner_id_remap_invoke;
  ot->exec = outliner_id_remap_exec;
  ot->poll = ED_operator_outliner_active;

  /* Flags. */

  prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", "");
  RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);

  prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", "Old ID to replace");
  RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, outliner_id_itemf);
  RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE | PROP_HIDDEN);

  ot->prop = RNA_def_enum(ot->srna,
                          "New ID",
                          "New ID to remap all selected IDs' users to");
  RNA_def_property_enum_funcs_runtime(ot->prop, NULL, NULL, outliner_id_itemf);
  RNA_def_property_flag(ot->prop, PROP_ENUM_NO_TRANSLATE);

and it looks like the wmOperatorType and the OPTYPE flags do not offer any resizing support that can be trivally enabled. I can simply make the width greater (e.g. 500), and this immediately improves usability :

I wonder if this is sufficient; I still don’t yet understand why the type and dropdowns don’t take full advantage


I cannot find any way to query the menu contents to autosize this based on the longest text (with an upper limit). @brecht : does the UI toolkit support this; would it be desirable? Just picking an arbitrary value to force the width seems kind of suboptimal. Also, about half the width is wasted here due to the left hand column being right-aligned; is that expected?

This is a bit of a strange question because this design is used throughout Blender, in almost every panel.

Why is it strange? Surely the user interface exists to present information to the user efficiently and effectively? If a general policy doesn’t fit well in a specific case, there should probably be a way to override this for the benefit of the user. Here, I would argue that it makes little sense to take a minimal UI and waste half the space on padding for some tiny labels, forcing the panel wide in order to fit reasonably-sized menus. What benefit does that padding on the left bring? I’m having to force a panel to 500 pixels wide when 300 might be enough without that padding. Not everyone has high resolution screens…

I think generally these types of popups should be made much bigger, and then you would make changes to improve the layout. Maybe reducing proportion used by the labels, adding an empty line below the title and above the OK button, making the OK button smaller, etc.

I don’t think there’s is a complete mechanism for dynamically sizing these dialogs. The layout engine has some idea of the required size, but it’s not integrated with the dialog window sizing.

However I’m not sure dynamically sized dialogs are really the correct solution here. That can be unpredictable for muscle memory, and really I think these dialogs can just be bigger to cover most cases. If you then still have a very long name that doesn’t fit, I don’t think making the dialog very wide is necessarily a good thing.

Thanks @brecht. So, trying to figure out what the approach to take is now, I don’t see a way to override the forced layout from the overall system. Assuming that requires more work, from people more knowledgeable about the UI system, would it be acceptable (if crude) to simply bump the minimum size up to, say, 500? I was nervous about an arbitrary value in case the user’s display cannot accommodate the hard-coded value (which may be why the very low 200 value was chosen originally).

Alternatively, do you have a more elegant approach already in mind?

I would say that for this dialog 400 is the maximum that looks good.
And it seems that this is quite enough to understand which ID is selected.

I don’t think this type of dialogs should be much bigger in the general case.
This is a quick pop-up under the cursor. They often look like below.

We can’t reduce the proportion used by labels because they can be long, especially in some languages.

And although the OK button doesn’t look good right now, I don’t think making it smaller will make it better.

the problem is not that the label is right-aligned, it’s that Blender’s UI doesn’t have any type of ‘elastic’ widget or column to fill a particular space, so in situations like this you have a huge pointless gap on the left side while information is being truncated on the right.


I’m honestly not sure how much this dialog is used so the following is just something to play with. But you did start off by asking where to look. So the following diff makes it look like the following:


diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index e449e4a609bb..bc33d53031f6 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -652,21 +652,21 @@ static int outliner_id_remap_invoke(bContext *C, wmOperator *op, const wmEvent *
   SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
   ARegion *region = CTX_wm_region(C);
   float fmval[2];
   if (!RNA_property_is_set(op->ptr, RNA_struct_find_property(op->ptr, "id_type"))) {
     UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
     outliner_id_remap_find_tree_element(C, op, &space_outliner->tree, fmval[1]);
-  return WM_operator_props_dialog_popup(C, op, 200);
+  return WM_operator_props_dialog_popup(C, op, 300);
 static const EnumPropertyItem *outliner_id_itemf(bContext *C,
                                                  PointerRNA *ptr,
                                                  PropertyRNA *UNUSED(prop),
                                                  bool *r_free)
   if (C == NULL) {
     return DummyRNA_NULL_items;
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index ffdc99152b1d..52d60eea8984 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1494,30 +1494,34 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *userD
   UI_block_flag_disable(block, UI_BLOCK_LOOP);
   UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_REGULAR);
   /* intentionally don't use 'UI_BLOCK_MOVEMOUSE_QUIT', some dialogues have many items
    * where quitting by accident is very annoying */
   UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_NUMSELECT);
   uiLayout *layout = UI_block_layout(
       block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
-  uiTemplateOperatorPropertyButs(
+  uiTemplateOperatorPropertyButs(C,
+                                 layout,
+                                 op,
+                                 UI_BUT_LABEL_ALIGN_COLUMN,
   /* clear so the OK button is left alone */
   UI_block_func_set(block, NULL, NULL, NULL);
   /* new column so as not to interfere with custom layouts T26436. */
     uiLayout *col = uiLayoutColumn(layout, false);
     uiBlock *col_block = uiLayoutGetBlock(col);
+    uiItemS_ex(layout, 1.0f);
     /* Create OK button, the callback of which will execute op */
     uiBut *but = uiDefBut(
         col_block, UI_BTYPE_BUT, 0, IFACE_("OK"), 0, -30, 0, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
     UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
     UI_but_func_set(but, dialog_exec_cb, data, col_block);
   /* center around the mouse */
       block, 6 * U.dpi_fac, (const int[2]){data->width / -2, data->height / 2});


Yes, thanks, that’s the bit I found earlier (Remap user dialog - where to go digging to make this resizable? - #6 by phil.stopford), but it does not seem to be an ideal fix due to the padding on the left and the arbitrary nature of the value (the dialog cannot adjust its width based on the menu content, up to some maximum).

This may be a case of making it better, but accepting it will be imperfect unless the UI toolkit has some extra tricks up its sleeve. This then leads to a bit of horse trading about what the new value should be.

Hmmm… not seeing anything earlier in this thread that is at all similar to the patch I sent

As shown in my screen capture it removes the padding on the left so there is no wasted space on the left side. So by only making the dialog 50% wider it can show values that are 3X longer.

Ah, sorry, I was focusing on the width change; missed that aspect of your change. Is that something you could/would submit for consideration?

That’s how the dialogs looked before 2.8, and we changed it everywhere to a new split layout.
Also note that these changes affect other dialogs that do not have this width issue.

Yes, I was working with William all through that time. But I see no reason why dialogs can’t have a format that suits them best as they aren’t as long and vertically constrained as other areas.

For sure and I really didn’t look into how this change affects other areas, but only assumed they were all similar small dialogs. I really like the extra space between the content and the “okay” button.

No. I’m assuming (from the text of your initial post and from where this thread exists) that this is something that you would explore further, test, refine, and possibly submit as a patch.

Fair enough; didn’t want to assume, so felt safer to ask