Operator icon

Hi all!
I’m writing a simple addon and I need a menu in the 3d view to assign one among four custom materials. The menu opens when you press E (in object mode). I came up with this:
[ATTACH=CONFIG]230567[/ATTACH]

I created an operator (ObjectAssignColour) with an integer property (index) ranging from 1 to 4. It assign the colour number index to the active object. Then I created a menu with the method

    def draw(self, context):
        layout = self.layout
        split = layout.split()
        col = split.column()
        for n in (1, 2, 3, 4):
            col.label(icon_value=layout.icon(bpy.data.materials[colour_name % n]))
        col = split.column()
        for t, n in zip(("Red", "Green", "Cyan", "Violet"), (1, 2, 3, 4)):
            col.operator(ObjectAssignColour.bl_idname, text=t).index = n

The main issue is the bad spacing between the icons in the left column and the operators in the right one (I would like to have them closer). The reason why I had to do this is because label() supports the icon_value keyword which allows me to reference the icon of the material. On the other hand, operator() unfortunately does not support it.

Is there a way to use custom icons with operators?
Or is there a way to control the spacing to fit the icons and the operators closer?
Or is there a way to put the materials directly inside the menu (instead of operators) and have the menu assign the selected one when it closes?

Thank you in advance

Attachments


I even tried a template_list in a custom UIList, but it appears to be impossible to have material icons in a menu next to an operator. There are always like 2 columns with even width.

The best i got is:

import bpy



def main(context):
    for ob in context.scene.objects:
        print(ob)




class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"
    bl_options = {'REGISTER', 'UNDO'}
   


    @classmethod
    def poll(cls, context):
        return context.active_object is not None


    def execute(self, context):
        main(context)
        return {'FINISHED'}




    def invoke(self, context, event):
        context.window_manager.invoke_props_popup(self, event)
        return {'FINISHED'}
    
    def draw(self, context):
        layout = self.layout
        
        for i, mat in enumerate(bpy.data.materials):
            row = layout.row()
            row.label(icon_value=layout.icon(mat))
            #p=row.operator("wm.context_set_enum")
            #p.data_path = "scene.coll"
            #p.value=str(i)
            row.operator("object.select_all")
            
def cb(self,context):
    return [tuple((str(i), mat.name, mat.name)) for i, mat in enumerate(bpy.data.materials)]
        


def register():
    bpy.utils.register_class(SimpleOperator)
    bpy.types.Scene.coll = bpy.props.EnumProperty(items=cb)




def unregister():
    bpy.utils.unregister_class(SimpleOperator)


    del bpy.types.Scene.coll


if __name__ == "__main__":
    register()

But that popup doesn’t close when it should and blender crashes soon. The only proper way would be if the devs added icon_value to layout.operator()