diff options
author | raa <roaoao@gmail.com> | 2017-01-26 20:22:20 +0300 |
---|---|---|
committer | raa <roaoao@gmail.com> | 2017-01-26 20:33:37 +0300 |
commit | 371960484a38fc64e0a2635170a41a0d8ab2f6bd (patch) | |
tree | c5674bfb1f2147e2f32481c27b18358998c78dfb /development_icon_get.py | |
parent | 0a9f786d72cd10e145d5bcff541a44acbb5869c2 (diff) |
Replace Icons addon with Icon Viewer - T50367
Diffstat (limited to 'development_icon_get.py')
-rw-r--r-- | development_icon_get.py | 617 |
1 files changed, 428 insertions, 189 deletions
diff --git a/development_icon_get.py b/development_icon_get.py index 24393554..bebf0983 100644 --- a/development_icon_get.py +++ b/development_icon_get.py @@ -20,224 +20,463 @@ bl_info = { - "name": "Icons", - "author": "Crouch, N.tox, PKHG, Campbell Barton, Dany Lebel", - "version": (1, 5, 2), - "blender": (2, 57, 0), - "location": "Text Editor > Properties or " "Console > Console Menu", - "warning": "", - "description": "Click an icon to display its name and " - "copy it to the clipboard", - "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/" - "Py/Scripts/System/Display_All_Icons", - "category": "Development", + "name": "Icon Viewer", + "description": "Click an icon to copy its name to the clipboard", + "author": "roaoao", + "version": (1, 3, 1), + "blender": (2, 75, 0), + "location": "Spacebar > Icon Viewer, Text Editor > Properties", + "wiki_url": ( + "https://wiki.blender.org/index.php/User:Raa/Addons/Icon_Viewer"), + "tracker_url": "http://blenderartists.org/forum/showthread.php?392912", + "category": "Development" } - import bpy +import math + +DPI = 72 +POPUP_PADDING = 10 +PANEL_PADDING = 44 +WIN_PADDING = 32 +ICON_SIZE = 20 +HISTORY_SIZE = 100 +HISTORY = [] + + +def ui_scale(): + ret = bpy.context.user_preferences.system.dpi / DPI + if bpy.context.user_preferences.system.virtual_pixel_mode == 'DOUBLE': + ret *= 2 + return ret + + +def prefs(): + return bpy.context.user_preferences.addons[__name__].preferences + + +class Icons: + def __init__(self): + self._filtered_icons = None + self._filter = "" + self.filter = "" + self.selected_icon = "" + + @property + def filter(self): + return self._filter + + @filter.setter + def filter(self, value): + if self._filter == value: + return + + self._filter = value + self.update() + + @property + def filtered_icons(self): + if self._filtered_icons is None: + self._filtered_icons = [] + icon_filter = self._filter.upper() + self.filtered_icons.clear() + pr = prefs() + + icons = bpy.types.UILayout.bl_rna.functions[ + "prop"].parameters["icon"].enum_items.keys() + for icon in icons: + if icon == 'NONE' or \ + icon_filter and icon_filter not in icon or \ + not pr.show_brush_icons and "BRUSH_" in icon and \ + icon != 'BRUSH_DATA' or \ + not pr.show_matcap_icons and "MATCAP_" in icon or \ + not pr.show_colorset_icons and "COLORSET_" in icon: + continue + self._filtered_icons.append(icon) + + return self._filtered_icons + + @property + def num_icons(self): + return len(self.filtered_icons) + + def update(self): + if self._filtered_icons is not None: + self._filtered_icons.clear() + self._filtered_icons = None + + def draw(self, layout, num_cols=0, icons=None, select=True): + if icons: + filtered_icons = reversed(icons) + else: + filtered_icons = self.filtered_icons + + column = layout.column(True) + row = column.row(True) + row.alignment = 'CENTER' + + op_name = IV_OT_icon_select.bl_idname if select else \ + IV_OT_icon_copy.bl_idname + + col_idx = 0 + for i, icon in enumerate(filtered_icons): + p = row.operator( + op_name, "", + icon=icon, emboss=select and icon == self.selected_icon) + p.icon = icon + + col_idx += 1 + if col_idx > num_cols - 1: + if icons: + break + col_idx = 0 + if i < len(filtered_icons) - 1: + row = column.row(True) + row.alignment = 'CENTER' + + if col_idx != 0 and not icons and i >= num_cols: + sub = row.row(True) + sub.scale_x = num_cols - col_idx + sub.label("", icon='BLANK1') + + if not filtered_icons: + row.label("No icons were found") + + +class IV_Preferences(bpy.types.AddonPreferences): + bl_idname = __name__ + + panel_icons = Icons() + popup_icons = Icons() + + def update_icons(self, context): + self.panel_icons.update() + self.popup_icons.update() + + def set_panel_filter(self, value): + self.panel_icons.filter = value + + panel_filter = bpy.props.StringProperty( + description="Filter", + default="", + get=lambda s: s.panel_icons.filter, + set=set_panel_filter, + options={'TEXTEDIT_UPDATE'}) + show_panel_icons = bpy.props.BoolProperty( + name="Show Icons", + description="Show icons", default=True) + show_history = bpy.props.BoolProperty( + name="Show History", + description="Show history", default=True) + show_brush_icons = bpy.props.BoolProperty( + name="Show Brush Icons", + description="Show brush icons", default=True, + update=update_icons) + show_matcap_icons = bpy.props.BoolProperty( + name="Show Matcap Icons", + description="Show matcap icons", default=True, + update=update_icons) + show_colorset_icons = bpy.props.BoolProperty( + name="Show Colorset Icons", + description="Show colorset icons", default=True, + update=update_icons) + copy_on_select = bpy.props.BoolProperty( + name="Copy Icon On Click", + description="Copy icon on click", default=True) + close_on_select = bpy.props.BoolProperty( + name="Close Popup On Click", + description=( + "Close the popup on click.\n" + "Not supported by some windows (User Preferences, Render)." + ), + default=False) + auto_focus_filter = bpy.props.BoolProperty( + name="Auto Focus Input Field", + description="Auto focus input field", default=True) + + def draw(self, context): + layout = self.layout + row = layout.row() + row.scale_y = 1.5 + row.operator(IV_OT_icons_show.bl_idname) + + row = layout.row() + + col = row.column(True) + col.label("Icons:") + col.prop(self, "show_matcap_icons") + col.prop(self, "show_brush_icons") + col.prop(self, "show_colorset_icons") + col.separator() + col.prop(self, "show_history") + + col = row.column(True) + col.label("Popup:") + col.prop(self, "auto_focus_filter") + col.prop(self, "copy_on_select") + if self.copy_on_select: + col.prop(self, "close_on_select") + + col = row.column(True) + col.label("Panel:") + col.prop(self, "show_panel_icons") + + +class IV_PT_icons(bpy.types.Panel): + bl_space_type = "TEXT_EDITOR" + bl_region_type = "UI" + bl_label = "Icon Viewer" + + @staticmethod + def tag_redraw(): + wm = bpy.context.window_manager + if not wm: + return + for w in wm.windows: + for a in w.screen.areas: + if a.type == 'TEXT_EDITOR': + for r in a.regions: + if r.type == 'UI': + r.tag_redraw() -def create_icon_list_all(): - icons = bpy.types.UILayout.bl_rna.functions['prop'].parameters['icon'].\ - enum_items.keys() + def draw(self, context): + pr = prefs() + row = self.layout.row(True) + if pr.show_panel_icons: + row.prop(pr, "panel_filter", "", icon='VIEWZOOM') + else: + row.operator(IV_OT_icons_show.bl_idname) + row.operator(IV_OT_panel_menu_call.bl_idname, "", icon='COLLAPSEMENU') + + _, y0 = context.region.view2d.region_to_view(0, 0) + _, y1 = context.region.view2d.region_to_view(0, 10) + region_scale = 10 / abs(y0 - y1) + + num_cols = max( + 1, + (context.region.width - PANEL_PADDING) // + math.ceil(ui_scale() * region_scale * ICON_SIZE)) - icons.remove("NONE") + col = None + if HISTORY and pr.show_history: + col = self.layout.column(True) + pr.panel_icons.draw(col.box(), num_cols, HISTORY, False) - return icons + if pr.show_panel_icons: + col = col or self.layout.column(True) + pr.panel_icons.draw(col.box(), num_cols, select=False) -def create_icon_list(): - icons = create_icon_list_all() - search = bpy.context.scene.icon_props.search.lower() +class IV_HT_icons(bpy.types.Header): + bl_space_type = 'CONSOLE' + + def draw(self, context): + layout = self.layout + layout.separator() + layout.operator(IV_OT_icons_show.bl_idname) + - if search == "": - pass - else: - icons = [key for key in icons if search in key.lower()] +class IV_OT_panel_menu_call(bpy.types.Operator): + bl_idname = "iv.panel_menu_call" + bl_label = "" + bl_description = "Menu" + bl_options = {'INTERNAL'} - return icons + def menu(self, menu, context): + pr = prefs() + layout = menu.layout + layout.prop(pr, "show_panel_icons") + layout.prop(pr, "show_history") + if not pr.show_panel_icons: + return + + layout.separator() + layout.prop(pr, "show_matcap_icons") + layout.prop(pr, "show_brush_icons") + layout.prop(pr, "show_colorset_icons") + + def execute(self, context): + context.window_manager.popup_menu(self.menu, "Icon Viewer") + return {'FINISHED'} + + +class IV_OT_icon_copy(bpy.types.Operator): + bl_idname = "iv.icon_copy" + bl_label = "" + bl_description = "Copy the icon" + bl_options = {'INTERNAL'} -class WM_OT_icon_info(bpy.types.Operator): - bl_idname = "wm.icon_info" - bl_label = "Icon Info" - bl_description = "Click to copy this icon name to the clipboard" icon = bpy.props.StringProperty() - icon_scroll = bpy.props.IntProperty() - def invoke(self, context, event): - bpy.data.window_managers['WinMan'].clipboard = self.icon - self.report({'INFO'}, "Icon ID: %s" % self.icon) + def execute(self, context): + context.window_manager.clipboard = self.icon + self.report({'INFO'}, self.icon) + + if prefs().show_history: + if self.icon in HISTORY: + HISTORY.remove(self.icon) + if len(HISTORY) >= HISTORY_SIZE: + HISTORY.pop(0) + HISTORY.append(self.icon) return {'FINISHED'} -class OBJECT_PT_icons(bpy.types.Panel): - bl_space_type = "TEXT_EDITOR" - bl_region_type = "UI" - bl_label = "All icons" +class IV_OT_icon_select(bpy.types.Operator): + bl_idname = "iv.icon_select" + bl_label = "" + bl_description = "Select the icon" + bl_options = {'INTERNAL'} - def __init__(self): - self.amount = 10 - self.icon_list = create_icon_list() + icon = bpy.props.StringProperty() - def draw(self, context): - props = context.scene.icon_props - # polling for updates - if props.search != CONSOLE_HT_icons._search_old: - self.icon_list = create_icon_list() - # adjusting max value of scroller -# IconProps.scroll = bpy.props.IntProperty(default=1, min=1, -# max=max(1, len(self.icon_list) - self.amount + 1), -# description="Drag to scroll icons") - - box = self.layout.box() - # scroll view - if not props.expand: - # expand button - toprow = box.row() - toprow.prop(props, "expand", icon="TRIA_RIGHT", icon_only=True, - text="", emboss=False) # icon_only broken? - # search buttons - row = toprow.row(align=True) - row.prop(props, "search", icon="VIEWZOOM", text="") - # scroll button - row = toprow.row() - row.active = props.bl_rna.scroll[1]['max'] > 1 - row.prop(props, "scroll") - - # icons - row = box.row(align=True) - if len(self.icon_list) == 0: - row.label("No icons found") - else: - for icon in self.icon_list[props.scroll - 1: - props.scroll - 1 + self.amount]: - row.operator("wm.icon_info", text=" ", icon=icon, - emboss=False).icon = icon - if len(self.icon_list) < self.amount: - for i in range(self.amount - len(self.icon_list) \ - % self.amount): - row.label("") - - # expanded view + def execute(self, context): + pr = prefs() + pr.popup_icons.selected_icon = self.icon + if pr.copy_on_select: + context.window_manager.clipboard = self.icon + self.report({'INFO'}, self.icon) + + if pr.close_on_select and IV_OT_icons_show.instance: + IV_OT_icons_show.instance.close() + + if pr.show_history: + if self.icon in HISTORY: + HISTORY.remove(self.icon) + if len(HISTORY) >= HISTORY_SIZE: + HISTORY.pop(0) + HISTORY.append(self.icon) + return {'FINISHED'} + + +class IV_OT_icons_show(bpy.types.Operator): + bl_idname = "iv.icons_show" + bl_label = "Icon Viewer" + bl_description = "Icon viewer" + bl_property = "filter_auto_focus" + + instance = None + + def set_filter(self, value): + prefs().popup_icons.filter = value + + def set_selected_icon(self, value): + if IV_OT_icons_show.instance: + IV_OT_icons_show.instance.auto_focusable = False + + filter_auto_focus = bpy.props.StringProperty( + description="Filter", + get=lambda s: prefs().popup_icons.filter, + set=set_filter, + options={'TEXTEDIT_UPDATE', 'SKIP_SAVE'}) + filter = bpy.props.StringProperty( + description="Filter", + get=lambda s: prefs().popup_icons.filter, + set=set_filter, + options={'TEXTEDIT_UPDATE'}) + selected_icon = bpy.props.StringProperty( + description="Selected Icon", + get=lambda s: prefs().popup_icons.selected_icon, + set=set_selected_icon) + + def get_num_cols(self, num_icons): + return round(1.3 * math.sqrt(num_icons)) + + def draw_header(self, layout): + pr = prefs() + header = layout.box() + header = header.split(0.75) if self.selected_icon else header.row() + row = header.row(True) + row.prop(pr, "show_matcap_icons", "", icon='SMOOTH') + row.prop(pr, "show_brush_icons", "", icon='BRUSH_DATA') + row.prop(pr, "show_colorset_icons", "", icon='COLOR') + row.separator() + + row.prop( + pr, "copy_on_select", "", + icon='BORDER_RECT', toggle=True) + if pr.copy_on_select: + sub = row.row(True) + if bpy.context.window.screen.name == "temp": + sub.alert = True + sub.prop( + pr, "close_on_select", "", + icon='RESTRICT_SELECT_OFF', toggle=True) + row.prop( + pr, "auto_focus_filter", "", + icon='OUTLINER_DATA_FONT', toggle=True) + row.separator() + + if self.auto_focusable and pr.auto_focus_filter: + row.prop(self, "filter_auto_focus", "", icon='VIEWZOOM') else: - # expand button - toprow = box.row() - toprow.prop(props, "expand", icon="TRIA_DOWN", icon_only=True, - text="", emboss=False) - # search buttons - row = toprow.row(align=True) - row.prop(props, "search", icon="VIEWZOOM", text="") - # scroll button - row = toprow.row() - row.active = False - row.prop(props, "scroll") - - # icons - col = box.column(align=True) - if len(self.icon_list) == 0: - col.label("No icons found") - else: - for i, icon in enumerate(self.icon_list): - if i % self.amount == 0: - row = col.row(align=True) - row.operator("wm.icon_info", text=" ", icon=icon, - emboss=False).icon = icon - for i in range(self.amount - len(self.icon_list) \ - % self.amount): - row.label("") - - -class CONSOLE_HT_icons(bpy.types.Header): - bl_space_type = 'CONSOLE' - _search_old = "" + row.prop(self, "filter", "", icon='VIEWZOOM') - def __init__(self): - self.amount = 10 - self.icon_list = create_icon_list() + if self.selected_icon: + row = header.row() + row.prop(self, "selected_icon", "", icon=self.selected_icon) def draw(self, context): - props = context.scene.icon_props - # polling for updates - if props.search != self.__class__._search_old: - self.__class__._search_old = props.search - self.icon_list = create_icon_list() - # adjusting max value of scroller -# IconProps.scroll = bpy.props.IntProperty(default=1, min=1, -# max=max(1, len(self.icon_list) - self.amount + 1), -# description="Drag to scroll icons") - - # scroll view - if props.console: - layout = self.layout - layout.separator() - # search buttons - row = layout.row() - row.prop(props, "search", icon="VIEWZOOM") - # scroll button - row = layout.row() - row.active = props.bl_rna.scroll[1]['max'] > 1 - row.prop(props, "scroll") - - # icons - row = layout.row(align=True) - if len(self.icon_list) == 0: - row.label("No icons found") - else: - for icon in self.icon_list[props.scroll - 1: - props.scroll - 1 + self.amount]: - row.operator("wm.icon_info", text="", icon=icon, - emboss=False).icon = icon - - -def menu_func(self, context): - self.layout.prop(bpy.context.scene.icon_props, 'console') + pr = prefs() + col = self.layout + self.draw_header(col) + subcol = col.column(True) + box = subcol.box() -def register(): - global IconProps - - icons_total = len(create_icon_list_all()) - icons_per_row = 10 - - class IconProps(bpy.types.PropertyGroup): - """ - Fake module like class - bpy.context.scene.icon_props - """ - console = bpy.props.BoolProperty(name='Show System Icons', - description='Display the Icons in the console header', - default=False) - expand = bpy.props.BoolProperty(name="Expand", - description="Expand, to display all icons at once", - default=False) - search = bpy.props.StringProperty(name="Search", - description="Search for icons by name", - default="") - scroll = bpy.props.IntProperty(name="Scroll", - description="Drag to scroll icons", - default=1, min=1, max=max(1, icons_total - icons_per_row + 1)) + num_cols = min( + self.get_num_cols(len(pr.popup_icons.filtered_icons)), + int((self.width - POPUP_PADDING) / (ui_scale() * ICON_SIZE))) - bpy.utils.register_module(__name__) - bpy.types.Scene.icon_props = bpy.props.PointerProperty(type=IconProps) - bpy.types.CONSOLE_MT_console.append(menu_func) + pr.popup_icons.draw(box, num_cols) + if HISTORY and pr.show_history: + box = subcol.box() + pr.popup_icons.draw(box, num_cols, HISTORY) -def unregister(): - if bpy.context.scene.get('icon_props') != None: - del bpy.context.scene['icon_props'] - try: - del bpy.types.Scene.icon_props - bpy.types.CONSOLE_MT_console.remove(menu_func) - except: - pass - if __name__ == "__main__": - # unregistering is only done automatically when run as addon - bpy.utils.unregister_class(OBJECT_PT_icons) - bpy.utils.unregister_class(CONSOLE_HT_icons) + def close(self): + bpy.context.window.screen = bpy.context.window.screen - bpy.utils.unregister_module(__name__) + def check(self, context): + return True + + def cancel(self, context): + IV_OT_icons_show.instance = None + IV_PT_icons.tag_redraw() + def execute(self, context): + if not IV_OT_icons_show.instance: + return {'CANCELLED'} + IV_OT_icons_show.instance = None -if __name__ == "__main__": - register() + pr = prefs() + if self.selected_icon and not pr.copy_on_select: + context.window_manager.clipboard = self.selected_icon + self.report({'INFO'}, self.selected_icon) + pr.popup_icons.selected_icon = "" + + IV_PT_icons.tag_redraw() + return {'FINISHED'} + + def invoke(self, context, event): + pr = prefs() + pr.popup_icons.selected_icon = "" + pr.popup_icons.filter = "" + IV_OT_icons_show.instance = self + self.auto_focusable = True + + num_cols = self.get_num_cols(len(pr.popup_icons.filtered_icons)) + self.width = min( + ui_scale() * (num_cols * ICON_SIZE + POPUP_PADDING), + context.window.width - WIN_PADDING) + + return context.window_manager.invoke_props_dialog(self, self.width) + + +def register(): + bpy.utils.register_module(__name__) + + +def unregister(): + bpy.utils.unregister_module(__name__) |