UI: use single column layout for image settings panels
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sun, 19 May 2019 12:51:21 +0000 (14:51 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Sun, 19 May 2019 14:24:53 +0000 (16:24 +0200)
release/scripts/startup/bl_ui/properties_data_empty.py
release/scripts/startup/bl_ui/space_node.py
source/blender/editors/space_image/image_buttons.c

index 8302bc7..ca1ebb0 100644 (file)
@@ -27,7 +27,8 @@ class DataButtonsPanel:
 
     @classmethod
     def poll(cls, context):
-        return (context.object and context.object.type == 'EMPTY')
+        ob = context.object
+        return (ob and ob.type == 'EMPTY')
 
 
 class DATA_PT_empty(DataButtonsPanel, Panel):
@@ -36,6 +37,7 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
     def draw(self, context):
         layout = self.layout
         layout.use_property_split = True
+        layout.use_property_decorate = False
 
         ob = context.object
 
@@ -43,11 +45,6 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
         layout.prop(ob, "empty_display_size", text="Size")
 
         if ob.empty_display_type == 'IMAGE':
-            layout.template_ID(ob, "data", open="image.open", unlink="object.unlink_data")
-            layout.template_image(ob, "data", ob.image_user, compact=True)
-
-            layout.row(align=True).row(align=True)
-
             layout.prop(ob, "use_empty_image_alpha")
 
             col = layout.column()
@@ -65,8 +62,25 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
             col.prop(ob, "show_empty_image_perspective", text="Display Perspective")
 
 
+class DATA_PT_empty_image(DataButtonsPanel, Panel):
+    bl_label = "Image"
+
+    @classmethod
+    def poll(cls, context):
+        ob = context.object
+        return (ob and ob.type == 'EMPTY' and ob.empty_display_type == 'IMAGE')
+
+    def draw(self, context):
+        layout = self.layout
+        ob = context.object
+        layout.template_ID(ob, "data", open="image.open", unlink="object.unlink_data")
+        layout.separator();
+        layout.template_image(ob, "data", ob.image_user, compact=True)
+
+
 classes = (
     DATA_PT_empty,
+    DATA_PT_empty_image,
 )
 
 if __name__ == "__main__":  # only for live edit.
index 45ff4ce..1777510 100644 (file)
@@ -490,7 +490,6 @@ class NODE_PT_active_node_properties(Panel):
     bl_category = "Item"
     bl_label = "Properties"
     bl_options = {'DEFAULT_CLOSED'}
-    bl_parent_id = 'NODE_PT_active_node_generic'
 
     @classmethod
     def poll(cls, context):
index 9f42932..44290a3 100644 (file)
 #define B_NOP -1
 #define MAX_IMAGE_INFO_LEN 128
 
-/* proto */
-
-static void image_info(
-    Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len)
-{
-  size_t ofs = 0;
-
-  str[0] = 0;
-  if (ima == NULL) {
-    return;
-  }
-
-  if (ibuf == NULL) {
-    ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs);
-  }
-  else {
-    if (ima->source == IMA_SRC_MOVIE) {
-      ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs);
-      if (BKE_image_has_anim(ima)) {
-        ofs += BLI_snprintf(
-            str + ofs,
-            len - ofs,
-            IFACE_(" %d frs"),
-            IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN));
-      }
-    }
-    else {
-      ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs);
-    }
-
-    ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y);
-
-    if (ibuf->rect_float) {
-      if (ibuf->channels != 4) {
-        ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels);
-      }
-      else if (ibuf->planes == R_IMF_PLANES_RGBA) {
-        ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs);
-      }
-      else {
-        ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs);
-      }
-    }
-    else {
-      if (ibuf->planes == R_IMF_PLANES_RGBA) {
-        ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs);
-      }
-      else {
-        ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs);
-      }
-    }
-    if (ibuf->zbuf || ibuf->zbuf_float) {
-      ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
-    }
-
-    if (ima->source == IMA_SRC_SEQUENCE) {
-      const char *file = BLI_last_slash(ibuf->name);
-      if (file == NULL) {
-        file = ibuf->name;
-      }
-      else {
-        file++;
-      }
-      ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file);
-    }
-  }
-
-  /* the frame number, even if we cant */
-  if (ima->source == IMA_SRC_SEQUENCE) {
-    /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
-    const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL);
-    ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr);
-  }
-}
-
 /* gets active viewer user */
 struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
 {
@@ -823,6 +748,22 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
   RNA_property_update(C, &cb->ptr, cb->prop);
 }
 
+static bool image_has_alpha(Image *ima, ImageUser *iuser)
+{
+  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+  if (ibuf == NULL) {
+    return false;
+  }
+
+  int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
+  char valid_channels = BKE_imtype_valid_channels(imtype, false);
+  bool has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
+
+  BKE_image_release_ibuf(ima, ibuf, NULL);
+
+  return has_alpha;
+}
+
 void uiTemplateImage(uiLayout *layout,
                      bContext *C,
                      PointerRNA *ptr,
@@ -831,24 +772,11 @@ void uiTemplateImage(uiLayout *layout,
                      bool compact,
                      bool multiview)
 {
-  PropertyRNA *prop;
-  PointerRNA imaptr;
-  RNAUpdateCb *cb;
-  Image *ima;
-  ImageUser *iuser;
-  Scene *scene = CTX_data_scene(C);
-  SpaceImage *space_image = CTX_wm_space_image(C);
-  uiLayout *row, *split, *col;
-  uiBlock *block;
-  char str[MAX_IMAGE_INFO_LEN];
-
-  void *lock;
-
   if (!ptr->data) {
     return;
   }
 
-  prop = RNA_struct_find_property(ptr, propname);
+  PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
   if (!prop) {
     printf(
         "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
@@ -863,22 +791,19 @@ void uiTemplateImage(uiLayout *layout,
     return;
   }
 
-  block = uiLayoutGetBlock(layout);
+  uiBlock *block = uiLayoutGetBlock(layout);
 
-  imaptr = RNA_property_pointer_get(ptr, prop);
-  ima = imaptr.data;
-  iuser = userptr->data;
+  PointerRNA imaptr = RNA_property_pointer_get(ptr, prop);
+  Image *ima = imaptr.data;
+  ImageUser *iuser = userptr->data;
 
+  Scene *scene = CTX_data_scene(C);
   BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
 
-  cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
-  cb->ptr = *ptr;
-  cb->prop = prop;
-  cb->iuser = iuser;
-
   uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
   uiLayoutSetContextPointer(layout, "edit_image_user", userptr);
 
+  SpaceImage *space_image = CTX_wm_space_image(C);
   if (!compact && (space_image == NULL || iuser != &space_image->iuser)) {
     uiTemplateID(layout,
                  C,
@@ -889,165 +814,178 @@ void uiTemplateImage(uiLayout *layout,
                  NULL,
                  UI_TEMPLATE_ID_FILTER_ALL,
                  false);
+
+    if (ima != NULL) {
+      uiItemS(layout);
+    }
   }
 
-  if (ima) {
-    UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
+  if (ima == NULL) {
+    return;
+  }
 
-    if (ima->source == IMA_SRC_VIEWER) {
-      ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
-      image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
-      BKE_image_release_ibuf(ima, ibuf, lock);
+  if (ima->source == IMA_SRC_VIEWER) {
+    /* Viewer images. */
+    uiTemplateImageInfo(layout, C, ima, iuser);
 
-      uiItemL(layout, ima->id.name + 2, ICON_NONE);
-      uiItemL(layout, str, ICON_NONE);
+    if (ima->type == IMA_TYPE_COMPOSITE) {
+    }
+    else if (ima->type == IMA_TYPE_R_RESULT) {
+      /* browse layer/passes */
+      RenderResult *rr;
+      const float dpi_fac = UI_DPI_FAC;
+      const int menus_width = 230 * dpi_fac;
+
+      /* use BKE_image_acquire_renderresult  so we get the correct slot in the menu */
+      rr = BKE_image_acquire_renderresult(scene, ima);
+      uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
+      BKE_image_release_renderresult(scene, ima);
+    }
 
-      if (ima->type == IMA_TYPE_COMPOSITE) {
-      }
-      else if (ima->type == IMA_TYPE_R_RESULT) {
-        /* browse layer/passes */
-        RenderResult *rr;
-        const float dpi_fac = UI_DPI_FAC;
-        const int menus_width = 230 * dpi_fac;
-
-        /* use BKE_image_acquire_renderresult  so we get the correct slot in the menu */
-        rr = BKE_image_acquire_renderresult(scene, ima);
-        uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
-        BKE_image_release_renderresult(scene, ima);
-      }
+    return;
+  }
+
+  /* Set custom callback for property updates. */
+  RNAUpdateCb *cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
+  cb->ptr = *ptr;
+  cb->prop = prop;
+  cb->iuser = iuser;
+  UI_block_funcN_set(block, rna_update_cb, cb, NULL);
+
+  /* Disable editing if image was modified, to avoid losing changes. */
+  const bool is_dirty = BKE_image_is_dirty(ima);
+  if (is_dirty) {
+    uiLayout *row = uiLayoutRow(layout, true);
+    uiItemO(row, IFACE_("Save"), ICON_NONE, "image.save");
+    uiItemO(row, IFACE_("Discard Changes"), ICON_NONE, "image.reload");
+    uiItemS(layout);
+  }
+
+  layout = uiLayoutColumn(layout, false);
+  uiLayoutSetEnabled(layout, !is_dirty);
+  uiLayoutSetPropDecorate(layout, false);
+
+  /* Image source */
+  {
+    uiLayout *col = uiLayoutColumn(layout, false);
+    uiLayoutSetPropSep(col, true);
+    uiItemR(col, &imaptr, "source", 0, NULL, ICON_NONE);
+  }
+
+  /* Filepath */
+  const bool is_packed = BKE_image_has_packedfile(ima);
+  const bool no_filepath = is_packed && !BKE_image_has_filepath(ima);
+
+  if ((ima->source != IMA_SRC_GENERATED) && !no_filepath) {
+    uiItemS(layout);
+
+    uiLayout *row = uiLayoutRow(layout, true);
+    if (is_packed) {
+      uiItemO(row, "", ICON_PACKAGE, "image.unpack");
     }
     else {
-      /* Disable editing if image was modified, to avoid losing changes. */
-      const bool is_dirty = BKE_image_is_dirty(ima);
-      if (is_dirty) {
-        row = uiLayoutRow(layout, true);
-        uiItemO(row, IFACE_("Save"), ICON_NONE, "image.save");
-        uiItemO(row, IFACE_("Discard Changes"), ICON_NONE, "image.reload");
-        uiItemS(layout);
-      }
+      uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
+    }
 
-      layout = uiLayoutColumn(layout, false);
-      uiLayoutSetEnabled(layout, !is_dirty);
+    row = uiLayoutRow(row, true);
+    uiLayoutSetEnabled(row, is_packed == false);
+    uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
+    uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
+  }
 
-      /* Image source */
-      uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);
+  /* Image layers and Info */
+  if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
+    uiItemS(layout);
 
-      /* Filepath */
-      const bool is_packed = BKE_image_has_packedfile(ima);
-      const bool no_filepath = is_packed && !BKE_image_has_filepath(ima);
+    const float dpi_fac = UI_DPI_FAC;
+    uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
+  }
+  else if (ima->source == IMA_SRC_GENERATED) {
+    uiItemS(layout);
 
-      if ((ima->source != IMA_SRC_GENERATED) && !no_filepath) {
-        row = uiLayoutRow(layout, true);
-        if (is_packed) {
-          uiItemO(row, "", ICON_PACKAGE, "image.unpack");
-        }
-        else {
-          uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
-        }
+    /* Generated */
+    uiLayout *col = uiLayoutColumn(layout, false);
+    uiLayoutSetPropSep(col, true);
 
-        row = uiLayoutRow(row, true);
-        uiLayoutSetEnabled(row, is_packed == false);
-        uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
-        uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
-      }
+    uiLayout *sub = uiLayoutColumn(col, true);
+    uiItemR(sub, &imaptr, "generated_width", 0, "X", ICON_NONE);
+    uiItemR(sub, &imaptr, "generated_height", 0, "Y", ICON_NONE);
 
-      /* Image layers and Info */
-      if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
-        const float dpi_fac = UI_DPI_FAC;
-        uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
-      }
-      else if (ima->source != IMA_SRC_GENERATED) {
-        if (compact == 0) {
-          uiTemplateImageInfo(layout, C, ima, iuser);
-        }
-      }
+    uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
 
-      uiItemS(layout);
+    uiItemS(col);
 
-      col = uiLayoutColumn(layout, false);
-      uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
-      uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
+    uiItemR(col, &imaptr, "generated_type", UI_ITEM_R_EXPAND, IFACE_("Type"), ICON_NONE);
+    if (ima->gen_type == IMA_GENTYPE_BLANK) {
+      uiItemR(col, &imaptr, "generated_color", 0, NULL, ICON_NONE);
+    }
+  }
+  else if (compact == 0) {
+    uiTemplateImageInfo(layout, C, ima, iuser);
+  }
 
-      uiItemS(layout);
+  if (BKE_image_is_animated(ima)) {
+    /* Animation */
+    uiItemS(layout);
 
-      if (ima->source != IMA_SRC_GENERATED) {
-        if (compact == 0) { /* background image view doesn't need these */
-          ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
-          bool has_alpha = true;
-
-          if (ibuf) {
-            int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
-            char valid_channels = BKE_imtype_valid_channels(imtype, false);
-
-            has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
-
-            BKE_image_release_ibuf(ima, ibuf, NULL);
-          }
-
-          if (multiview) {
-            if ((scene->r.scemode & R_MULTIVIEW) != 0) {
-              uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
-
-              if (RNA_boolean_get(&imaptr, "use_multiview")) {
-                uiTemplateImageViews(layout, &imaptr);
-              }
-            }
-          }
-
-          if (has_alpha) {
-            col = uiLayoutColumn(layout, false);
-            uiItemR(col, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
-
-            /* Alpha mode has no effect for non-color data. */
-            bool is_data = IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name);
-            uiLayoutSetActive(col, !is_data);
-          }
-
-          if (ima->source == IMA_SRC_MOVIE) {
-            col = uiLayoutColumn(layout, false);
-            uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
-          }
-        }
-      }
+    uiLayout *col = uiLayoutColumn(layout, true);
+    uiLayoutSetPropSep(col, true);
 
-      if (BKE_image_is_animated(ima)) {
-        uiItemS(layout);
+    uiLayout *sub = uiLayoutColumn(col, true);
+    uiLayout *row = uiLayoutRow(sub, true);
+    uiItemR(row, userptr, "frame_duration", 0, IFACE_("Frames"), ICON_NONE);
+    uiItemO(row, "", ICON_FILE_REFRESH, "IMAGE_OT_match_movie_length");
 
-        split = uiLayoutSplit(layout, 0.0f, false);
+    uiItemR(sub, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
+    uiItemR(sub, userptr, "frame_offset", 0, NULL, ICON_NONE);
 
-        col = uiLayoutColumn(split, false);
+    uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
+    uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
 
-        BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr);
-        uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
-        uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
-        uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
+    if (ima->source == IMA_SRC_MOVIE && compact == 0) {
+      uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
+    }
+  }
+
+  /* Multiview */
+  if (multiview && compact == 0) {
+    if ((scene->r.scemode & R_MULTIVIEW) != 0) {
+      uiItemS(layout);
 
-        col = uiLayoutColumn(split, false);
-        uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length");
-        uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
-        uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
+      uiLayout *col = uiLayoutColumn(layout, false);
+      uiLayoutSetPropSep(col, true);
+      uiItemR(col, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
+
+      if (RNA_boolean_get(&imaptr, "use_multiview")) {
+        uiTemplateImageViews(layout, &imaptr);
       }
-      else if (ima->source == IMA_SRC_GENERATED) {
-        split = uiLayoutSplit(layout, 0.0f, false);
+    }
+  }
 
-        col = uiLayoutColumn(split, true);
-        uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
-        uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
+  /* Colorspace and alpha */
+  {
+    uiItemS(layout);
 
-        uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
+    uiLayout *col = uiLayoutColumn(layout, false);
+    uiLayoutSetPropSep(col, true);
+    uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
 
-        uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+    if (compact == 0) {
+      if (ima->source != IMA_SRC_GENERATED) {
+        if (image_has_alpha(ima, iuser)) {
+          uiLayout *sub = uiLayoutColumn(col, false);
+          uiItemR(sub, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
 
-        if (ima->gen_type == IMA_GENTYPE_BLANK) {
-          uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE);
+          bool is_data = IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name);
+          uiLayoutSetActive(sub, !is_data);
         }
       }
-    }
 
-    UI_block_funcN_set(block, NULL, NULL, NULL);
+      uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
+    }
   }
 
-  MEM_freeN(cb);
+  UI_block_funcN_set(block, NULL, NULL, NULL);
 }
 
 void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management)
@@ -1260,21 +1198,83 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser
 
 void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
 {
-  Scene *scene = CTX_data_scene(C);
-  ImBuf *ibuf;
-  char str[MAX_IMAGE_INFO_LEN];
+  if (ima == NULL || iuser == NULL) {
+    return;
+  }
+
+  /* Acquire image buffer. */
   void *lock;
+  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
 
-  if (!ima || !iuser) {
-    return;
+  uiLayout *col = uiLayoutColumn(layout, true);
+
+  if (ibuf == NULL) {
+    uiItemL(col, IFACE_("Can't Load Image"), ICON_NONE);
   }
+  else {
+    char str[MAX_IMAGE_INFO_LEN] = {0};
+    const int len = MAX_IMAGE_INFO_LEN;
+    int ofs = 0;
 
-  ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
+    ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d x %d, "), ibuf->x, ibuf->y);
+
+    if (ibuf->rect_float) {
+      if (ibuf->channels != 4) {
+        ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels);
+      }
+      else if (ibuf->planes == R_IMF_PLANES_RGBA) {
+        ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs);
+      }
+      else {
+        ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs);
+      }
+    }
+    else {
+      if (ibuf->planes == R_IMF_PLANES_RGBA) {
+        ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs);
+      }
+      else {
+        ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs);
+      }
+    }
+    if (ibuf->zbuf || ibuf->zbuf_float) {
+      ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
+    }
+
+    uiItemL(col, str, ICON_NONE);
+  }
+
+  /* Frame number, even if we can't load the image. */
+  if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+    /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
+    Scene *scene = CTX_data_scene(C);
+    const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL);
+    char str[MAX_IMAGE_INFO_LEN];
+    int duration = 0;
+
+    if (ima->source == IMA_SRC_MOVIE && BKE_image_has_anim(ima)) {
+      duration = IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN);
+    }
+
+    if (duration > 0) {
+      /* Movie duration */
+      BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d / %d"), framenr, duration);
+    }
+    else if (ima->source == IMA_SRC_SEQUENCE && ibuf) {
+      /* Image sequence frame number + filename */
+      const char *filename = BLI_last_slash(ibuf->name);
+      filename = (filename == NULL) ? ibuf->name : filename + 1;
+      BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d: %s"), framenr, filename);
+    }
+    else {
+      /* Frame number */
+      BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d"), framenr);
+    }
+
+    uiItemL(col, str, ICON_NONE);
+  }
 
-  BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
-  image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
   BKE_image_release_ibuf(ima, ibuf, lock);
-  uiItemL(layout, str, ICON_NONE);
 }
 
 #undef MAX_IMAGE_INFO_LEN