Correct error in last commit
[blender.git] / release / scripts / startup / bl_ui / space_text.py
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
19 # <pep8-80 compliant>
20 import bpy
21 from bpy.types import Header, Menu, Panel
22 from bpy.app.translations import pgettext_iface as iface_
23
24
25 class TEXT_HT_header(Header):
26     bl_space_type = 'TEXT_EDITOR'
27
28     def draw(self, context):
29         layout = self.layout
30
31         st = context.space_data
32         text = st.text
33
34         layout.template_header()
35
36         TEXT_MT_editor_menus.draw_collapsible(context, layout)
37
38         if text and text.is_modified:
39             row = layout.row(align=True)
40             row.alert = True
41             row.operator("text.resolve_conflict", text="", icon='HELP')
42
43         layout.separator_spacer()
44
45         row = layout.row(align=True)
46         row.template_ID(st, "text", new="text.new", unlink="text.unlink", open="text.open")
47
48         layout.separator_spacer()
49
50         row = layout.row(align=True)
51         row.prop(st, "show_line_numbers", text="")
52         row.prop(st, "show_word_wrap", text="")
53         row.prop(st, "show_syntax_highlight", text="")
54
55         if text:
56             is_osl = text.name.endswith((".osl", ".osl"))
57
58             row = layout.row()
59             if is_osl:
60                 row = layout.row()
61                 row.operator("node.shader_script_update")
62             else:
63                 row = layout.row()
64                 row.active = text.name.endswith(".py")
65                 row.prop(text, "use_module")
66
67                 row = layout.row()
68                 row.operator("text.run_script")
69
70
71 class TEXT_HT_footer(Header):
72     bl_space_type = 'TEXT_EDITOR'
73     bl_region_type = 'FOOTER'
74
75     def draw(self, context):
76         layout = self.layout
77
78         st = context.space_data
79         text = st.text
80         if text:
81             row = layout.row()
82             if text.filepath:
83                 if text.is_dirty:
84                     row.label(
85                         text=iface_(f"File: *{text.filepath:s} (unsaved)"),
86                         translate=False,
87                     )
88                 else:
89                     row.label(
90                         text=iface_(f"File: {text.filepath:s}"),
91                         translate=False,
92                     )
93             else:
94                 row.label(
95                     text="Text: External"
96                     if text.library
97                     else "Text: Internal",
98                 )
99
100
101 class TEXT_MT_editor_menus(Menu):
102     bl_idname = "TEXT_MT_editor_menus"
103     bl_label = ""
104
105     def draw(self, context):
106         layout = self.layout
107         st = context.space_data
108         text = st.text
109
110         layout.menu("TEXT_MT_view")
111         layout.menu("TEXT_MT_text")
112
113         if text:
114             layout.menu("TEXT_MT_edit")
115             layout.menu("TEXT_MT_format")
116
117         layout.menu("TEXT_MT_templates")
118
119
120 class TEXT_PT_properties(Panel):
121     bl_space_type = 'TEXT_EDITOR'
122     bl_region_type = 'UI'
123     bl_category = "Text"
124     bl_label = "Properties"
125
126     def draw(self, context):
127         layout = self.layout
128
129         st = context.space_data
130
131         flow = layout.column_flow()
132         flow.prop(st, "show_line_numbers")
133         flow.prop(st, "show_word_wrap")
134         flow.prop(st, "show_syntax_highlight")
135         flow.prop(st, "show_line_highlight")
136         flow.prop(st, "use_live_edit")
137
138         flow = layout.column_flow()
139         flow.prop(st, "font_size")
140         flow.prop(st, "tab_width")
141
142         text = st.text
143         if text:
144             flow.prop(text, "use_tabs_as_spaces")
145
146         flow.prop(st, "show_margin")
147         col = flow.column()
148         col.active = st.show_margin
149         col.prop(st, "margin_column")
150
151
152 class TEXT_PT_find(Panel):
153     bl_space_type = 'TEXT_EDITOR'
154     bl_region_type = 'UI'
155     bl_category = "Text"
156     bl_label = "Find"
157
158     def draw(self, context):
159         layout = self.layout
160
161         st = context.space_data
162
163         # find
164         col = layout.column(align=True)
165         row = col.row(align=True)
166         row.prop(st, "find_text", text="")
167         row.operator("text.find_set_selected", text="", icon='TEXT')
168         col.operator("text.find")
169
170         # replace
171         col = layout.column(align=True)
172         row = col.row(align=True)
173         row.prop(st, "replace_text", text="")
174         row.operator("text.replace_set_selected", text="", icon='TEXT')
175         col.operator("text.replace")
176
177         # settings
178         layout.prop(st, "use_match_case")
179         row = layout.row(align=True)
180         row.prop(st, "use_find_wrap", text="Wrap")
181         row.prop(st, "use_find_all", text="All")
182
183
184 class TEXT_MT_view(Menu):
185     bl_label = "View"
186
187     def draw(self, context):
188         layout = self.layout
189
190         st = context.space_data
191
192         layout.prop(st, "show_region_ui")
193
194         layout.separator()
195
196         layout.operator("text.move",
197                         text="Top of File",
198                         ).type = 'FILE_TOP'
199         layout.operator("text.move",
200                         text="Bottom of File",
201                         ).type = 'FILE_BOTTOM'
202
203         layout.separator()
204
205         layout.menu("INFO_MT_area")
206
207
208 class TEXT_MT_text(Menu):
209     bl_label = "Text"
210
211     def draw(self, context):
212         layout = self.layout
213
214         st = context.space_data
215         text = st.text
216
217         layout.operator("text.new", text="New")
218         layout.operator("text.open", text="Open...", icon='FILE_FOLDER')
219
220         if text:
221             layout.separator()
222             layout.operator("text.reload")
223
224             layout.separator()
225             layout.operator("text.save", icon='FILE_TICK')
226             layout.operator("text.save_as", text="Save As...")
227
228             if text.filepath:
229                 layout.operator("text.make_internal")
230
231             layout.separator()
232             layout.operator("text.run_script")
233
234
235 class TEXT_MT_templates_py(Menu):
236     bl_label = "Python"
237
238     def draw(self, _context):
239         self.path_menu(
240             bpy.utils.script_paths("templates_py"),
241             "text.open",
242             props_default={"internal": True},
243         )
244
245
246 class TEXT_MT_templates_osl(Menu):
247     bl_label = "Open Shading Language"
248
249     def draw(self, _context):
250         self.path_menu(
251             bpy.utils.script_paths("templates_osl"),
252             "text.open",
253             props_default={"internal": True},
254         )
255
256
257 class TEXT_MT_templates(Menu):
258     bl_label = "Templates"
259
260     def draw(self, _context):
261         layout = self.layout
262         layout.menu("TEXT_MT_templates_py")
263         layout.menu("TEXT_MT_templates_osl")
264
265
266 class TEXT_MT_edit_select(Menu):
267     bl_label = "Select"
268
269     def draw(self, _context):
270         layout = self.layout
271
272         layout.operator("text.select_all")
273         layout.operator("text.select_line")
274
275
276 class TEXT_MT_format(Menu):
277     bl_label = "Format"
278
279     def draw(self, _context):
280         layout = self.layout
281
282         layout.operator("text.indent")
283         layout.operator("text.unindent")
284
285         layout.separator()
286
287         layout.operator("text.comment")
288         layout.operator("text.uncomment")
289
290         layout.separator()
291
292         layout.operator_menu_enum("text.convert_whitespace", "type")
293
294
295 class TEXT_MT_edit_to3d(Menu):
296     bl_label = "Text To 3D Object"
297
298     def draw(self, _context):
299         layout = self.layout
300
301         layout.operator("text.to_3d_object",
302                         text="One Object",
303                         ).split_lines = False
304         layout.operator("text.to_3d_object",
305                         text="One Object Per Line",
306                         ).split_lines = True
307
308
309 class TEXT_MT_edit(Menu):
310     bl_label = "Edit"
311
312     @classmethod
313     def poll(cls, context):
314         return (context.space_data.text)
315
316     def draw(self, _context):
317         layout = self.layout
318
319         layout.operator("ed.undo")
320         layout.operator("ed.redo")
321
322         layout.separator()
323
324         layout.operator("text.cut")
325         layout.operator("text.copy", icon='COPYDOWN')
326         layout.operator("text.paste", icon='PASTEDOWN')
327         layout.operator("text.duplicate_line")
328
329         layout.separator()
330
331         layout.operator("text.move_lines",
332                         text="Move line(s) up").direction = 'UP'
333         layout.operator("text.move_lines",
334                         text="Move line(s) down").direction = 'DOWN'
335
336         layout.separator()
337
338         layout.menu("TEXT_MT_edit_select")
339
340         layout.separator()
341
342         layout.operator("text.jump")
343         layout.operator("text.start_find", text="Find...")
344         layout.operator("text.autocomplete")
345
346         layout.separator()
347
348         layout.menu("TEXT_MT_edit_to3d")
349
350
351 class TEXT_MT_toolbox(Menu):
352     bl_label = ""
353
354     def draw(self, _context):
355         layout = self.layout
356
357         layout.operator_context = 'INVOKE_DEFAULT'
358
359         layout.operator("text.cut")
360         layout.operator("text.copy")
361         layout.operator("text.paste")
362
363         layout.separator()
364
365         layout.operator("text.run_script")
366
367
368 classes = (
369     TEXT_HT_header,
370     TEXT_HT_footer,
371     TEXT_MT_edit,
372     TEXT_MT_editor_menus,
373     TEXT_PT_properties,
374     TEXT_PT_find,
375     TEXT_MT_view,
376     TEXT_MT_text,
377     TEXT_MT_templates,
378     TEXT_MT_templates_py,
379     TEXT_MT_templates_osl,
380     TEXT_MT_edit_select,
381     TEXT_MT_format,
382     TEXT_MT_edit_to3d,
383     TEXT_MT_toolbox,
384 )
385
386 if __name__ == "__main__":  # only for live edit.
387     from bpy.utils import register_class
388     for cls in classes:
389         register_class(cls)