2222# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2323# SOFTWARE.
2424
25+ from dataclasses import asdict
26+ from dataclasses import dataclass
27+ import os
2528from pathlib import Path
29+ import tkinter
2630
2731import ansys .aedt .core
2832from ansys .aedt .core import get_pyaedt_app
3438from ansys .aedt .core .extensions .misc import is_student
3539from ansys .aedt .core .visualization .advanced .misc import nastran_to_stl
3640
37- port = get_port ()
38- version = get_aedt_version ()
39- aedt_process_id = get_process_id ()
40- is_student = is_student ()
4141
42- # Extension batch arguments
43- extension_arguments = {"decimate" : 0.0 , "lightweight" : False , "planar" : True , "file_path" : "" }
44- extension_description = "Import Nastran or STL file"
42+ @dataclass
43+ class ExtensionData :
44+ decimate : float = 0.0
45+ lightweight : bool = False
46+ planar : bool = True
47+ file_path : str = ""
4548
4649
47- def frontend (): # pragma: no cover
48- import tkinter
49- from tkinter import filedialog
50- from tkinter import ttk
51-
52- import PIL .Image
53- import PIL .ImageTk
54-
55- from ansys .aedt .core .extensions .misc import ExtensionTheme
56-
57- master = tkinter .Tk ()
58- master .title ("Import Nastran or STL file" )
50+ PORT = get_port ()
51+ VERSION = get_aedt_version ()
52+ AEDT_PROCESS_ID = get_process_id ()
53+ IS_STUDENT = is_student ()
54+ EXTENSION_TITLE = "Import Nastran or STL file"
55+ EXTENSION_DEFAULT_ARGUMENTS = {"decimate" : 0.0 , "lightweight" : False , "planar" : True , "file_path" : "" }
5956
60- # Detect if user closes the UI
61- master .flag = False
57+ result = None
6258
63- # Load the logo for the main window
64- icon_path = Path (ansys .aedt .core .extensions .__path__ [0 ]) / "images" / "large" / "logo.png"
65- im = PIL .Image .open (icon_path )
66- photo = PIL .ImageTk .PhotoImage (im )
6759
68- # Set the icon for the main window
69- master .iconphoto (True , photo )
70-
71- # Configure style for ttk buttons
72- style = ttk .Style ()
73- theme = ExtensionTheme ()
74-
75- # Apply light theme initially
76- theme .apply_light_theme (style )
77- master .theme = "light"
60+ def create_ui (withdraw = False ):
61+ from tkinter import filedialog
62+ from tkinter import ttk
7863
79- # Set background color of the window (optional)
80- master .configure (bg = theme .light ["widget_bg" ])
64+ from ansys .aedt .core .extensions .misc import create_default_ui
8165
82- label2 = ttk . Label ( master , text = "Browse file:" , style = "PyAEDT.TLabel" )
66+ root , theme , style = create_default_ui ( EXTENSION_TITLE , withdraw = withdraw )
8367
68+ label2 = ttk .Label (root , text = "Browse file:" , style = "PyAEDT.TLabel" )
8469 label2 .grid (row = 0 , column = 0 , pady = 10 )
85- text = tkinter .Text (master , width = 40 , height = 1 )
70+
71+ text = tkinter .Text (root , width = 40 , height = 1 , name = "file_path_text" )
8672 text .configure (bg = theme .light ["pane_bg" ], foreground = theme .light ["text" ], font = theme .default_font )
8773 text .grid (row = 0 , column = 1 , pady = 10 , padx = 5 )
8874
@@ -94,105 +80,97 @@ def browseFiles():
9480 )
9581 text .insert (tkinter .END , filename )
9682
97- b1 = ttk .Button (master , text = "..." , width = 10 , command = browseFiles , style = "PyAEDT.TButton" )
83+ b1 = ttk .Button (root , text = "..." , width = 10 , command = browseFiles , style = "PyAEDT.TButton" , name = "browse_button " )
9884 b1 .grid (row = 0 , column = 2 , pady = 10 )
9985
100- label = ttk .Label (master , text = "Decimation factor (0-0.9). It may affect results:" , style = "PyAEDT.TLabel" )
86+ label = ttk .Label (root , text = "Decimation factor (0-0.9). It may affect results:" , style = "PyAEDT.TLabel" )
10187 label .grid (row = 1 , column = 0 , pady = 10 )
10288
103- check = tkinter .Text (master , width = 20 , height = 1 )
89+ check = tkinter .Text (root , width = 20 , height = 1 , name = "decimation_text" )
10490 check .configure (bg = theme .light ["pane_bg" ], foreground = theme .light ["text" ], font = theme .default_font )
10591 check .insert (tkinter .END , "0.0" )
10692 check .grid (row = 1 , column = 1 , pady = 10 , padx = 5 )
10793
108- label = ttk .Label (master , text = "Import as lightweight (only HFSS):" , style = "PyAEDT.TLabel" )
94+ label = ttk .Label (root , text = "Import as lightweight (only HFSS):" , style = "PyAEDT.TLabel" )
10995 label .grid (row = 2 , column = 0 , pady = 10 )
110- light = tkinter .IntVar ()
111- check2 = ttk .Checkbutton (master , variable = light , style = "PyAEDT.TCheckbutton" )
96+ light = tkinter .IntVar (root , name = "var_lightweight" )
97+ check2 = ttk .Checkbutton (root , variable = light , style = "PyAEDT.TCheckbutton" , name = "check_lightweight " )
11298 check2 .grid (row = 2 , column = 1 , pady = 10 , padx = 5 )
11399
114- label = ttk .Label (master , text = "Enable planar merge:" , style = "PyAEDT.TLabel" )
100+ label = ttk .Label (root , text = "Enable planar merge:" , style = "PyAEDT.TLabel" )
115101 label .grid (row = 3 , column = 0 , pady = 10 )
116- planar = tkinter .IntVar (value = 1 )
117- check3 = ttk .Checkbutton (master , variable = planar , style = "PyAEDT.TCheckbutton" )
102+ planar = tkinter .IntVar (root , value = 1 )
103+ check3 = ttk .Checkbutton (root , variable = planar , style = "PyAEDT.TCheckbutton" , name = "check_planar_merge " )
118104 check3 .grid (row = 3 , column = 1 , pady = 10 , padx = 5 )
119105
120106 def toggle_theme ():
121- if master .theme == "light" :
107+ if root .theme == "light" :
122108 set_dark_theme ()
123- master .theme = "dark"
109+ root .theme = "dark"
124110 else :
125111 set_light_theme ()
126- master .theme = "light"
112+ root .theme = "light"
127113
128114 def set_light_theme ():
129- master .configure (bg = theme .light ["widget_bg" ])
115+ root .configure (bg = theme .light ["widget_bg" ])
130116 text .configure (bg = theme .light ["pane_bg" ], foreground = theme .light ["text" ], font = theme .default_font )
131117 check .configure (bg = theme .light ["pane_bg" ], foreground = theme .light ["text" ], font = theme .default_font )
132118 theme .apply_light_theme (style )
133119 change_theme_button .config (text = "\u263d " ) # Sun icon for light theme
134120
135121 def set_dark_theme ():
136- master .configure (bg = theme .dark ["widget_bg" ])
122+ root .configure (bg = theme .dark ["widget_bg" ])
137123 text .configure (bg = theme .dark ["pane_bg" ], foreground = theme .dark ["text" ], font = theme .default_font )
138124 check .configure (bg = theme .dark ["pane_bg" ], foreground = theme .dark ["text" ], font = theme .default_font )
139125 theme .apply_dark_theme (style )
140126 change_theme_button .config (text = "\u2600 " ) # Moon icon for dark theme
141127
142128 # Create a frame for the toggle button to position it correctly
143- button_frame = ttk .Frame (master , style = "PyAEDT.TFrame" , relief = tkinter .SUNKEN , borderwidth = 2 )
129+ button_frame = ttk .Frame (
130+ root , style = "PyAEDT.TFrame" , relief = tkinter .SUNKEN , borderwidth = 2 , name = "theme_button_frame"
131+ )
144132 button_frame .grid (row = 5 , column = 2 , pady = 10 , padx = 10 )
145133
146134 # Add the toggle theme button inside the frame
147135 change_theme_button = ttk .Button (
148- button_frame , width = 20 , text = "\u263d " , command = toggle_theme , style = "PyAEDT.TButton"
136+ button_frame , width = 20 , text = "\u263d " , command = toggle_theme , style = "PyAEDT.TButton" , name = "theme_toggle_button"
149137 )
150138
151139 change_theme_button .grid (row = 0 , column = 0 , padx = 0 )
152140
153141 def callback ():
154- master .flag = True
155- master .decimate_ui = float (check .get ("1.0" , tkinter .END ).strip ())
156- master .lightweight_ui = True if light .get () == 1 else False
157- master .planar_ui = True if planar .get () == 1 else False
158- master .file_path_ui = text .get ("1.0" , tkinter .END ).strip ()
159- master .destroy ()
142+ global result
143+ result = ExtensionData (
144+ decimate = float (check .get ("1.0" , tkinter .END ).strip ()),
145+ lightweight = True if light .get () == 1 else False ,
146+ planar = True if planar .get () == 1 else False ,
147+ file_path = text .get ("1.0" , tkinter .END ).strip (),
148+ )
149+ root .destroy ()
160150
161151 def preview ():
162- master .decimate_ui = float (check .get ("1.0" , tkinter .END ).strip ())
163- master .lightweight_ui = True if light .get () == 1 else False
164- master .planar_ui = True if planar .get () == 1 else False
165- master .file_path_ui = text .get ("1.0" , tkinter .END ).strip ()
152+ decimate_ui = float (check .get ("1.0" , tkinter .END ).strip ())
153+ file_path_ui = text .get ("1.0" , tkinter .END ).strip ()
154+ if not file_path_ui :
155+ raise ValueError ("Incorrect file path. Please select a valid file." )
156+
157+ if not Path (file_path_ui ).is_file ():
158+ raise FileNotFoundError (f"File ({ file_path_ui } ) not found" )
166159
167- if master . file_path_ui .endswith (".nas" ):
168- nastran_to_stl (input_file = master . file_path_ui , decimation = master . decimate_ui , preview = True )
160+ if file_path_ui .endswith (".nas" ):
161+ nastran_to_stl (file_path_ui , decimation = decimate_ui , preview = True )
169162 else :
170163 from ansys .aedt .core .visualization .advanced .misc import simplify_stl
171164
172- simplify_stl (master . file_path_ui , decimation = master . decimate_ui , preview = True )
165+ simplify_stl (file_path_ui , decimation = decimate_ui , preview = True )
173166
174- b2 = ttk .Button (master , text = "Preview" , width = 40 , command = preview , style = "PyAEDT.TButton" )
167+ b2 = ttk .Button (root , text = "Preview" , width = 40 , command = preview , style = "PyAEDT.TButton" , name = "preview_button " )
175168 b2 .grid (row = 5 , column = 0 , pady = 10 , padx = 10 )
176169
177- b3 = ttk .Button (master , text = "Ok" , width = 40 , command = callback , style = "PyAEDT.TButton" )
170+ b3 = ttk .Button (root , text = "Ok" , width = 40 , command = callback , style = "PyAEDT.TButton" , name = "ok_button " )
178171 b3 .grid (row = 5 , column = 1 , pady = 10 , padx = 10 )
179172
180- tkinter .mainloop ()
181-
182- decimate_ui = getattr (master , "decimate_ui" , extension_arguments ["decimate" ])
183- lightweight_ui = getattr (master , "lightweight_ui" , extension_arguments ["lightweight" ])
184- planar_ui = getattr (master , "planar_ui" , extension_arguments ["planar" ])
185- file_path_ui = getattr (master , "file_path_ui" , extension_arguments ["file_path" ])
186-
187- output_dict = {}
188- if master .flag :
189- output_dict = {
190- "decimate" : decimate_ui ,
191- "lightweight" : lightweight_ui ,
192- "planar" : planar_ui ,
193- "file_path" : file_path_ui ,
194- }
195- return output_dict
173+ return root
196174
197175
198176def main (extension_args ):
@@ -204,10 +182,10 @@ def main(extension_args):
204182 if file_path .is_file ():
205183 app = ansys .aedt .core .Desktop (
206184 new_desktop = False ,
207- version = version ,
208- port = port ,
209- aedt_process_id = aedt_process_id ,
210- student_version = is_student ,
185+ version = VERSION ,
186+ port = PORT ,
187+ aedt_process_id = AEDT_PROCESS_ID ,
188+ student_version = IS_STUDENT ,
211189 )
212190
213191 active_project = app .active_project ()
@@ -233,28 +211,29 @@ def main(extension_args):
233211 else :
234212 app = ansys .aedt .core .Desktop (
235213 new_desktop = False ,
236- version = version ,
237- port = port ,
238- aedt_process_id = aedt_process_id ,
239- student_version = is_student ,
214+ version = VERSION ,
215+ port = PORT ,
216+ aedt_process_id = AEDT_PROCESS_ID ,
217+ student_version = IS_STUDENT ,
240218 )
241219 app .logger .debug ("Wrong file selected. Select a .nas or .stl file" )
242220
243- if not extension_args [ "is_test" ]: # pragma: no cover
221+ if "PYTEST_CURRENT_TEST" not in os . environ :
244222 app .release_desktop (False , False )
245223 return True
246224
247225
248226if __name__ == "__main__" : # pragma: no cover
249- args = get_arguments (extension_arguments , extension_description )
227+ args = get_arguments (EXTENSION_DEFAULT_ARGUMENTS , EXTENSION_TITLE )
250228
251229 # Open UI
252230 if not args ["is_batch" ]: # pragma: no cover
253- output = frontend ()
254- if output :
255- for output_name , output_value in output .items ():
256- if output_name in extension_arguments :
257- args [output_name ] = output_value
231+ root = create_ui ()
232+
233+ tkinter .mainloop ()
234+
235+ if result :
236+ args .update (asdict (result ))
258237 main (args )
259238 else :
260239 main (args )
0 commit comments