space_text.py 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. # ##### BEGIN GPL LICENSE BLOCK #####
  2. #
  3. # This program is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU General Public License
  5. # as published by the Free Software Foundation; either version 2
  6. # of the License, or (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software Foundation,
  15. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. # ##### END GPL LICENSE BLOCK #####
  18. # <pep8-80 compliant>
  19. import bpy
  20. from bpy.types import Header, Menu, Panel
  21. from bpy.app.translations import pgettext_iface as iface_
  22. class TEXT_HT_header(Header):
  23. bl_space_type = 'TEXT_EDITOR'
  24. def draw(self, context):
  25. layout = self.layout
  26. st = context.space_data
  27. text = st.text
  28. layout.template_header()
  29. TEXT_MT_editor_menus.draw_collapsible(context, layout)
  30. if text and text.is_modified:
  31. row = layout.row(align=True)
  32. row.alert = True
  33. row.operator("text.resolve_conflict", text="", icon='HELP')
  34. layout.separator_spacer()
  35. row = layout.row(align=True)
  36. row.template_ID(st, "text", new="text.new", unlink="text.unlink", open="text.open")
  37. layout.separator_spacer()
  38. row = layout.row(align=True)
  39. row.prop(st, "show_line_numbers", text="")
  40. row.prop(st, "show_word_wrap", text="")
  41. row.prop(st, "show_syntax_highlight", text="")
  42. if text:
  43. is_osl = text.name.endswith((".osl", ".osl"))
  44. row = layout.row()
  45. if is_osl:
  46. row = layout.row()
  47. row.operator("node.shader_script_update")
  48. else:
  49. row = layout.row()
  50. row.active = text.name.endswith(".py")
  51. row.prop(text, "use_module")
  52. row = layout.row()
  53. row.operator("text.run_script")
  54. class TEXT_HT_footer(Header):
  55. bl_space_type = 'TEXT_EDITOR'
  56. bl_region_type = 'FOOTER'
  57. def draw(self, context):
  58. layout = self.layout
  59. st = context.space_data
  60. text = st.text
  61. if text:
  62. row = layout.row()
  63. if text.filepath:
  64. if text.is_dirty:
  65. row.label(
  66. text=iface_(f"File: *{text.filepath:s} (unsaved)"),
  67. translate=False,
  68. )
  69. else:
  70. row.label(
  71. text=iface_(f"File: {text.filepath:s}"),
  72. translate=False,
  73. )
  74. else:
  75. row.label(
  76. text="Text: External"
  77. if text.library
  78. else "Text: Internal",
  79. )
  80. class TEXT_MT_editor_menus(Menu):
  81. bl_idname = "TEXT_MT_editor_menus"
  82. bl_label = ""
  83. def draw(self, context):
  84. layout = self.layout
  85. st = context.space_data
  86. text = st.text
  87. layout.menu("TEXT_MT_view")
  88. layout.menu("TEXT_MT_text")
  89. if text:
  90. layout.menu("TEXT_MT_edit")
  91. layout.menu("TEXT_MT_format")
  92. layout.menu("TEXT_MT_templates")
  93. class TEXT_PT_properties(Panel):
  94. bl_space_type = 'TEXT_EDITOR'
  95. bl_region_type = 'UI'
  96. bl_category = "Text"
  97. bl_label = "Properties"
  98. def draw(self, context):
  99. layout = self.layout
  100. st = context.space_data
  101. flow = layout.column_flow()
  102. flow.prop(st, "show_line_numbers")
  103. flow.prop(st, "show_word_wrap")
  104. flow.prop(st, "show_syntax_highlight")
  105. flow.prop(st, "show_line_highlight")
  106. flow.prop(st, "use_live_edit")
  107. flow = layout.column_flow()
  108. flow.prop(st, "font_size")
  109. flow.prop(st, "tab_width")
  110. text = st.text
  111. if text:
  112. flow.prop(text, "use_tabs_as_spaces")
  113. flow.prop(st, "show_margin")
  114. col = flow.column()
  115. col.active = st.show_margin
  116. col.prop(st, "margin_column")
  117. class TEXT_PT_find(Panel):
  118. bl_space_type = 'TEXT_EDITOR'
  119. bl_region_type = 'UI'
  120. bl_category = "Text"
  121. bl_label = "Find"
  122. def draw(self, context):
  123. layout = self.layout
  124. st = context.space_data
  125. # find
  126. col = layout.column(align=True)
  127. row = col.row(align=True)
  128. row.prop(st, "find_text", text="")
  129. row.operator("text.find_set_selected", text="", icon='TEXT')
  130. col.operator("text.find")
  131. # replace
  132. col = layout.column(align=True)
  133. row = col.row(align=True)
  134. row.prop(st, "replace_text", text="")
  135. row.operator("text.replace_set_selected", text="", icon='TEXT')
  136. col.operator("text.replace")
  137. # settings
  138. layout.prop(st, "use_match_case")
  139. row = layout.row(align=True)
  140. row.prop(st, "use_find_wrap", text="Wrap")
  141. row.prop(st, "use_find_all", text="All")
  142. class TEXT_MT_view(Menu):
  143. bl_label = "View"
  144. def draw(self, context):
  145. layout = self.layout
  146. st = context.space_data
  147. layout.prop(st, "show_region_ui")
  148. layout.separator()
  149. layout.operator("text.move",
  150. text="Top of File",
  151. ).type = 'FILE_TOP'
  152. layout.operator("text.move",
  153. text="Bottom of File",
  154. ).type = 'FILE_BOTTOM'
  155. layout.separator()
  156. layout.menu("INFO_MT_area")
  157. class TEXT_MT_text(Menu):
  158. bl_label = "Text"
  159. def draw(self, context):
  160. layout = self.layout
  161. st = context.space_data
  162. text = st.text
  163. layout.operator("text.new", text="New")
  164. layout.operator("text.open", text="Open...", icon='FILE_FOLDER')
  165. if text:
  166. layout.separator()
  167. layout.operator("text.reload")
  168. layout.separator()
  169. layout.operator("text.save", icon='FILE_TICK')
  170. layout.operator("text.save_as", text="Save As...")
  171. if text.filepath:
  172. layout.operator("text.make_internal")
  173. layout.separator()
  174. layout.operator("text.run_script")
  175. class TEXT_MT_templates_py(Menu):
  176. bl_label = "Python"
  177. def draw(self, _context):
  178. self.path_menu(
  179. bpy.utils.script_paths("templates_py"),
  180. "text.open",
  181. props_default={"internal": True},
  182. filter_ext=lambda ext: (ext.lower() == ".py")
  183. )
  184. class TEXT_MT_templates_osl(Menu):
  185. bl_label = "Open Shading Language"
  186. def draw(self, _context):
  187. self.path_menu(
  188. bpy.utils.script_paths("templates_osl"),
  189. "text.open",
  190. props_default={"internal": True},
  191. filter_ext=lambda ext: (ext.lower() == ".osl")
  192. )
  193. class TEXT_MT_templates(Menu):
  194. bl_label = "Templates"
  195. def draw(self, _context):
  196. layout = self.layout
  197. layout.menu("TEXT_MT_templates_py")
  198. layout.menu("TEXT_MT_templates_osl")
  199. class TEXT_MT_edit_select(Menu):
  200. bl_label = "Select"
  201. def draw(self, _context):
  202. layout = self.layout
  203. layout.operator("text.select_all")
  204. layout.operator("text.select_line")
  205. class TEXT_MT_format(Menu):
  206. bl_label = "Format"
  207. def draw(self, _context):
  208. layout = self.layout
  209. layout.operator("text.indent")
  210. layout.operator("text.unindent")
  211. layout.separator()
  212. layout.operator("text.comment")
  213. layout.operator("text.uncomment")
  214. layout.separator()
  215. layout.operator_menu_enum("text.convert_whitespace", "type")
  216. class TEXT_MT_edit_to3d(Menu):
  217. bl_label = "Text To 3D Object"
  218. def draw(self, _context):
  219. layout = self.layout
  220. layout.operator("text.to_3d_object",
  221. text="One Object",
  222. ).split_lines = False
  223. layout.operator("text.to_3d_object",
  224. text="One Object Per Line",
  225. ).split_lines = True
  226. class TEXT_MT_edit(Menu):
  227. bl_label = "Edit"
  228. @classmethod
  229. def poll(cls, context):
  230. return (context.space_data.text)
  231. def draw(self, _context):
  232. layout = self.layout
  233. layout.operator("ed.undo")
  234. layout.operator("ed.redo")
  235. layout.separator()
  236. layout.operator("text.cut")
  237. layout.operator("text.copy", icon='COPYDOWN')
  238. layout.operator("text.paste", icon='PASTEDOWN')
  239. layout.operator("text.duplicate_line")
  240. layout.separator()
  241. layout.operator("text.move_lines",
  242. text="Move line(s) up").direction = 'UP'
  243. layout.operator("text.move_lines",
  244. text="Move line(s) down").direction = 'DOWN'
  245. layout.separator()
  246. layout.menu("TEXT_MT_edit_select")
  247. layout.separator()
  248. layout.operator("text.jump")
  249. layout.operator("text.start_find", text="Find...")
  250. layout.operator("text.autocomplete")
  251. layout.separator()
  252. layout.menu("TEXT_MT_edit_to3d")
  253. class TEXT_MT_toolbox(Menu):
  254. bl_label = ""
  255. def draw(self, _context):
  256. layout = self.layout
  257. layout.operator_context = 'INVOKE_DEFAULT'
  258. layout.operator("text.cut")
  259. layout.operator("text.copy")
  260. layout.operator("text.paste")
  261. layout.separator()
  262. layout.operator("text.run_script")
  263. classes = (
  264. TEXT_HT_header,
  265. TEXT_HT_footer,
  266. TEXT_MT_edit,
  267. TEXT_MT_editor_menus,
  268. TEXT_PT_properties,
  269. TEXT_PT_find,
  270. TEXT_MT_view,
  271. TEXT_MT_text,
  272. TEXT_MT_templates,
  273. TEXT_MT_templates_py,
  274. TEXT_MT_templates_osl,
  275. TEXT_MT_edit_select,
  276. TEXT_MT_format,
  277. TEXT_MT_edit_to3d,
  278. TEXT_MT_toolbox,
  279. )
  280. if __name__ == "__main__": # only for live edit.
  281. from bpy.utils import register_class
  282. for cls in classes:
  283. register_class(cls)