package uk.co.mmscomputing.device.phone; import java.io.*; import java.util.*; import java.text.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.table.*; import java.beans.*; import javax.swing.border.*; import uk.co.mmscomputing.util.*; public class PhoneAnswererPanel extends JPanel implements PhoneConstants,PhoneAnswererListener{ protected Properties properties; protected PhoneCallHandlerFactory handlerfactory; protected PhoneBook phonebook; private JTable table; private PhoneModel model=new PhoneModel(); private PhoneColumnModel columnmodel=new PhoneColumnModel(); public PhoneAnswererPanel( Properties properties, PhoneCallHandlerFactory handlerfactory, PhoneBook phonebook ){ this.properties=properties; this.handlerfactory=handlerfactory; this.phonebook=phonebook; setLayout(new BorderLayout()); table=new JTable(model,columnmodel); table.createDefaultColumnsFromModel(); table.getTableHeader().setReorderingAllowed(false); add(new JScrollPane(table),BorderLayout.CENTER); buildCallList(); table.addMouseListener(new MouseAdapter(){ public void mouseClicked(MouseEvent e){ if(e.isMetaDown()){ int selected=table.rowAtPoint(new Point(e.getX(),e.getY())); table.setRowSelectionInterval(selected, selected); if(e.getClickCount()==2){ deletePhoneCalls(); } }else if(e.isShiftDown()){ int selected=table.rowAtPoint(new Point(e.getX(),e.getY())); table.setRowSelectionInterval(selected, selected); if(e.getClickCount()==2){ updatePhoneBook(model.getRemote(selected)); } }else if(e.getClickCount()==2){ int selected=table.getSelectedRow(); if(selected==-1){return;} table.setRowSelectionInterval(selected,selected); playPhoneCall( model.getTime(selected), model.getLocal(selected), model.getRemote(selected), model.getFile(selected) ); } } }); } private void addPropertyChangeListener(String name){ Component parent=getParent(); while(parent!=null){ if(parent instanceof JTabbedPane){ JTabbedPane tp =(JTabbedPane)parent; int index=tp.indexOfTab(name); if(index!=-1){ Object tab=tp.getComponentAt(index); if(tab instanceof PropertyChangeListener){ PropertyChangeListener pcl=(PropertyChangeListener)tab; addPropertyChangeListener(pcl); return; } } } parent=parent.getParent(); } } protected void playPhoneCall(String time,String local,String remote,String fn){ // handled by sub class System.out.println("5\bPlay Sound File: "+fn); } private static boolean addedPhoneBookListener=false; protected void updatePhoneBook(String remote){ // handled by sub class if(!addedPhoneBookListener){ addedPhoneBookListener=true; addPropertyChangeListener("Phone Book"); } firePropertyChange("update", null, remote); // Call PhoneBookTab; (property name, old value , new value) } protected void deletePhoneCalls(){ int[] selected=table.getSelectedRows(); for(int i=selected.length-1; i>=0; i--){ ((PhoneModel)table.getModel()).delEntry(selected[i]); } table.revalidate(); } private int getPickUpTime(String localno){ try{ String[] localnos=properties.getProperty(phoneLocalNosID,"").split(","); if((localnos.length==1)&&(localnos[0].equals(""))){ try{ return Integer.parseInt(properties.getProperty(phoneTimeToWaitID)); }catch(Exception e){ System.out.println("3\b"+getClass().getName()+".update:\n\tCould not set pick up time.\n\t"+e); return 20; } } for(int i=0;i<localnos.length;i++){ if(localno.trim().equals(localnos[i])){ try{ return Integer.parseInt(properties.getProperty(phoneTimeToWaitID)); }catch(Exception e){ System.out.println("3\b"+getClass().getName()+".update:\n\tCould not set pick up time.\n\t"+e); return 20; } } } }catch(Exception e){ System.err.println(getClass().getName()+".getPickUpTime:\n\t"+e); e.printStackTrace(); } return -1; // ignore call } public void update(PhoneAnswererMetadata.Type type, PhoneAnswererMetadata md){ // PhoneAnswererListener: called by PhoneAnswerer try{ if(type.equals(PhoneAnswererMetadata.STATE)){ if(md.isState(phoneRinging)){ int waitforsecs = getPickUpTime(md.getLocalNo()); if(waitforsecs!=-1){ // if we accept that call. IndicationProgressMonitor pm; String rno=md.getRemoteNo(); pm=new IndicationProgressMonitor( md.getController(),rno,phonebook.getName(rno),waitforsecs*1000 ); md.setPickUpTime(waitforsecs,pm); try{ md.setALaw(properties.getProperty(phoneLawID).equals("true")); }catch(Exception e){ System.out.println("3\b"+getClass().getName()+".update:\n\tCould not speech coding constant.\n\t"+e); md.setALaw(true); } } }else if(md.isState(phoneConnected)){ PhoneCallHandler pch=handlerfactory.getHandler(properties); md.setHandler(pch); }else if(md.isState(phoneDisconnected)){ PhoneCallHandler pch=md.getHandler(); if(pch instanceof PhoneCallSaver){ String fn=((PhoneCallSaver)pch).getFile(); if(md.getChangedProtocol()){ if(fn!=null){ new File(fn).delete(); } }else{ if(fn!=null){ model.addEntry(parseFileName(new File(fn))); table.revalidate(); } } } } } }catch(Exception e){ System.out.println("9\b"+getClass().getName()+".update:\n\t"+e); e.printStackTrace(); } } private PhoneEntry parseFileName(File file){ String fn=file.getName(); fn=fn.substring(0,fn.indexOf('.')); String[] content=fn.split("_"); String date =(content.length>=1)?content[0]:"unknown"; String time =(content.length>=2)?content[1].replace('-',':'):"unknown"; String local =(content.length>=3)?content[2]:"unknown"; String remote=(content.length>=4)?content[3]:"withhold"; String name=phonebook.getName(remote); return new PhoneEntry(date+" "+time,local,remote,name,file.getAbsolutePath()); } protected void buildCallList(){ properties.setProperty(phoneFileDirID,properties.getProperty(phoneFileDirID,phoneDefaultPath)); String path=properties.getProperty(phoneFileDirID); String[] files=list(path,new fnf()); for(int i=0; i<files.length; i++){ File file=new File(path,files[i]); try{ model.addEntry(parseFileName(file)); }catch(Exception e){ System.out.println(getClass().getName()+".parseFileName:\n\t"+e); e.printStackTrace(); } } } private String[] list(String dir, FilenameFilter fnf){ String dirs[]=new java.io.File(dir).list(fnf); if(dirs==null){ return new String[0];} java.util.Arrays.sort(dirs); return dirs; } class fnf implements FilenameFilter{ public boolean accept(File dir, String s){ File f=new File(dir,s); return f.isFile()&&s.endsWith(".wav"); } } } class PhoneEntry{ static final int MAXCOL=5; static private String[] headers={"time","local no","remote no","remote name","file"}; private Object[] content=new Object[MAXCOL]; public PhoneEntry(String time, String localno, String remoteno, String name, String file){ content[0]=time; content[1]=localno; content[2]=remoteno; content[3]=name; content[4]=file; } public Object getColContent(int i){ return content[i];} static public String[] getHeaders(){ return headers;} } class PhoneColumnModel extends DefaultTableColumnModel{ public PhoneColumnModel(){super();} public void addColumn(TableColumn tc){ int index=getColumnCount(); switch(index){ case 0: tc.setMinWidth(150);tc.setMaxWidth(175);break; // time case 1: tc.setMinWidth(75);tc.setMaxWidth(100);break; // local case 2: tc.setMinWidth(120);tc.setMaxWidth(200);break; // remote case 3: tc.setMinWidth(200);tc.setMaxWidth(400);break; // name case 4: tc.setMinWidth(60);/*tc.setMaxWidth(200);*/break; // file } super.addColumn(tc); } } class PhoneModel extends AbstractTableModel{ private static final Class[] columnTypes=new Class[]{String.class,String.class,String.class,String.class,String.class}; private Vector entries=new Vector(); public Object getValueAt(int r,int c){ if(r<entries.size()){ PhoneEntry e=(PhoneEntry)entries.elementAt(r); return e.getColContent(c); } throw new IllegalArgumentException("Bad Cell ("+r+", "+c+")"); } public String getTime(int r){return (String)getValueAt(r,0);} public String getLocal(int r){return (String)getValueAt(r,1);} public String getRemote(int r){return (String)getValueAt(r,2);} public String getRemoteName(int r){return (String)getValueAt(r,3);} public String getFile(int r){return (String)getValueAt(r,4);} public void addEntry(PhoneEntry e){ entries.add(e);} public void delEntry(int index){ String filename=getFile(index); File file=new File(filename); Object[] options = { "YES", "NO" }; int action=JOptionPane.showOptionDialog( null, "<html><b>Do you really want to delete the following file ?</b><br> <br><i>" +file.getAbsolutePath()+"</i><br> </html>", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0] ); if(action==JOptionPane.YES_OPTION){ file.delete(); entries.remove(index); } } public int getColumnCount(){ return PhoneEntry.MAXCOL;} public int getRowCount(){ return entries.size();} public String getColumnName(int c){ return PhoneEntry.getHeaders()[c];} public Class getColumnClass(int c){ return columnTypes[c];} } class IndicationProgressMonitor extends uk.co.mmscomputing.concurrent.Timer implements uk.co.mmscomputing.concurrent.TimerListener{ JFrame dialog; JProgressBar progressBar; public IndicationProgressMonitor(int cntl,String remote,String name,int timeout){ super(timeout); setDelay(500); setListener(this); dialog=getDialog(cntl,remote,name); } public JFrame getDialog(int cntl,String remote,String name){ JPanel panel=new JPanel(); JPanel q=new JPanel(); q.setLayout(new BorderLayout()); Border border = q.getBorder(); Border margin = new EmptyBorder(10,10,5,10); q.setBorder(new CompoundBorder(border, margin)); q.add(new JLabel("Indication ["+cntl+"] from:"),BorderLayout.NORTH); JLabel img=new JLabel(new JarImageIcon(getClass(),"32x32/phone.png")); img.setBorder(new EmptyBorder(10,10,10,10)); q.add(img,BorderLayout.WEST); JLabel msg=new JLabel("<html><i>"+name+"</i><br>"+remote+"</html>"); msg.setBorder(new EmptyBorder(10,10,10,10)); q.add(msg,BorderLayout.CENTER); JPanel p=new JPanel(); p.setLayout(new BorderLayout()); progressBar = new JProgressBar(0,timeout); progressBar.setValue(0); progressBar.setIndeterminate(false); progressBar.setStringPainted(true); progressBar.setBorder(new EmptyBorder(5,0,5,0)); p.add(progressBar,BorderLayout.NORTH); JPanel buttons=new JPanel(); buttons.setLayout(new GridLayout(0,3)); buttons.add(new JPanel()); JButton button=new JButton( new AbstractAction("pick up"){ public void actionPerformed(ActionEvent ev){ release(); } } ); buttons.add(button); buttons.add(new JPanel()); p.add(buttons,BorderLayout.CENTER); q.add(p,BorderLayout.SOUTH); panel.setLayout(new BorderLayout()); panel.setOpaque(true); panel.add(q,BorderLayout.NORTH); JFrame dialog = new JFrame("Progress..."); dialog.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); dialog.setContentPane(panel); dialog.pack(); return dialog; } public void begin(int timeleft){ dialog.setLocationRelativeTo(null); dialog.toFront(); dialog.setVisible(true); } public void tick(int timeleft){ progressBar.setValue(timeout-timeleft); progressBar.setString("Pick up in "+timeleft+" ms"); } public void end(int timeleft){ dialog.dispose(); } }