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