From 1a3e8871a674e715850d78199c09c2f12dfc742c Mon Sep 17 00:00:00 2001 From: Kenneth van Ewijk Date: Thu, 26 Feb 2015 19:35:54 +0100 Subject: [PATCH] Added remove and edit capability. --- AddArtistPanel.java | 18 ++- AddStagePanel.java | 1 + EditArtistPanel.java | 163 ++++++++++++++++++++ EditEventPanel.java | 356 +++++++++++++++++++++++++++++++++++++++++++ EditStagePanel.java | 127 +++++++++++++++ PanelArtSta.java | 4 +- TabbedPane.java | 4 +- 7 files changed, 665 insertions(+), 8 deletions(-) create mode 100644 EditArtistPanel.java create mode 100644 EditEventPanel.java create mode 100644 EditStagePanel.java diff --git a/AddArtistPanel.java b/AddArtistPanel.java index 2fda7ce..39c02bb 100644 --- a/AddArtistPanel.java +++ b/AddArtistPanel.java @@ -22,7 +22,7 @@ public class AddArtistPanel extends JFrame{ setDefaultCloseOperation(HIDE_ON_CLOSE); JPanel content = new JPanel(new BorderLayout()); JPanel south = new JPanel(new FlowLayout()); - JPanel center = new JPanel(new GridLayout(4,2)); + JPanel center = new JPanel(new GridLayout(5,2)); content.add(south, BorderLayout.SOUTH); content.add(center, BorderLayout.CENTER); @@ -52,7 +52,7 @@ public class AddArtistPanel extends JFrame{ center.add(panel5); JPanel panel6 = new JPanel(); - JTextField imageTF = new JTextField("", 15); + JTextField imageTF = new JTextField("null", 15); panel6.add(imageTF); center.add(panel6); @@ -65,6 +65,16 @@ public class AddArtistPanel extends JFrame{ JTextField descriptionTF = new JTextField("", 15); panel8.add(descriptionTF); center.add(panel8); + + JPanel panel9 = new JPanel(); + JLabel background = new JLabel("Background: "); + panel9.add(background); + center.add(panel9); + + JPanel panel10 = new JPanel(); + JTextField backgroundTF = new JTextField("", 15); + panel10.add(backgroundTF); + center.add(panel10); @@ -78,6 +88,7 @@ public class AddArtistPanel extends JFrame{ String genre = genreTF.getText(); String image = imageTF.getText(); String description = descriptionTF.getText(); + String background = backgroundTF.getText(); boolean alreadyExists = false; for (Artist artist : agenda.getArtists()) @@ -92,11 +103,12 @@ public class AddArtistPanel extends JFrame{ } else if (alreadyExists == false) { - Artist a = new Artist(name,genre,image,description, description); + Artist a = new Artist(name,genre,image,description, background); agenda.addArtist(a); JOptionPane.showMessageDialog(null, "Artist added!"); setVisible(false); dispose(); + Window.updatePanel("art_sta"); } else { JOptionPane.showMessageDialog(null, "Choose a different artist name!"); } diff --git a/AddStagePanel.java b/AddStagePanel.java index df5eace..1b298cc 100644 --- a/AddStagePanel.java +++ b/AddStagePanel.java @@ -74,6 +74,7 @@ public class AddStagePanel extends JFrame{ JOptionPane.showMessageDialog(null, "Stage added!"); setVisible(false); dispose(); + Window.updatePanel("art_sta"); } else { JOptionPane.showMessageDialog(null, "Choose a different stage name!"); diff --git a/EditArtistPanel.java b/EditArtistPanel.java new file mode 100644 index 0000000..91e4cc8 --- /dev/null +++ b/EditArtistPanel.java @@ -0,0 +1,163 @@ +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Iterator; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; + + +public class EditArtistPanel extends JFrame{ + + private static final long serialVersionUID = 1; + + public EditArtistPanel(Agenda agenda, Artist art) + { + super("Artist editscreen!"); + setDefaultCloseOperation(HIDE_ON_CLOSE); + JPanel content = new JPanel(new BorderLayout()); + JPanel south = new JPanel(new FlowLayout()); + JPanel center = new JPanel(new GridLayout(5,2)); + content.add(south, BorderLayout.SOUTH); + content.add(center, BorderLayout.CENTER); + + JPanel panel1 = new JPanel(); + JLabel name = new JLabel("Artist name: "); + panel1.add(name); + center.add(panel1); + + JPanel panel2 = new JPanel(); + JTextField nameTF = new JTextField(art.getName(),15); + panel2.add(nameTF); + center.add(panel2); + + JLabel genre = new JLabel("Genre: "); + JPanel panel3 = new JPanel(); + panel3.add(genre); + center.add(panel3); + + JTextField genreTF = new JTextField(art.getGenre(),15); + JPanel panel4 = new JPanel(); + panel4.add(genreTF); + center.add(panel4); + + JPanel panel5 = new JPanel(); + JLabel image = new JLabel("Image: "); + panel5.add(image); + center.add(panel5); + + JPanel panel6 = new JPanel(); + JTextField imageTF = new JTextField("null", 15); + panel6.add(imageTF); + center.add(panel6); + + JPanel panel7 = new JPanel(); + JLabel description = new JLabel("Description: "); + panel7.add(description); + center.add(panel7); + + JPanel panel8 = new JPanel(); + JTextField descriptionTF = new JTextField(art.getDescription(), 15); + panel8.add(descriptionTF); + center.add(panel8); + + JPanel panel9 = new JPanel(); + JLabel background = new JLabel("Background: "); + panel9.add(background); + center.add(panel9); + + JPanel panel10 = new JPanel(); + JTextField backgroundTF = new JTextField(art.getBackground(), 15); + panel10.add(backgroundTF); + center.add(panel10); + + + + JButton edit = new JButton("Edit artist!"); + south.add(edit); + + edit.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) { + String name = nameTF.getText(); + String genre = genreTF.getText(); + String image = imageTF.getText(); + String description = descriptionTF.getText(); + String background = backgroundTF.getText(); + + boolean alreadyExists = false; + for (Artist artist : agenda.getArtists()) + { + if (artist.getName().equals(name)) + { + alreadyExists = true; + } + } + if (name.isEmpty() == true){ + JOptionPane.showMessageDialog(null, "Fill in a correct name!"); + } + else if (alreadyExists == false) + { + art.setName(name); + art.setGenre(genre); + art.setImageIconString(image); + art.setDescription(description); + art.setBackground(background); + JOptionPane.showMessageDialog(null, "Artist edited!"); + setVisible(false); + dispose(); + Window.updatePanel("art_sta"); + } else { + JOptionPane.showMessageDialog(null, "Choose a different artist name!"); + } + + } + }); + + JButton remove = new JButton("Remove artist!"); + for(Event e : agenda.getEvents()) + { + if(e.getArtist().equals(art)) + { + remove.setEnabled(false); + } + } + south.add(remove); + + remove.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) { + + if(JOptionPane.showConfirmDialog(null, "Are you sure you want to remove this artist?", "Remove Artist", JOptionPane.YES_NO_OPTION) == JOptionPane.OK_OPTION) + { + Iterator it = agenda.getArtists().iterator(); + while(it.hasNext()) + { + Artist a = it.next(); + if(a.equals(art)) + { + it.remove(); + } + } + + JOptionPane.showMessageDialog(null, "Artist removed!"); + setVisible(false); + dispose(); + Window.updatePanel("art_sta"); + } + } + }); + + + setContentPane(content); + setVisible(true); + setSize(500,320); + } + +} diff --git a/EditEventPanel.java b/EditEventPanel.java new file mode 100644 index 0000000..45a3ada --- /dev/null +++ b/EditEventPanel.java @@ -0,0 +1,356 @@ +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.GregorianCalendar; +import java.util.Iterator; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JTextField; +import javax.swing.SwingConstants; + + +public class EditEventPanel extends JFrame{ + + private static final long serialVersionUID = 1; + + public EditEventPanel(Agenda agenda, Event e) + { + super("Event editscreen!"); + setDefaultCloseOperation(HIDE_ON_CLOSE); + JPanel content = new JPanel(new BorderLayout()); + JPanel south = new JPanel(new FlowLayout()); + JPanel center = new JPanel(new GridLayout(7,2)); + content.add(south, BorderLayout.SOUTH); + content.add(center, BorderLayout.CENTER); + + + JPanel panel1 = new JPanel(); + JLabel name = new JLabel("Event name: "); + panel1.add(name); + center.add(panel1); + + JPanel panel2 = new JPanel(); + JTextField nameTF = new JTextField(e.getEventName(),15); + panel2.add(nameTF); + center.add(panel2); + + JLabel starttime = new JLabel("Starttime: "); + JPanel panel3 = new JPanel(); + panel3.add(starttime); + center.add(panel3); + + Integer[] hours = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 }; + JComboBox hour = new JComboBox(hours); + hour.setSelectedIndex(e.getStartDate().get(GregorianCalendar.HOUR_OF_DAY)); + JPanel panel4 = new JPanel(); + panel4.add(hour); + center.add(panel4); + + Integer[] minutes = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59}; + JComboBox minute = new JComboBox(minutes); + minute.setSelectedIndex(e.getStartDate().get(GregorianCalendar.MINUTE)); + panel4.add(minute); + panel4.add(new JSeparator(SwingConstants.VERTICAL)); + panel4.add(new JSeparator(SwingConstants.VERTICAL)); + + + Integer[] days = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; + JComboBox day = new JComboBox(days); + day.setSelectedIndex(e.getStartDate().get(GregorianCalendar.DAY_OF_MONTH) - 1); + panel4.add(day); + + String[] months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; + JComboBox month = new JComboBox(months); + month.setSelectedIndex(e.getStartDate().get(GregorianCalendar.MONTH)); + panel4.add(month); + + + Integer[] years = { 2015,2016,2017,2018}; + JComboBox year = new JComboBox(years); + year.setSelectedItem(e.getStartDate().get(GregorianCalendar.YEAR)); + panel4.add(year); + + + + JPanel panel5 = new JPanel(); + JLabel endtime = new JLabel("Endtime: "); + panel5.add(endtime); + center.add(panel5); + + JComboBox hourE = new JComboBox(hours); + hourE.setSelectedIndex(e.getEndDate().get(GregorianCalendar.HOUR_OF_DAY)); + JPanel panel6 = new JPanel(); + panel6.add(hourE); + center.add(panel6); + + JComboBox minuteE = new JComboBox(minutes); + minuteE.setSelectedIndex(e.getEndDate().get(GregorianCalendar.MINUTE)); + panel6.add(minuteE); + panel6.add(new JSeparator(SwingConstants.VERTICAL)); + panel6.add(new JSeparator(SwingConstants.VERTICAL)); + + + JComboBox dayE = new JComboBox(days); + dayE.setSelectedIndex(e.getEndDate().get(GregorianCalendar.DAY_OF_MONTH) - 1); + panel6.add(dayE); + + JComboBox monthE = new JComboBox(months); + monthE.setSelectedIndex(e.getEndDate().get(GregorianCalendar.MONTH)); + panel6.add(monthE); + + + JComboBox yearE = new JComboBox(years); + yearE.setSelectedItem(e.getEndDate().get(GregorianCalendar.YEAR)); + panel6.add(yearE); + + + JPanel panel7 = new JPanel(); + JLabel artist2 = new JLabel("Artist: "); + panel7.add(artist2); + center.add(panel7); + + JPanel panel8 = new JPanel(); + String[] artists = new String[agenda.getArtists().size()]; + int artistIndex = 0; + + for ( int idx = 0; idx < agenda.getArtists().size(); idx ++) + { + artists[idx] = agenda.getArtists().get(idx).getName(); + if(agenda.getArtists().get(idx).equals(e.getArtist())) + { + artistIndex = idx; + } + } + + JComboBox artist = new JComboBox(artists); + artist.setSelectedIndex(artistIndex); + panel8.add(artist); + center.add(panel8); + + JPanel panel9 = new JPanel(); + JLabel stage = new JLabel("Stage: "); + panel9.add(stage); + center.add(panel9); + + JPanel panel10 = new JPanel(); + String[] stages = new String[agenda.getStages().size()]; + + int stageIndex = 0; + + for ( int idx = 0; idx < agenda.getStages().size(); idx ++) + { + stages[idx] = agenda.getStages().get(idx).getName(); + if(agenda.getStages().get(idx).equals(e.getStage())) + { + stageIndex = idx; + } + } + + JComboBox stage2 = new JComboBox(stages); + stage2.setSelectedIndex(stageIndex); + panel10.add(stage2); + center.add(panel10); + + JPanel panel11 = new JPanel(); + JLabel description = new JLabel("Description: "); + panel11.add(description); + center.add(panel11); + + JPanel panel12 = new JPanel(); + JTextField descriptionTF = new JTextField(e.getDescription(),15); + panel12.add(descriptionTF); + center.add(panel12); + + JPanel panel13 = new JPanel(); + JLabel expectedPopularity = new JLabel("Expected Popularity: "); + panel13.add(expectedPopularity); + center.add(panel13); + + JPanel panel14 = new JPanel(); + Integer[] eps= { 1,2,3,4,5,6,7,8,9,10}; + JComboBox ep = new JComboBox(eps); + ep.setSelectedIndex(e.getExpectedPopularity() - 1); + panel14.add(ep); + center.add(panel14); + + + + + + JButton add = new JButton("Edit event!"); + south.add(add); + + add.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent f) { + boolean everythingCorrect = true; + String name = nameTF.getText(); + + int hourS = hour.getSelectedIndex(); + int minuteS = minute.getSelectedIndex(); + int dayS = day.getSelectedIndex() + 1; + String monthS = (String) month.getSelectedItem(); + int yearS = year.getSelectedIndex() + 2015; + + int hourEnd = hourE.getSelectedIndex(); + int minuteEnd = minuteE.getSelectedIndex(); + int dayEnd = dayE.getSelectedIndex() + 1; + String monthEnd = (String) monthE.getSelectedItem(); + int yearEnd = yearE.getSelectedIndex() + 2015; + + String artistName = (String)artist.getSelectedItem(); + + Artist artist = null; + + for(Artist a : agenda.getArtists()) + { + if (a.getName().equals(artistName)) + { + artist = a; + } + } + + String stageName = (String)stage2.getSelectedItem(); + + Stage stage = null; + + for(Stage s : agenda.getStages()) + { + if (s.getName().equals(stageName)) + { + stage = s; + } + } + + String description = descriptionTF.getText(); + + int popularity = ep.getSelectedIndex() + 1; + + if (dayS > monthDays(monthS)){ + everythingCorrect = false; + JOptionPane.showMessageDialog(null, "Invalid Date!"); + } + else if (yearS > yearEnd || monthToInt(monthS) > monthToInt(monthEnd) || dayS > dayEnd || hourS > hourEnd || minuteS > minuteEnd){ + everythingCorrect = false; + JOptionPane.showMessageDialog(null, "End time is earlier then start time!"); + } + else if (dayS != dayEnd || monthS.equals(monthEnd) == false || yearS != yearEnd){ + everythingCorrect = false; + JOptionPane.showMessageDialog(null, "Event is too long! It can't be longer than a single day."); + } else if (name.isEmpty()){ + everythingCorrect = false; + JOptionPane.showMessageDialog(null, "Fill in a correct name!"); + } else if (stage == null){ + everythingCorrect = false; + JOptionPane.showMessageDialog(null, "Missing a stage!"); + } else if (artist == null){ + JOptionPane.showMessageDialog(null, "Missing a artist!"); + } + + + if (everythingCorrect == true) + { + e.setEventName(name); + e.setDescription(description); + e.setExpectedPopularity(popularity); + e.setArtist(artist); + e.setStage(stage); + e.setStartDate(yearS, monthToInt(monthS), dayS, hourS, minuteS); + e.setEndDate(yearEnd, monthToInt(monthEnd), dayEnd, hourEnd, minuteEnd); + + everythingCorrect = false; + JOptionPane.showMessageDialog(null, "Event edited!"); + setVisible(false); + dispose(); + Window.updatePanel("table"); + } + + + } + }); + + JButton remove = new JButton("Remove event!"); + south.add(remove); + + remove.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) { + + if(JOptionPane.showConfirmDialog(null, "Are you sure you want to remove this event?", "Remove Event", JOptionPane.YES_NO_OPTION) == JOptionPane.OK_OPTION) + { + Iterator it = agenda.getEvents().iterator(); + while(it.hasNext()) + { + Event ev = it.next(); + if(ev.equals(e)) + { + it.remove(); + } + } + + JOptionPane.showMessageDialog(null, "Event removed!"); + setVisible(false); + dispose(); + Window.updatePanel("table"); + } + } + }); + + + setContentPane(content); + setVisible(true); + setSize(700,320); + + } + + public int monthToInt(String month) + { + int number = 0; + switch (month) + { + case "January": number = 1; break; + case "February": number = 2; break; + case "March": number = 3; break; + case "April": number = 4; break; + case "May": number = 5; break; + case "June":number = 6; break; + case "July": number = 7; break; + case "August": number = 8; break; + case "September":number = 9; break; + case "October": number = 10; break; + case "November": number = 11; break; + case "December": number = 12; break; + } + return number; + } + + public int monthDays(String month) + { + int number = 0; + switch (month) + { + case "January": number = 31; break; + case "February": number = 28; break; + case "March": number = 31; break; + case "April": number = 30; break; + case "May": number = 31; break; + case "June":number = 30; break; + case "July": number = 31; break; + case "August": number = 31; break; + case "September":number = 30; break; + case "October": number = 31; break; + case "November": number = 30; break; + case "December": number = 31; break; + } + return number; + } + +} diff --git a/EditStagePanel.java b/EditStagePanel.java new file mode 100644 index 0000000..9cdb32b --- /dev/null +++ b/EditStagePanel.java @@ -0,0 +1,127 @@ +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Iterator; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; + + +public class EditStagePanel extends JFrame{ + + private static final long serialVersionUID = 1; + + public EditStagePanel(Agenda agenda, Stage sta) + { + super("Stage editscreen!"); + setDefaultCloseOperation(HIDE_ON_CLOSE); + JPanel content = new JPanel(new BorderLayout()); + JPanel south = new JPanel(new FlowLayout()); + JPanel center = new JPanel(new GridLayout(2,2)); + content.add(south, BorderLayout.SOUTH); + content.add(center, BorderLayout.CENTER); + + JPanel panel1 = new JPanel(); + JLabel name = new JLabel("Stage name: "); + panel1.add(name); + center.add(panel1); + + JPanel panel2 = new JPanel(); + JTextField nameTF = new JTextField(sta.getName(),15); + panel2.add(nameTF); + center.add(panel2); + + JLabel description = new JLabel("Stage Description: "); + JPanel panel3 = new JPanel(); + panel3.add(description); + center.add(panel3); + + JTextField descriptionTF = new JTextField(sta.getDescription(),15); + JPanel panel4 = new JPanel(); + panel4.add(descriptionTF); + center.add(panel4); + + + JButton add = new JButton("Edit stage!"); + south.add(add); + + add.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) { + String name = nameTF.getText(); + String description = descriptionTF.getText(); + + boolean alreadyExists = false; + for (Stage stage : agenda.getStages()) + { + if (stage.getName().equals(name)) + { + alreadyExists = true; + } + } + if (name.isEmpty()){ + JOptionPane.showMessageDialog(null, "Fill in a correct name!"); + } + else if ( alreadyExists == false ) + { + sta.setName(name); + sta.setDescription(description); + JOptionPane.showMessageDialog(null, "Stage edited!"); + setVisible(false); + dispose(); + Window.updatePanel("art_sta"); + } + else { + JOptionPane.showMessageDialog(null, "Choose a different stage name!"); + } + + } + }); + + JButton remove = new JButton("Remove stage!"); + for(Event e : agenda.getEvents()) + { + if(e.getStage().equals(sta)) + { + remove.setEnabled(false); + } + } + south.add(remove); + + remove.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) { + + if(JOptionPane.showConfirmDialog(null, "Are you sure you want to remove this stage?", "Remove Stage", JOptionPane.YES_NO_OPTION) == JOptionPane.OK_OPTION) + { + Iterator it = agenda.getStages().iterator(); + while(it.hasNext()) + { + Stage s = it.next(); + if(s.equals(sta)) + { + it.remove(); + } + } + + JOptionPane.showMessageDialog(null, "Stage removed!"); + setVisible(false); + dispose(); + Window.updatePanel("art_sta"); + } + } + }); + + + setContentPane(content); + setVisible(true); + setSize(400,180); + } + +} diff --git a/PanelArtSta.java b/PanelArtSta.java index 87d308e..e12d0ce 100644 --- a/PanelArtSta.java +++ b/PanelArtSta.java @@ -34,7 +34,7 @@ public class PanelArtSta extends JPanel implements Panel{ if (artists.getSelectedIndex() == -1) { } else { - JOptionPane.showMessageDialog(null, "Artist Selected: " + a.getArtists().get(artists.getSelectedIndex())); + new EditArtistPanel(w.getAgenda(), a.getArtists().get(artists.getSelectedIndex())); artists.clearSelection(); } } @@ -54,7 +54,7 @@ public class PanelArtSta extends JPanel implements Panel{ if (stages.getSelectedIndex() == -1) { } else { - JOptionPane.showMessageDialog(null, "Stage Selected: " + a.getStages().get(stages.getSelectedIndex())); + new EditStagePanel(w.getAgenda(), a.getStages().get(stages.getSelectedIndex())); stages.clearSelection(); } } diff --git a/TabbedPane.java b/TabbedPane.java index bf01925..a8633ba 100644 --- a/TabbedPane.java +++ b/TabbedPane.java @@ -24,6 +24,4 @@ public class TabbedPane extends JFrame{ setSize(480, 410); setVisible(true); } -} -//"Event", new EventPanel("Introductie", "Hoofdpodium", "14:00-15:00", "Populair", "Paul Lindelauf", "25-02-2015", "Het begin van het festival, wordt gepresenteerd door Paul Lindelauf. En ik moet nog een hele hoop onzin toevoegen om dit goed te kunnen testen, dus daarom doe ik dat nu ook maar even. En nog een hele hoop informatie vanwege REDENEN. En waarom de fuck hij nu wel ineens normaal kan doen weet ik niet, maar zal dus maar voor de volgende keer onthouden minder onzin te typen." -//"Artist", new ArtistPanel("Paul Lindelauf", "Paultje Lindelauf

Paultje is de ster van de show en opent de voorstelling. Hierna komen de geweldige artiesten.

", "Achtergrondinformatie

Paul staat bekend als de man die zijn leerlingen treiterde met zijn diagrammen, leiderschap en Excel.", "src/content/Paul.jpg" \ No newline at end of file +} \ No newline at end of file