[Bf-blender-cvs] [0c83ef567c5] master: UI: Auto-scroll to keep active text buttons in view

Julian Eisel noreply at git.blender.org
Thu Jul 15 16:14:26 CEST 2021


Commit: 0c83ef567c503abf1e8305062fc8b3e7de17b257
Author: Julian Eisel
Date:   Tue Jul 13 17:06:15 2021 +0200
Branches: master
https://developer.blender.org/rB0c83ef567c503abf1e8305062fc8b3e7de17b257

UI: Auto-scroll to keep active text buttons in view

If a text button is activated that is not in view (i.e. scrolled away),
the scrolling will now be adjusted to have it in view (with some
small additional margin). While entering text, the view may also be
updated should the button move out of view, for whatever reason. For the
most part, this feature shouldn't be needed and won't kick in, except
when a clicked on text button is partially out of view or very close to
the region edge. It's however quite important for the previously
committed feature, that is, pressing Ctrl+F to start searching in a UI
list. The end of the list where the scroll button appears may not be in
view. Plus while filtering the number of visible items changes so the
scrolling has to be updated to keep the search button visible.

Note that I disabled the auto-scrolling for when the text button spawned
an additional popup, like for search-box buttons. That is because
current code assumes the button to have a fixed position while the popup
is open. There is no code to update the popup position together with the
button/scrolling.

I also think that the logic added here could be used in more places,
e.g. for the "ensure file in view" logic the File Browser does.

===================================================================

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_query.c
M	source/blender/editors/interface/interface_utils.c
M	source/blender/editors/screen/area.c

===================================================================

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 58eaba480e1..020ab5f5b66 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -707,6 +707,7 @@ void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2],
 void UI_block_end(const struct bContext *C, uiBlock *block);
 void UI_block_draw(const struct bContext *C, struct uiBlock *block);
 void UI_blocklist_update_window_matrix(const struct bContext *C, const struct ListBase *lb);
+void UI_blocklist_update_view_for_buttons(const struct bContext *C, const struct ListBase *lb);
 void UI_blocklist_draw(const struct bContext *C, const struct ListBase *lb);
 void UI_block_update_from_old(const struct bContext *C, struct uiBlock *block);
 
@@ -2654,6 +2655,8 @@ bool UI_editsource_enable_check(void);
 void UI_editsource_active_but_test(uiBut *but);
 void UI_editsource_but_replace(const uiBut *old_but, uiBut *new_but);
 
+void UI_but_ensure_in_view(const struct bContext *C, struct ARegion *region, const uiBut *but);
+
 /* UI_butstore_ helpers */
 typedef struct uiButStore uiButStore;
 typedef struct uiButStoreElem uiButStoreElem;
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 32b86119753..d5316df0e0c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -131,12 +131,10 @@ static bool ui_but_is_unit_radians(const uiBut *but)
 
 /* ************* window matrix ************** */
 
-void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
+void ui_block_to_region_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
 {
   const int getsizex = BLI_rcti_size_x(&region->winrct) + 1;
   const int getsizey = BLI_rcti_size_y(&region->winrct) + 1;
-  const int sx = region->winrct.xmin;
-  const int sy = region->winrct.ymin;
 
   float gx = *r_x;
   float gy = *r_y;
@@ -146,14 +144,19 @@ void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, fl
     gy += block->panel->ofsy;
   }
 
-  *r_x = ((float)sx) +
-         ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] +
+  *r_x = ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] +
                                              block->winmat[3][0]));
-  *r_y = ((float)sy) +
-         ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] +
+  *r_y = ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] +
                                              block->winmat[3][1]));
 }
 
+void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
+{
+  ui_block_to_region_fl(region, block, r_x, r_y);
+  *r_x += region->winrct.xmin;
+  *r_y += region->winrct.ymin;
+}
+
 void ui_block_to_window(const ARegion *region, uiBlock *block, int *r_x, int *r_y)
 {
   float fx = *r_x;
@@ -165,6 +168,16 @@ void ui_block_to_window(const ARegion *region, uiBlock *block, int *r_x, int *r_
   *r_y = (int)(fy + 0.5f);
 }
 
+void ui_block_to_region_rctf(const ARegion *region,
+                             uiBlock *block,
+                             rctf *rct_dst,
+                             const rctf *rct_src)
+{
+  *rct_dst = *rct_src;
+  ui_block_to_region_fl(region, block, &rct_dst->xmin, &rct_dst->ymin);
+  ui_block_to_region_fl(region, block, &rct_dst->xmax, &rct_dst->ymax);
+}
+
 void ui_block_to_window_rctf(const ARegion *region,
                              uiBlock *block,
                              rctf *rct_dst,
@@ -249,6 +262,14 @@ void ui_window_to_region_rcti(const ARegion *region, rcti *rect_dst, const rcti
   rect_dst->ymax = rct_src->ymax - region->winrct.ymin;
 }
 
+void ui_window_to_region_rctf(const ARegion *region, rctf *rect_dst, const rctf *rct_src)
+{
+  rect_dst->xmin = rct_src->xmin - region->winrct.xmin;
+  rect_dst->xmax = rct_src->xmax - region->winrct.xmin;
+  rect_dst->ymin = rct_src->ymin - region->winrct.ymin;
+  rect_dst->ymax = rct_src->ymax - region->winrct.ymin;
+}
+
 void ui_region_to_window(const ARegion *region, int *r_x, int *r_y)
 {
   *r_x += region->winrct.xmin;
@@ -3440,6 +3461,15 @@ void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb)
   }
 }
 
+void UI_blocklist_update_view_for_buttons(const bContext *C, const ListBase *lb)
+{
+  LISTBASE_FOREACH (uiBlock *, block, lb) {
+    if (block->active) {
+      ui_but_update_view_for_active(C, block);
+    }
+  }
+}
+
 void UI_blocklist_draw(const bContext *C, const ListBase *lb)
 {
   LISTBASE_FOREACH (uiBlock *, block, lb) {
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index cd975e97613..5bd7ac28664 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -3519,6 +3519,11 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
 
   ui_but_update(but);
 
+  /* Popup blocks don't support moving after creation, so don't change the view for them. */
+  if (!data->searchbox) {
+    UI_but_ensure_in_view(C, data->region, but);
+  }
+
   WM_cursor_modal_set(win, WM_CURSOR_TEXT_EDIT);
 
 #ifdef WITH_INPUT_IME
@@ -8883,6 +8888,26 @@ void UI_context_update_anim_flag(const bContext *C)
   }
 }
 
+/**
+ * In some cases we may want to update the view (#View2D) in-between layout definition and drawing.
+ * E.g. to make sure a button is visible while editing.
+ */
+void ui_but_update_view_for_active(const bContext *C, const uiBlock *block)
+{
+  uiBut *active_but = ui_block_active_but_get(block);
+  if (!active_but || !active_but->active || !active_but->changed || active_but->block != block) {
+    return;
+  }
+  /* If there is a search popup attached to the button, don't change the view. The popups don't
+   * support updating the position to the button position nicely. */
+  uiHandleButtonData *data = active_but->active;
+  if (data->searchbox) {
+    return;
+  }
+
+  UI_but_ensure_in_view(C, active_but->active->region, active_but);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index efc94b89046..a3a9776a510 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -597,11 +597,19 @@ typedef struct uiSafetyRct {
 
 void ui_fontscale(short *points, float aspect);
 
+extern void ui_block_to_region_fl(const struct ARegion *region,
+                                  uiBlock *block,
+                                  float *r_x,
+                                  float *r_y);
 extern void ui_block_to_window_fl(const struct ARegion *region,
                                   uiBlock *block,
                                   float *x,
                                   float *y);
 extern void ui_block_to_window(const struct ARegion *region, uiBlock *block, int *x, int *y);
+extern void ui_block_to_region_rctf(const struct ARegion *region,
+                                    uiBlock *block,
+                                    rctf *rct_dst,
+                                    const rctf *rct_src);
 extern void ui_block_to_window_rctf(const struct ARegion *region,
                                     uiBlock *block,
                                     rctf *rct_dst,
@@ -620,6 +628,9 @@ extern void ui_window_to_region(const struct ARegion *region, int *x, int *y);
 extern void ui_window_to_region_rcti(const struct ARegion *region,
                                      rcti *rect_dst,
                                      const rcti *rct_src);
+extern void ui_window_to_region_rctf(const struct ARegion *region,
+                                     rctf *rect_dst,
+                                     const rctf *rct_src);
 extern void ui_region_to_window(const struct ARegion *region, int *x, int *y);
 extern void ui_region_winrct_get_no_margin(const struct ARegion *region, struct rcti *r_rect);
 
@@ -944,6 +955,7 @@ extern void ui_but_execute_end(struct bContext *C,
                                uiBut *but,
                                void *active_back);
 extern void ui_but_active_free(const struct bContext *C, uiBut *but);
+extern void ui_but_update_view_for_active(const struct bContext *C, const uiBlock *block);
 extern int ui_but_menu_direction(uiBut *but);
 extern void ui_but_text_password_hide(char password_str[128], uiBut *but, const bool restore);
 extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction);
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
index ecb96a83355..8534c95b6fd 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -572,6 +572,17 @@ size_t ui_but_tip_len_only_first_line(const uiBut *but)
 /** \name Block (#uiBlock) State
  * \{ */
 
+uiBut *ui_block_active_but_get(const uiBlock *block)
+{
+  LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+    if (but->active) {
+      return but;
+    }
+  }
+
+  return NULL;
+}
+
 bool ui_block_is_menu(const uiBlock *block)
 {
   return (((block->flag & UI_BLOCK_LOOP) != 0) &&
@@ -675,10 +686,9 @@ uiBlock *ui_block_find_mouse_over(const ARegion *region, const wmEvent *event, b
 uiBut *ui_region_find_active_but(ARegion *region)
 {
   LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
-    LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
-      if (but->active) {
-        return but;
-      }
+    uiBut *but = ui_block_active_but_get(block);
+    if (but) {
+      return but;
     }
   }
 
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 7ea02226f02..aa6dff3952a 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -29,6 +29,8 @@

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list