17
17
import listfix .view .IListFixGui ;
18
18
import listfix .view .dialogs .*;
19
19
import listfix .view .support .IPlaylistModifiedListener ;
20
- import listfix . view . support . ImageIcons ;
20
+
21
21
import listfix .view .support .ProgressWorker ;
22
22
import listfix .view .support .ZebraJTable ;
23
23
import org .apache .commons .io .FilenameUtils ;
@@ -58,6 +58,7 @@ public class PlaylistEditCtrl extends JPanel
58
58
private final FolderChooser _destDirFileChooser = new FolderChooser ();
59
59
private Playlist _playlist ;
60
60
protected final IListFixGui listFixGui ;
61
+ private boolean refreshPending = false ;
61
62
62
63
private final IPlaylistModifiedListener listener = this ::onPlaylistModified ;
63
64
@@ -90,7 +91,25 @@ private void onPlaylistModified(Playlist list)
90
91
_btnPlay .setEnabled (_playlist != null );
91
92
_btnNextMissing .setEnabled (_playlist != null && _playlist .getMissingCount () > 0 );
92
93
_btnPrevMissing .setEnabled (_playlist != null && _playlist .getMissingCount () > 0 );
93
- getTableModel ().fireTableDataChanged ();
94
+ this .fireTableDataChanged ();
95
+ }
96
+
97
+ /**
98
+ * Call fireTableDataChanged() on the GUI thread, and do not call when a pending call is present
99
+ */
100
+ private void fireTableDataChanged () {
101
+ if (!refreshPending ) {
102
+ synchronized (this .playlistTableModel ) {
103
+ refreshPending = true ;
104
+ SwingUtilities .invokeLater (() -> {
105
+ synchronized (this .playlistTableModel )
106
+ {
107
+ refreshPending = false ;
108
+ }
109
+ getTableModel ().fireTableDataChanged ();
110
+ });
111
+ }
112
+ }
94
113
}
95
114
96
115
private void addItems ()
@@ -222,19 +241,19 @@ private void moveSelectedRowsDown()
222
241
}
223
242
224
243
/**
225
- * Locate missing files
244
+ * Repair playlist
226
245
* @return false if cancelled, otherwise true
227
246
*/
228
247
public boolean locateMissingFiles ()
229
248
{
230
249
_logger .debug (markerRepair , "Start locateMissingFiles()" );
231
- ProgressWorker <List <Integer >, String > worker = new ProgressWorker <>()
250
+ ProgressWorker <List <PlaylistEntry >, String > worker = new ProgressWorker <>()
232
251
{
233
252
@ Override
234
- protected List <Integer > doInBackground ()
253
+ protected List <PlaylistEntry > doInBackground ()
235
254
{
236
255
_logger .debug (markerRepairWorker , "Start repairing in background...." );
237
- List <Integer > result = _playlist .repair (PlaylistEditCtrl .this .getMediaLibrary (), this );
256
+ List <PlaylistEntry > result = _playlist .repair (PlaylistEditCtrl .this .getMediaLibrary (), this );
238
257
_logger .debug (markerRepairWorker , "Repair completed." );
239
258
return result ;
240
259
}
@@ -247,12 +266,13 @@ protected void done()
247
266
{
248
267
_logger .debug (markerRepair , "Updating UI-table..." );
249
268
_uiTable .clearSelection ();
250
- List < Integer > fixed = this . get ();
251
- for (Integer fixIx : fixed )
269
+
270
+ for (Integer fixIx : this . getIndexList ( this . get ()) )
252
271
{
253
272
int viewIx = _uiTable .convertRowIndexToView (fixIx );
254
273
_uiTable .addRowSelectionInterval (viewIx , viewIx );
255
274
}
275
+ playlistTableModel .fireTableDataChanged ();
256
276
_logger .debug (markerRepair , "Completed updating UI-table" );
257
277
}
258
278
catch (CancellationException | InterruptedException exception )
@@ -264,13 +284,29 @@ protected void done()
264
284
_logger .error (markerRepair , "Error processing missing files" , ex );
265
285
}
266
286
}
287
+
288
+ private List <Integer > getIndexList (List <PlaylistEntry > fixedEntries ) {
289
+ final List <Integer > fixedIndexes = new LinkedList <>();
290
+ final List <PlaylistEntry > copiedList = new LinkedList <>(fixedEntries );
291
+
292
+ // Lookup the playlist index of the fixed playlist entries
293
+ for (int fixIx = 0 ; fixIx < _playlist .size () && !copiedList .isEmpty (); ++fixIx ) {
294
+ if (_playlist .get (fixIx ) == copiedList .get (0 )) {
295
+ copiedList .remove (0 );
296
+ fixedIndexes .add (fixIx );
297
+ }
298
+ }
299
+ assert fixedIndexes .size () == fixedEntries .size ();
300
+ return fixedIndexes ;
301
+ }
267
302
};
268
303
269
304
ProgressDialog pd = new ProgressDialog (getParentFrame (), true , worker , "Repairing..." );
270
305
pd .setVisible (true ); // Wait until the worker completed
271
306
return !worker .isCancelled ();
272
307
}
273
308
309
+
274
310
private void reorderList ()
275
311
{
276
312
Playlist .SortIx sortIx = Playlist .SortIx .None ;
@@ -771,7 +807,8 @@ public void mouseClicked(MouseEvent evt)
771
807
_uiTableScrollPane .setBorder (BorderFactory .createEtchedBorder ());
772
808
773
809
_uiTable .setAutoCreateRowSorter (true );
774
- _uiTable .setModel (new PlaylistTableModel ());
810
+
811
+ _uiTable .setModel (playlistTableModel );
775
812
_uiTable .setDragEnabled (true );
776
813
_uiTable .setFillsViewportHeight (true );
777
814
_uiTable .setGridColor (new Color (153 , 153 , 153 ));
@@ -1113,6 +1150,7 @@ private void _miNewPlaylistFromSelectedActionPerformed()
1113
1150
private JMenuItem _miFindClosest ;
1114
1151
private JMenuItem _miReplace ;
1115
1152
private JPopupMenu _playlistEntryRightClickMenu ;
1153
+ private final PlaylistTableModel playlistTableModel = new PlaylistTableModel ();
1116
1154
private ZebraJTable _uiTable ;
1117
1155
private JScrollPane _uiTableScrollPane ;
1118
1156
@@ -1134,7 +1172,7 @@ public void setPlaylist(Playlist list, boolean force)
1134
1172
}
1135
1173
_playlist = list ;
1136
1174
1137
- (( PlaylistTableModel ) _uiTable . getModel ()). fireTableDataChanged ( );
1175
+ this . playlistTableModel . changePlaylist ( _playlist );
1138
1176
1139
1177
boolean hasPlaylist = _playlist != null ;
1140
1178
@@ -1695,96 +1733,6 @@ private void initFolderChooser()
1695
1733
_destDirFileChooser .setDialogTitle ("Choose a destination directory..." );
1696
1734
}
1697
1735
1698
- private class PlaylistTableModel extends AbstractTableModel
1699
- {
1700
- @ Override
1701
- public int getRowCount ()
1702
- {
1703
- if (_playlist != null )
1704
- {
1705
- return _playlist .size ();
1706
- }
1707
- else
1708
- {
1709
- return 0 ;
1710
- }
1711
- }
1712
-
1713
- @ Override
1714
- public int getColumnCount ()
1715
- {
1716
- return 4 ;
1717
- }
1718
-
1719
- @ Override
1720
- public Object getValueAt (int rowIndex , int columnIndex )
1721
- {
1722
- PlaylistEntry entry = _playlist .get (rowIndex );
1723
- switch (columnIndex )
1724
- {
1725
- case 0 ->
1726
- {
1727
- return rowIndex + 1 ;
1728
- }
1729
- case 1 ->
1730
- {
1731
- if (entry .isURL ())
1732
- {
1733
- return ImageIcons .IMG_URL ;
1734
- }
1735
- else if (entry .isFixed ())
1736
- {
1737
- return ImageIcons .IMG_FIXED ;
1738
- }
1739
- else if (entry .isFound ())
1740
- {
1741
- return ImageIcons .IMG_FOUND ;
1742
- }
1743
- else
1744
- {
1745
- return ImageIcons .IMG_MISSING ;
1746
- }
1747
- }
1748
- case 2 ->
1749
- {
1750
- return entry .getTrackFileName ();
1751
- }
1752
- case 3 ->
1753
- {
1754
- return entry .getTrackFolder ();
1755
- }
1756
- default ->
1757
- {
1758
- return null ;
1759
- }
1760
- }
1761
- }
1762
-
1763
- @ Override
1764
- public String getColumnName (int column )
1765
- {
1766
- return switch (column )
1767
- {
1768
- case 0 -> "#" ;
1769
- case 1 -> "" ;
1770
- case 2 -> "File Name" ;
1771
- case 3 -> "Location" ;
1772
- default -> null ;
1773
- };
1774
- }
1775
-
1776
- @ Override
1777
- public Class <?> getColumnClass (int columnIndex )
1778
- {
1779
- return switch (columnIndex )
1780
- {
1781
- case 0 -> Integer .class ;
1782
- case 1 -> ImageIcon .class ;
1783
- default -> Object .class ;
1784
- };
1785
- }
1786
- }
1787
-
1788
1736
private static class IntRenderer extends DefaultTableCellRenderer
1789
1737
{
1790
1738
IntRenderer ()
0 commit comments