88 * it under the terms of the GNU General Public License as
99 * published by the Free Software Foundation, either version 3 of the
1010 * License, or (at your option) any later version.
11- *
11+ *
1212 * This program is distributed in the hope that it will be useful,
1313 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1414 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1515 * GNU General Public License for more details.
16- *
16+ *
1717 * You should have received a copy of the GNU General Public
1818 * License along with this program. If not, see
1919 * <http://www.gnu.org/licenses/gpl-3.0.html>.
2323
2424import static fiji .plugin .trackmate .gui .Fonts .SMALL_FONT ;
2525import static fiji .plugin .trackmate .gui .Icons .ADD_ICON ;
26- import static fiji .plugin .trackmate .gui .Icons .REMOVE_ICON ;
26+ import static fiji .plugin .trackmate .gui .Icons .BIN_CLOSED_ICON ;
2727
2828import java .awt .BorderLayout ;
29- import java .awt .Component ;
3029import java .awt .FlowLayout ;
30+ import java .awt .GridBagConstraints ;
31+ import java .awt .GridBagLayout ;
3132import java .awt .datatransfer .DataFlavor ;
3233import java .awt .dnd .DnDConstants ;
3334import java .awt .dnd .DropTarget ;
3435import java .awt .dnd .DropTargetDropEvent ;
3536import java .awt .event .FocusAdapter ;
3637import java .io .File ;
37- import java .util .ArrayList ;
3838import java .util .List ;
39+ import java .util .function .Consumer ;
3940import java .util .stream .Collectors ;
4041
4142import javax .swing .BorderFactory ;
5758public class FileListPanel extends JPanel
5859{
5960
60- private final List < FileBoxPanel > fileBoxes = new ArrayList <>();
61-
6261 private final EverythingDisablerAndReenabler enabler ;
6362
64- private final Runnable refresher ;
65-
6663 private final JPanel mainPanel ;
6764
6865 private final JPanel buttonPanel ;
6966
67+ private final FileListModel model ;
68+
7069 public FileListPanel ( final FileListModel model )
7170 {
71+ this .model = model ;
72+ model .listeners ().add ( this ::refresh );
7273 this .enabler = new EverythingDisablerAndReenabler ( this , new Class [] { JLabel .class } );
73- this .refresher = new Runnable ()
74- {
75- @ Override
76- public void run ()
77- {
78- final List < String > strs = new ArrayList <>( fileBoxes .size () );
79- for ( final FileBoxPanel fb : fileBoxes )
80- {
81- final String str = fb .tfStr .getText ();
82- strs .add ( str );
83- }
84- model .setAll ( strs );
85- }
86- };
8774 setLayout ( new BorderLayout ( 0 , 0 ) );
8875
8976 final JScrollPane scrollPane = new JScrollPane ();
@@ -94,9 +81,7 @@ public void run()
9481 scrollPane .setBorder ( null );
9582 scrollPane .getVerticalScrollBar ().setUnitIncrement ( 16 );
9683
97- mainPanel = new JPanel ();
98- final BoxLayout jPanelAllThresholdsLayout = new BoxLayout ( mainPanel , BoxLayout .Y_AXIS );
99- mainPanel .setLayout ( jPanelAllThresholdsLayout );
84+ mainPanel = new JPanel ( new GridBagLayout () );
10085 scrollPane .setViewportView ( mainPanel );
10186
10287 final JButton btnAdd = new JButton ();
@@ -107,76 +92,55 @@ public void run()
10792 buttonPanel = new JPanel ( new FlowLayout ( FlowLayout .LEFT ) );
10893 buttonPanel .add ( btnAdd );
10994
110- /*
111- * Default values.
112- */
113-
114- mainPanel .add ( buttonPanel );
115- for ( final String string : model .getList () )
116- addFileBox ( string );
117- if ( fileBoxes .size () > 1 )
118- fileBoxes .forEach ( sp -> sp .btnRemove .setVisible ( true ) );
119- else if ( fileBoxes .size () > 0 )
120- fileBoxes .get ( 0 ).btnRemove .setVisible ( false );
121-
12295 /*
12396 * Listeners & co.
12497 */
12598
126- btnAdd .addActionListener ( e -> addFileBox ( ) );
99+ btnAdd .addActionListener ( e -> model . add ( System . getProperty ( "user.home" ) ) );
127100 setDropTarget ( new AddFilesDropTarget () );
101+ refresh ();
128102 }
129103
130- public void addFileBox ()
104+ /**
105+ * Refreshes the panel when the model changes.
106+ */
107+ private void refresh ()
131108 {
132- addFileBox ( System .getProperty ( "user.home" ) );
133- }
109+ mainPanel .removeAll ();
134110
135- private void addFileBox ( final String str )
136- {
137- final FileBoxPanel panel = new FileBoxPanel ( str ) ;
138- addFileBox ( panel ) ;
139- refresher . run () ;
140- }
111+ final GridBagConstraints gbc = new GridBagConstraints ();
112+ gbc . gridx = 0 ;
113+ gbc . gridy = 0 ;
114+ gbc . anchor = GridBagConstraints . NORTHWEST ;
115+ gbc . fill = GridBagConstraints . HORIZONTAL ;
116+ gbc . weightx = 1.0 ;
141117
142- private void addFileBoxes ( final List < String > files )
143- {
144- for ( final String str : files )
118+ mainPanel .add ( buttonPanel , gbc );
119+
120+ final List < String > list = model .getList ();
121+ for ( int i = 0 ; i < list .size (); i ++ )
145122 {
146- final FileBoxPanel panel = new FileBoxPanel ( str );
147- addFileBox ( panel );
123+ final String str = list .get ( i );
124+ final int index = i ;
125+ final FileBoxPanel panel = new FileBoxPanel ( str , ( s ) -> model .set ( index , s ) );
126+ panel .btnRemove .addActionListener ( e -> model .remove ( index ) );
127+ if ( list .size () > 1 )
128+ panel .btnRemove .setVisible ( true );
129+ else if ( list .size () == 1 && i == 0 )
130+ panel .btnRemove .setVisible ( false );
131+
132+ gbc .gridy ++;
133+ mainPanel .add ( Box .createVerticalStrut ( 5 ), gbc );
134+ gbc .gridy ++;
135+ mainPanel .add ( panel , gbc );
148136 }
149- refresher .run ();
150- }
151-
152- private void addFileBox ( final FileBoxPanel panel )
153- {
154- mainPanel .remove ( buttonPanel );
155-
156- final Component strut = Box .createVerticalStrut ( 5 );
157- fileBoxes .add ( panel );
158- mainPanel .add ( panel );
159- mainPanel .add ( strut );
160- mainPanel .add ( buttonPanel );
161-
162- if ( fileBoxes .size () > 1 )
163- fileBoxes .forEach ( sp -> sp .btnRemove .setVisible ( true ) );
164137
165- panel .btnRemove .addActionListener ( e -> removeStringPanel ( panel , strut ) );
166- mainPanel .revalidate ();
167- }
168-
169- private void removeStringPanel ( final FileBoxPanel stringPanel , final Component strut )
170- {
171- fileBoxes .remove ( stringPanel );
138+ gbc .gridy ++;
139+ gbc .weighty = 1.0 ;
140+ mainPanel .add ( Box .createVerticalGlue (), gbc );
172141
173- if ( fileBoxes .size () < 2 )
174- fileBoxes .forEach ( sp -> sp .btnRemove .setVisible ( false ) );
175- mainPanel .remove ( strut );
176- mainPanel .remove ( stringPanel );
177142 mainPanel .revalidate ();
178143 mainPanel .repaint ();
179- refresher .run ();
180144 }
181145
182146 private static final long serialVersionUID = 1L ;
@@ -199,7 +163,7 @@ public synchronized void drop( final DropTargetDropEvent evt )
199163 @ SuppressWarnings ( "unchecked" )
200164 final List < File > droppedFiles = ( List < File > ) evt .getTransferable ().getTransferData ( DataFlavor .javaFileListFlavor );
201165 final List < String > list = droppedFiles .stream ().map ( File ::getAbsolutePath ).collect ( Collectors .toList () );
202- addFileBoxes ( list );
166+ model . addAll ( list );
203167 }
204168 catch ( final Exception ex )
205169 {
@@ -217,17 +181,23 @@ private class FileBoxPanel extends JPanel
217181
218182 private final JTextField tfStr ;
219183
220- public FileBoxPanel ( final String str )
184+ private final Consumer < String > refresher ;
185+
186+ public FileBoxPanel ( final String str , final Consumer < String > refresher )
221187 {
222- setLayout ( new BoxLayout ( this , BoxLayout . X_AXIS ) ) ;
188+ this . refresher = refresher ;
223189
224- btnRemove = new JButton ();
190+ setLayout ( new BoxLayout ( this , BoxLayout .X_AXIS ) );
191+ btnRemove = new JButton ( BIN_CLOSED_ICON );
192+ final int w = 30 ;
193+ btnRemove .setPreferredSize ( new java .awt .Dimension ( w , w ) );
194+ btnRemove .setSize ( w , w );
195+ btnRemove .setMinimumSize ( new java .awt .Dimension ( w , w ) );
196+ btnRemove .setContentAreaFilled ( false );
197+ btnRemove .setBorderPainted ( false );
198+ btnRemove .setFocusPainted ( false );
199+ btnRemove .setOpaque ( false );
225200 add ( btnRemove );
226- btnRemove .setIcon ( REMOVE_ICON );
227- btnRemove .setFont ( SMALL_FONT );
228- btnRemove .setPreferredSize ( new java .awt .Dimension ( 24 , 24 ) );
229- btnRemove .setSize ( 24 , 24 );
230- btnRemove .setMinimumSize ( new java .awt .Dimension ( 24 , 24 ) );
231201
232202 add ( Box .createHorizontalStrut ( 5 ) );
233203 tfStr = new JTextField ( str );
@@ -240,20 +210,21 @@ public FileBoxPanel( final String str )
240210 btnBrowse .addActionListener ( e -> browse () );
241211 add ( btnBrowse );
242212
243- setMinimumSize ( new java .awt .Dimension ( 24 , 24 ) );
244- setPreferredSize ( new java .awt .Dimension ( 100 , 24 ) );
245- setMaximumSize ( new java .awt .Dimension ( 6000 , 30 ) );
213+ setMinimumSize ( new java .awt .Dimension ( w , w ) );
214+ setPreferredSize ( new java .awt .Dimension ( 100 , w ) );
215+ setMaximumSize ( new java .awt .Dimension ( 6000 , w ) );
246216 setBorder ( BorderFactory .createEmptyBorder ( 2 , 5 , 2 , 5 ) );
247217
248218 // Listeners.
249219 fiji .plugin .trackmate .gui .GuiUtils .selectAllOnFocus ( tfStr );
250- tfStr .addActionListener ( e -> refresher .run () );
220+
221+ tfStr .addActionListener ( e -> refresher .accept ( tfStr .getText () ) );
251222 final FocusAdapter fa = new FocusAdapter ()
252223 {
253224 @ Override
254225 public void focusLost ( final java .awt .event .FocusEvent e )
255226 {
256- refresher .run ( );
227+ refresher .accept ( tfStr . getText () );
257228 }
258229 };
259230 tfStr .addFocusListener ( fa );
@@ -274,7 +245,7 @@ private void browse()
274245 if ( file != null )
275246 {
276247 tfStr .setText ( file .getAbsolutePath () );
277- refresher .run ( );
248+ refresher .accept ( tfStr . getText () );
278249 }
279250 }
280251 finally
0 commit comments