1+ use std:: cell:: RefCell ;
12use std:: {
23 collections:: HashSet ,
34 fmt:: Display ,
@@ -10,10 +11,10 @@ use std::{
1011use binrw:: { binread, BinReaderExt , Endian } ;
1112use destiny_pkg:: { package:: UEntryHeader , PackageVersion , TagHash , TagHash64 } ;
1213use eframe:: egui:: load:: SizedTexture ;
13- use eframe:: egui:: { collapsing_header:: CollapsingState , vec2, TextureId } ;
14+ use eframe:: egui:: { collapsing_header:: CollapsingState , vec2, RichText , TextureId } ;
1415use eframe:: egui_wgpu:: RenderState ;
1516use eframe:: {
16- egui:: { self , CollapsingHeader , RichText } ,
17+ egui:: { self , CollapsingHeader } ,
1718 epaint:: Color32 ,
1819 wgpu,
1920} ;
@@ -22,6 +23,7 @@ use log::error;
2223use poll_promise:: Promise ;
2324use rustc_hash:: FxHashMap ;
2425use std:: fmt:: Write ;
26+ use std:: rc:: Rc ;
2527
2628use crate :: { gui:: texture:: Texture , scanner:: read_raw_string_blob, text:: RawStringHashCache } ;
2729use crate :: {
@@ -43,6 +45,7 @@ use super::{
4345
4446pub struct TagView {
4547 cache : Arc < TagCache > ,
48+ tag_history : Rc < RefCell < TagHistory > > ,
4649 string_cache : Arc < StringCache > ,
4750 raw_string_hash_cache : Arc < RawStringHashCache > ,
4851
@@ -74,6 +77,7 @@ pub struct TagView {
7477impl TagView {
7578 pub fn create (
7679 cache : Arc < TagCache > ,
80+ tag_history : Rc < RefCell < TagHistory > > ,
7781 string_cache : Arc < StringCache > ,
7882 raw_string_hash_cache : Arc < RawStringHashCache > ,
7983 tag : TagHash ,
@@ -237,6 +241,7 @@ impl TagView {
237241
238242 scan,
239243 cache,
244+ tag_history,
240245 traversal_depth_limit : 16 ,
241246 tag_traversal : None ,
242247 traversal_show_strings : false ,
@@ -252,9 +257,13 @@ impl TagView {
252257 }
253258
254259 /// Replaces this view with another tag
255- pub fn open_tag ( & mut self , tag : TagHash ) {
260+ pub fn open_tag ( & mut self , tag : TagHash , push_history : bool ) {
261+ if push_history {
262+ self . tag_history . borrow_mut ( ) . push ( tag) ;
263+ }
256264 if let Some ( mut tv) = Self :: create (
257265 self . cache . clone ( ) ,
266+ self . tag_history . clone ( ) ,
258267 self . string_cache . clone ( ) ,
259268 self . raw_string_hash_cache . clone ( ) ,
260269 tag,
@@ -373,6 +382,49 @@ impl View for TagView {
373382 ui : & mut eframe:: egui:: Ui ,
374383 ) -> Option < ViewAction > {
375384 let mut open_new_tag = None ;
385+ let mut push_history = true ;
386+
387+ ui. horizontal ( |ui| {
388+ let mut history = self . tag_history . borrow_mut ( ) ;
389+
390+ ui. style_mut ( ) . spacing . button_padding = [ 4.0 , 4.0 ] . into ( ) ;
391+ ui. add_enabled_ui ( history. current > 0 , |ui| {
392+ if ui. button ( RichText :: new ( "⬅" ) . strong ( ) ) . clicked ( ) {
393+ open_new_tag = history. back ( ) ;
394+ push_history = false ;
395+ }
396+ } ) ;
397+
398+ ui. add_enabled_ui ( ( history. current + 1 ) < history. tags . len ( ) , |ui| {
399+ if ui. button ( RichText :: new ( "➡" ) . strong ( ) ) . clicked ( ) {
400+ open_new_tag = history. forward ( ) ;
401+ push_history = false ;
402+ }
403+ } ) ;
404+
405+ egui:: ComboBox :: new ( "tag_history" , "" )
406+ . selected_text ( "History" )
407+ . show_ui ( ui, |ui| {
408+ let mut set_current = None ;
409+ for ( i, ( tag, tag_label, tag_color) ) in history. tags . iter ( ) . enumerate ( ) . rev ( ) {
410+ if ui
411+ . selectable_label (
412+ i == history. current ,
413+ RichText :: new ( tag_label) . color ( * tag_color) ,
414+ )
415+ . clicked ( )
416+ {
417+ open_new_tag = Some ( * tag) ;
418+ push_history = false ;
419+ set_current = Some ( i) ;
420+ }
421+ }
422+
423+ if let Some ( i) = set_current {
424+ history. current = i;
425+ }
426+ } ) ;
427+ } ) ;
376428
377429 ui. heading ( format_tag_entry ( self . tag , Some ( & self . tag_entry ) ) )
378430 . context_menu ( |ui| tag_context ( ui, self . tag , self . tag64 ) ) ;
@@ -812,7 +864,7 @@ impl View for TagView {
812864 ctx. request_repaint_after ( Duration :: from_secs ( 1 ) ) ;
813865
814866 if let Some ( new_tag) = open_new_tag {
815- self . open_tag ( new_tag) ;
867+ self . open_tag ( new_tag, push_history ) ;
816868 }
817869
818870 None
@@ -1214,3 +1266,49 @@ pub fn strip_ansi_codes(input: &str) -> String {
12141266 let ansi_escape_pattern = regex:: Regex :: new ( r"\x1B\[[0-9;]*[mK]" ) . unwrap ( ) ;
12151267 ansi_escape_pattern. replace_all ( input, "" ) . to_string ( )
12161268}
1269+
1270+ #[ derive( Default ) ]
1271+ pub struct TagHistory {
1272+ pub tags : Vec < ( TagHash , String , Color32 ) > ,
1273+ pub current : usize ,
1274+ }
1275+
1276+ impl TagHistory {
1277+ pub fn push ( & mut self , tag : TagHash ) {
1278+ self . tags . truncate ( self . current + 1 ) ;
1279+
1280+ if let Some ( entry) = package_manager ( ) . get_entry ( tag) {
1281+ let tagtype = TagType :: from_type_subtype ( entry. file_type , entry. file_subtype ) ;
1282+ let color = tagtype. display_color ( ) ;
1283+ let fancy_tag = format_tag_entry ( tag, Some ( & entry) ) ;
1284+
1285+ self . tags . push ( ( tag, fancy_tag, color) ) ;
1286+ } else {
1287+ self . tags . push ( (
1288+ tag,
1289+ format ! ( "{tag} (pkg entry not found)" ) ,
1290+ Color32 :: LIGHT_RED ,
1291+ ) ) ;
1292+ }
1293+
1294+ self . current = self . tags . len ( ) . saturating_sub ( 1 ) ;
1295+ }
1296+
1297+ pub fn back ( & mut self ) -> Option < TagHash > {
1298+ if self . current > 0 {
1299+ self . current -= 1 ;
1300+ self . tags . get ( self . current ) . map ( |v| v. 0 )
1301+ } else {
1302+ None
1303+ }
1304+ }
1305+
1306+ pub fn forward ( & mut self ) -> Option < TagHash > {
1307+ if ( self . current + 1 ) < self . tags . len ( ) {
1308+ self . current += 1 ;
1309+ self . tags . get ( self . current ) . map ( |v| v. 0 )
1310+ } else {
1311+ None
1312+ }
1313+ }
1314+ }
0 commit comments