@@ -12,183 +12,183 @@ pub fn draw_menu(ctx: &Context, app: &mut CascExplorerApp) {
1212 . inner_margin ( egui:: Margin :: symmetric ( 12.0 , 4.0 ) ) ,
1313 )
1414 . show ( ctx, |ui| {
15- egui:: menu:: bar ( ui, |ui| {
16- // ── File ──────────────────────────────────────────────────────────
17- ui. menu_button ( "File" , |ui| {
18- // Auto-detected game installs.
19- let installs = detect_game_installs ( ) ;
20- if !installs. is_empty ( ) {
21- ui. menu_button ( "Open Game" , |ui| {
22- for ( name, path) in & installs {
23- if ui. button ( name) . clicked ( ) {
24- ui. close_menu ( ) ;
25- app. open_game_dir ( path. clone ( ) ) ;
15+ egui:: menu:: bar ( ui, |ui| {
16+ // ── File ──────────────────────────────────────────────────────────
17+ ui. menu_button ( "File" , |ui| {
18+ // Auto-detected game installs.
19+ let installs = detect_game_installs ( ) ;
20+ if !installs. is_empty ( ) {
21+ ui. menu_button ( "Open Game" , |ui| {
22+ for ( name, path) in & installs {
23+ if ui. button ( name) . clicked ( ) {
24+ ui. close_menu ( ) ;
25+ app. open_game_dir ( path. clone ( ) ) ;
26+ }
2627 }
28+ } ) ;
29+ }
30+
31+ if ui. button ( "Open Game Directory…" ) . clicked ( ) {
32+ ui. close_menu ( ) ;
33+ if let Some ( path) = rfd:: FileDialog :: new ( ) . pick_folder ( ) {
34+ app. open_game_dir ( path) ;
2735 }
28- } ) ;
29- }
36+ }
3037
31- if ui. button ( "Open Game Directory…" ) . clicked ( ) {
32- ui. close_menu ( ) ;
33- if let Some ( path) = rfd:: FileDialog :: new ( ) . pick_folder ( ) {
34- app. open_game_dir ( path) ;
38+ let has_builtin = app
39+ . handler
40+ . as_ref ( )
41+ . map ( |h| h. has_builtin_paths ( ) )
42+ . unwrap_or ( false ) ;
43+ let listfile_enabled = app. handler . is_some ( ) && !has_builtin;
44+ let listfile_btn =
45+ ui. add_enabled ( listfile_enabled, egui:: Button :: new ( "Load Listfile…" ) ) ;
46+ let listfile_btn = if has_builtin {
47+ listfile_btn. on_disabled_hover_text (
48+ "Not needed — this game provides its own file paths." ,
49+ )
50+ } else {
51+ listfile_btn
52+ } ;
53+ if listfile_btn. clicked ( ) {
54+ ui. close_menu ( ) ;
55+ if let Some ( path) = rfd:: FileDialog :: new ( )
56+ . add_filter ( "Listfile" , & [ "csv" , "txt" ] )
57+ . pick_file ( )
58+ {
59+ app. load_listfile ( path) ;
60+ }
3561 }
36- }
37-
38- let has_builtin = app
39- . handler
40- . as_ref ( )
41- . map ( |h| h. has_builtin_paths ( ) )
42- . unwrap_or ( false ) ;
43- let listfile_enabled = app. handler . is_some ( ) && !has_builtin;
44- let listfile_btn =
45- ui. add_enabled ( listfile_enabled, egui:: Button :: new ( "Load Listfile…" ) ) ;
46- let listfile_btn = if has_builtin {
47- listfile_btn. on_disabled_hover_text (
48- "Not needed — this game provides its own file paths." ,
49- )
50- } else {
51- listfile_btn
52- } ;
53- if listfile_btn. clicked ( ) {
54- ui. close_menu ( ) ;
55- if let Some ( path) = rfd:: FileDialog :: new ( )
56- . add_filter ( "Listfile" , & [ "csv" , "txt" ] )
57- . pick_file ( )
62+
63+ ui. separator ( ) ;
64+
65+ let sel_count = app. multi_selected . len ( ) ;
66+ let has_selection = sel_count > 0 ;
67+
68+ if ui
69+ . add_enabled (
70+ has_selection,
71+ egui:: Button :: new ( format ! ( "Export {sel_count} Selected…" ) ) ,
72+ )
73+ . clicked ( )
5874 {
59- app. load_listfile ( path) ;
75+ ui. close_menu ( ) ;
76+ app. export_selected ( ) ;
6077 }
61- }
62-
63- ui. separator ( ) ;
64-
65- let sel_count = app. multi_selected . len ( ) ;
66- let has_selection = sel_count > 0 ;
67-
68- if ui
69- . add_enabled (
70- has_selection,
71- egui:: Button :: new ( format ! ( "Export {sel_count} Selected…" ) ) ,
72- )
73- . clicked ( )
74- {
75- ui. close_menu ( ) ;
76- app. export_selected ( ) ;
77- }
78-
79- if ui
80- . add_enabled (
81- app. browsed_folder . is_some ( ) ,
82- egui:: Button :: new ( "Export Current Folder…" ) ,
83- )
84- . clicked ( )
85- {
86- ui. close_menu ( ) ;
87- app. export_folder ( ) ;
88- }
89-
90- ui. separator ( ) ;
91-
92- if ui. button ( "Quit" ) . clicked ( ) {
93- ctx. send_viewport_cmd ( egui:: ViewportCommand :: Close ) ;
94- }
95- } ) ;
9678
97- // ── Edit ──────────────────────────────────────────────────────────
98- ui. menu_button ( "Edit" , |ui| {
99- if ui. button ( "Copy Hash" ) . clicked ( ) {
100- ui. close_menu ( ) ;
101- if let Some ( sel) = & app. selected {
102- ctx. copy_text ( format ! ( "{:016X}" , sel. result. hash) ) ;
79+ if ui
80+ . add_enabled (
81+ app. browsed_folder . is_some ( ) ,
82+ egui:: Button :: new ( "Export Current Folder…" ) ,
83+ )
84+ . clicked ( )
85+ {
86+ ui. close_menu ( ) ;
87+ app. export_folder ( ) ;
10388 }
104- }
105- if ui. button ( "Copy CKey" ) . clicked ( ) {
106- ui . close_menu ( ) ;
107- if let Some ( sel ) = & app . selected {
108- ctx. copy_text ( sel . result . ckey . to_hex ( ) ) ;
89+
90+ ui. separator ( ) ;
91+
92+ if ui . button ( "Quit" ) . clicked ( ) {
93+ ctx. send_viewport_cmd ( egui :: ViewportCommand :: Close ) ;
10994 }
110- }
111- } ) ;
95+ } ) ;
11296
113- // ── View ──────────────────────────────────────────────────────────
114- ui. menu_button ( "View" , |ui| {
115- if ui. button ( "Expand All" ) . clicked ( ) {
116- ui. close_menu ( ) ;
117- if let Some ( handler) = & app. handler {
118- if let Some ( root) = & handler. root_folder {
119- collect_folder_paths ( root, "" , & mut app. expanded ) ;
97+ // ── Edit ──────────────────────────────────────────────────────────
98+ ui. menu_button ( "Edit" , |ui| {
99+ if ui. button ( "Copy Hash" ) . clicked ( ) {
100+ ui. close_menu ( ) ;
101+ if let Some ( sel) = & app. selected {
102+ ctx. copy_text ( format ! ( "{:016X}" , sel. result. hash) ) ;
120103 }
121104 }
122- app. expansion_dirty = true ;
123- }
124- if ui. button ( "Collapse All" ) . clicked ( ) {
125- ui. close_menu ( ) ;
126- app. expanded . clear ( ) ;
127- app. expansion_dirty = true ;
128- }
129- ui. separator ( ) ;
130- ui. checkbox ( & mut app. viewport3d_open , "3D Test Viewport" ) ;
131- } ) ;
105+ if ui. button ( "Copy CKey" ) . clicked ( ) {
106+ ui. close_menu ( ) ;
107+ if let Some ( sel) = & app. selected {
108+ ctx. copy_text ( sel. result . ckey . to_hex ( ) ) ;
109+ }
110+ }
111+ } ) ;
132112
133- // ── Tools ─────────────────────────────────────────────────────────
134- ui. menu_button ( "Tools" , |ui| {
135- // Show detected products first, then a fixed fallback list.
136- let detected = app. detected_products . clone ( ) ;
137- let fallback = [
138- "fenris" ,
139- "wow" ,
140- "wow_classic" ,
141- "hs" ,
142- "s2" ,
143- "hero" ,
144- "pro" ,
145- "w3" ,
146- "osi" ,
147- "d3" ,
148- ] ;
149- let products: Vec < & str > = if detected. is_empty ( ) {
150- fallback. to_vec ( )
151- } else {
152- detected. iter ( ) . map ( |s| s. as_str ( ) ) . collect ( )
153- } ;
154-
155- ui. menu_button ( "Product" , |ui| {
156- for product in & products {
157- if ui
158- . selectable_label ( & app. product == product, * product)
159- . clicked ( )
160- {
161- app. product = product. to_string ( ) ;
162- ui. close_menu ( ) ;
113+ // ── View ──────────────────────────────────────────────────────────
114+ ui. menu_button ( "View" , |ui| {
115+ if ui. button ( "Expand All" ) . clicked ( ) {
116+ ui. close_menu ( ) ;
117+ if let Some ( handler) = & app. handler {
118+ if let Some ( root) = & handler. root_folder {
119+ collect_folder_paths ( root, "" , & mut app. expanded ) ;
120+ }
163121 }
122+ app. expansion_dirty = true ;
123+ }
124+ if ui. button ( "Collapse All" ) . clicked ( ) {
125+ ui. close_menu ( ) ;
126+ app. expanded . clear ( ) ;
127+ app. expansion_dirty = true ;
164128 }
129+ ui. separator ( ) ;
130+ ui. checkbox ( & mut app. viewport3d_open , "3D Test Viewport" ) ;
165131 } ) ;
166132
167- let mut validate = app
168- . handler
169- . as_ref ( )
170- . map ( |h| h. validate_hashes )
171- . unwrap_or ( false ) ;
172- if ui. checkbox ( & mut validate, "Validate Hashes" ) . clicked ( ) {
173- if let Some ( h) = app. handler . as_mut ( ) . and_then ( Arc :: get_mut) {
174- h. validate_hashes = validate;
133+ // ── Tools ─────────────────────────────────────────────────────────
134+ ui. menu_button ( "Tools" , |ui| {
135+ // Show detected products first, then a fixed fallback list.
136+ let detected = app. detected_products . clone ( ) ;
137+ let fallback = [
138+ "fenris" ,
139+ "wow" ,
140+ "wow_classic" ,
141+ "hs" ,
142+ "s2" ,
143+ "hero" ,
144+ "pro" ,
145+ "w3" ,
146+ "osi" ,
147+ "d3" ,
148+ ] ;
149+ let products: Vec < & str > = if detected. is_empty ( ) {
150+ fallback. to_vec ( )
151+ } else {
152+ detected. iter ( ) . map ( |s| s. as_str ( ) ) . collect ( )
153+ } ;
154+
155+ ui. menu_button ( "Product" , |ui| {
156+ for product in & products {
157+ if ui
158+ . selectable_label ( & app. product == product, * product)
159+ . clicked ( )
160+ {
161+ app. product = product. to_string ( ) ;
162+ ui. close_menu ( ) ;
163+ }
164+ }
165+ } ) ;
166+
167+ let mut validate = app
168+ . handler
169+ . as_ref ( )
170+ . map ( |h| h. validate_hashes )
171+ . unwrap_or ( false ) ;
172+ if ui. checkbox ( & mut validate, "Validate Hashes" ) . clicked ( ) {
173+ if let Some ( h) = app. handler . as_mut ( ) . and_then ( Arc :: get_mut) {
174+ h. validate_hashes = validate;
175+ }
175176 }
176- }
177- } ) ;
177+ } ) ;
178178
179- // ── Help ──────────────────────────────────────────────────────────
180- ui. menu_button ( "Help" , |ui| {
181- if ui. button ( "About" ) . clicked ( ) {
182- ui. close_menu ( ) ;
183- app. status = format ! (
184- "rustydemon v{} — CASC explorer | rustydemon-lib v{}" ,
185- env!( "CARGO_PKG_VERSION" ) ,
186- env!( "CARGO_PKG_VERSION" ) ,
187- ) ;
188- }
179+ // ── Help ──────────────────────────────────────────────────────────
180+ ui. menu_button ( "Help" , |ui| {
181+ if ui. button ( "About" ) . clicked ( ) {
182+ ui. close_menu ( ) ;
183+ app. status = format ! (
184+ "rustydemon v{} — CASC explorer | rustydemon-lib v{}" ,
185+ env!( "CARGO_PKG_VERSION" ) ,
186+ env!( "CARGO_PKG_VERSION" ) ,
187+ ) ;
188+ }
189+ } ) ;
189190 } ) ;
190191 } ) ;
191- } ) ;
192192}
193193
194194fn collect_folder_paths (
0 commit comments