22
33import io .github .pixelclover .uview .core .PackageManager ;
44import io .github .pixelclover .uview .model .UnityAsset ;
5- import java .awt .*;
5+ import java .awt .BorderLayout ;
6+ import java .awt .Desktop ;
7+ import java .awt .Dimension ;
8+ import java .awt .FlowLayout ;
9+ import java .awt .event .WindowAdapter ;
10+ import java .awt .event .WindowEvent ;
611import java .io .File ;
712import java .io .IOException ;
813import java .nio .charset .StandardCharsets ;
914import java .nio .file .Files ;
1015import java .text .DecimalFormat ;
1116import java .util .Set ;
12- import javax .swing .*;
17+ import javax .swing .BorderFactory ;
18+ import javax .swing .Box ;
19+ import javax .swing .BoxLayout ;
20+ import javax .swing .ImageIcon ;
21+ import javax .swing .JButton ;
22+ import javax .swing .JFrame ;
23+ import javax .swing .JLabel ;
24+ import javax .swing .JOptionPane ;
25+ import javax .swing .JPanel ;
26+ import javax .swing .JScrollPane ;
1327
1428public class AssetViewerFrame extends JFrame {
1529
@@ -41,10 +55,12 @@ public class AssetViewerFrame extends JFrame {
4155 Set .of (
4256 "png" , "jpg" , "jpeg" , "gif" , "tga" , "bmp" , "webp" , "svg" , "ico" , "avif" , "tiff" , "tif" );
4357 private static final Set <String > MEDIA_EXTENSIONS = Set .of ("mp4" , "mov" , "wav" , "mp3" , "ogg" );
58+ private static final Set <String > PDF_EXTENSIONS = Set .of ("pdf" );
4459 private static final DecimalFormat FILE_SIZE_FORMAT = new DecimalFormat ("#,##0.0 KB" );
4560
4661 private final PackageManager packageManager ;
4762 private final Runnable onSaveCallback ;
63+ private PdfViewerPanel pdfPanel ;
4864
4965 public AssetViewerFrame (
5066 JFrame owner , UnityAsset asset , PackageManager packageManager , Runnable onSaveCallback ) {
@@ -59,32 +75,43 @@ public AssetViewerFrame(
5975
6076 JPanel contentPanel = createContentPanel (asset );
6177 if (contentPanel == null ) {
62- dispose (); // Frame was closed by media handler
78+ dispose ();
6379 return ;
6480 }
6581
6682 add (contentPanel , BorderLayout .CENTER );
6783 add (createFooterPanel (asset ), BorderLayout .SOUTH );
84+
85+ addWindowListener (
86+ new WindowAdapter () {
87+ @ Override
88+ public void windowClosed (WindowEvent e ) {
89+ if (pdfPanel != null ) {
90+ try {
91+ pdfPanel .close ();
92+ } catch (IOException ex ) {
93+ System .err .println ("Failed to close PDF document: " + ex .getMessage ());
94+ }
95+ }
96+ }
97+ });
6898 }
6999
70100 private JPanel createFooterPanel (UnityAsset asset ) {
71101 JPanel footer = new JPanel ();
72102 footer .setLayout (new BoxLayout (footer , BoxLayout .X_AXIS ));
73103 footer .setBorder (BorderFactory .createEmptyBorder (4 , 8 , 4 , 8 ));
74104
75- // Path
76105 JLabel pathLabel = new JLabel (asset .assetPath ());
77- pathLabel .setToolTipText (asset .assetPath ()); // Show full path on hover
106+ pathLabel .setToolTipText (asset .assetPath ());
78107
79- // Size
80108 String size = "N/A (Directory)" ;
81109 if (asset .content () != null ) {
82110 double sizeInKb = asset .content ().length / 1024.0 ;
83111 size = FILE_SIZE_FORMAT .format (sizeInKb );
84112 }
85113 JLabel sizeLabel = new JLabel (size );
86114
87- // GUID
88115 JLabel guidLabel = new JLabel ("GUID: " + asset .guid ());
89116
90117 footer .add (pathLabel );
@@ -109,21 +136,29 @@ private JPanel createContentPanel(UnityAsset asset) {
109136 return createTextEditorPanel (asset );
110137 }
111138
112- JPanel panel = new JPanel (new BorderLayout ());
113- panel .setBorder (BorderFactory .createEmptyBorder (10 , 10 , 10 , 10 ));
139+ JPanel contentWrapperPanel = new JPanel (new BorderLayout ());
114140
115141 if (IMAGE_EXTENSIONS .contains (extension )) {
116142 ImageIcon imageIcon = new ImageIcon (asset .content ());
117143 JLabel imageLabel = new JLabel (imageIcon );
118- panel .add (new JScrollPane (imageLabel ), BorderLayout .CENTER );
144+ contentWrapperPanel .add (new JScrollPane (imageLabel ), BorderLayout .CENTER );
145+ } else if (PDF_EXTENSIONS .contains (extension )) {
146+ try {
147+ this .pdfPanel = new PdfViewerPanel (asset .content ());
148+ contentWrapperPanel .add (this .pdfPanel , BorderLayout .CENTER );
149+ } catch (IOException e ) {
150+ JLabel errorLabel = new JLabel ("Failed to load PDF: " + e .getMessage ());
151+ errorLabel .setHorizontalAlignment (JLabel .CENTER );
152+ contentWrapperPanel .add (errorLabel , BorderLayout .CENTER );
153+ }
119154 } else if (MEDIA_EXTENSIONS .contains (extension )) {
120155 handleMediaAsset (asset );
121156 return null ;
122157 } else {
123- panel .add (new JLabel ("Binary content cannot be previewed." ), BorderLayout .CENTER );
158+ contentWrapperPanel .add (
159+ new JLabel ("Binary content cannot be previewed." ), BorderLayout .CENTER );
124160 }
125-
126- return panel ;
161+ return contentWrapperPanel ;
127162 }
128163
129164 private JPanel createTextEditorPanel (UnityAsset asset ) {
@@ -146,7 +181,7 @@ private JPanel createTextEditorPanel(UnityAsset asset) {
146181 e -> {
147182 byte [] newContent = syntaxTextPanel .getText ().getBytes (StandardCharsets .UTF_8 );
148183 packageManager .updateAssetContent (asset .assetPath (), newContent );
149- syntaxTextPanel .markAsSaved (); // Reset the dirty state
184+ syntaxTextPanel .markAsSaved ();
150185 onSaveCallback .run ();
151186 });
152187
0 commit comments