package org.greenstone.gatherer.feedback; import java.io.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; import java.util.*; import java.net.*; import java.rmi.server.*; import javax.imageio.*; import java.util.Locale; import java.util.ResourceBundle; import java.text.MessageFormat; import com.sun.image.codec.jpeg.*; import javax.swing.Timer; import org.greenstone.gatherer.util.Utility; /** * This class will show the FeedbackInterface form. * It will allow user to described about the problem better.Here we will also take some more information available * in the system such as the size of the memory available and the screen size.User also could take more screenshot * so they will be able to say the sequence of events that lead up to the problem. *
If the user don't want to send this form, then all the information taken from this form will be deleted * and user will be quitted from the Reporting Feedback sequence. * * @author Veronica Liesaputra */ public class FeedbackInterface extends JDialog implements ActionListener { /** * This is the button user need to pressed if they want to view the files. * This button will be disabled when the timer is running and finish = false. */ private JButton view_button; /** * This button means that the user finished give the information and * want to send it. */ public JButton send_button; /** * This button means that the user don't want to send information and * back to normal application. * All the data taken start from user choose to start doing the Feedback sequence * up to this point will be delete. */ private JButton notsend_button; /** * This is the text area where user can explain more about the problem. */ private JTextArea problem_details; /** * This is the combo box that allow user to specify the poblem type. */ private JComboBox problem_type; /** * This is the combo box that allow user to specify the urgency of the problem. */ private JComboBox problem_urgency; /** * This combo box will ask whether or not user want to send the screenshot. */ private JComboBox problem_screenshot; /** * This text field allow user to type the smtp address of their email that * they want this application to use to send all the data. * If they don't fill this field then it will set to the same * smtp adress of where the data will be send to. */ private JTextField smtp_address; /** * This text field allow user to type the email adress that they want this * application to use to send all the data. * If they don't fill this field then it will set to the same email * adress of where the data will be send to. */ private JTextField email_address; /** * This is the name of the window the user lastly used. * This is the name of the window where the user called to start the Feedback * sequence. */ private String frameName; /** * This is the unique code generated for each time user start doing the Feedback * sequence. * This code will be used as reference to which feedback that the user send. */ private static String code; /** * This is the date when the user start open this FeedbackInterface form. */ private Date curr_date; /** * This is the special listener class that record all the action user did in application. */ private static ActionRecorderDialog dialog; /** * This variable will hold the resource of the words that is stored in Messages.properties file. * The calling using messages.getString(someString) will caused someString to be translated * into some other string that is hold in that file.usually it will caused it to be translated * to the language that the user use or choose to have as stated in Locale. */ private static ResourceBundle messages; /** * This is the screen shot instance that will allow the application to take screen shot of the whole * screen or only the window that the user currently doing their action. */ private ScreenShot screen; /** * This is the thread that allows the encoding of the image file to String and the saving of image to * a jpeg file happens concurrently. */ private Thread save; /** * This is the hashmap that hold the screen shot and the panel where the screenshot is held. */ private HashMap picAndPane; /** * This is the panel that hold all the panels containing the screenshots taken. */ private JPanel picture_scroll; /** * This is how many rows of screenshots panel displayed at the moment. */ private int row; /** * This is the array list that hold all the screenshots panel displayed. */ private ArrayList paneArray; /** * This button will remove the last screenshot panels. */ private JButton remove; /** * This is a reference to feedback interface displayed at the moment. */ private FeedbackInterface frame; /** * This is the thread to send all the xml files back to the developer. */ private Thread sendThread; /** * This is the flag to tell whether or not the sending files finished or not. * It is also flag to tell whether or not the viewing files finished or not. */ private static boolean finish; /** * This is the timer to displayed the progress bar to tell user to wait while * we sending the files or while we generate the xml files to be viewed. * If finish = false then wait cursor,progress bar and wait label will be displayed. * If finish = true then default cursor will be displayed. */ private Timer timer; /** * Progress bar displayed when user sending or want to view details. */ private JProgressBar progressBar; /** * Label displayed to tell user to wait for a while. */ private JLabel wait_lbl; /** * This is the background colour for the window. */ private Color bckcolor; /** * This is the panel to displayed all descriptions panel. */ private JPanel tempPane; /** * This is the thread that will be running when user pressed the preview button. * This thread will show the 6 xml files that are going to be send. It will run concurrently * with the timer, if value of finish = true, this thread will be null-ed. */ private Thread prevThread; /** * This is the flag to say whether or not this window should be dispose when timer is stop * and finish = true. * If selected = true then this window should be dispose, otherwise don't dispose it. */ private boolean selected = false; /** * This is a blocker to say that user cannot do anything while waiting. */ private MouseListener mouse_blocker_listener = new MouseAdapter() {}; /** * Will make a dialog window that allows people to write more about the problem that want * to send. * This is the GUI for user to write on Feedback form. It is also setting the up the appropriate * data member with the value passed on to this constructor. * (Precondition: (sh != null) && (dlg != null) && (msg != null)) * @param sh an instance of ScreenShot that will allow application to take screenshot. * @param frame_name name of the window where user called Feedback form from. * @param msg holding the resource of the words that is stored in Messages.properties file. * @param dlg holding the special listener. */ public FeedbackInterface(ScreenShot sh,String frame_name, ResourceBundle msg,ActionRecorderDialog dlg) { super(); frame = this; bckcolor = new Color(176,209,217); picAndPane = new HashMap(); messages = msg; frameName = frame_name; dialog = dlg; FeedbackInterface.setDefaultLookAndFeelDecorated(true); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); setTitle(messages.getString("SendFeedbackForm")); screen = sh; Container container; container = getContentPane(); createUI(container); curr_date = new Date(); Toolkit kit; kit = Toolkit.getDefaultToolkit(); Dimension screenSize; screenSize = kit.getScreenSize(); int screenHeight; screenHeight = screenSize.height; int screenWidth; screenWidth = screenSize.width; Dimension size; size = this.getSize(); setLocation((screenWidth - size.width - 500) , (screenHeight - size.height - 700)); setBackground(bckcolor); pack(); setModal(false); setVisible(true); } /** * This method is setting up the content pane for the Feedback form window. * (Precondition: (window != null)) * @param window the content pane of Feedback form window. */ public void createUI(Container window) { JPanel container; container = new JPanel(); container.setBackground(bckcolor); container.setLayout(new BoxLayout(container,BoxLayout.PAGE_AXIS)); String opening_text; opening_text = messages.getString("FeedbackOpeningText"); JTextArea textArea; textArea = new JTextArea(opening_text); textArea.setMinimumSize(new Dimension(100,100)); textArea.setOpaque(false); textArea.setEditable(false); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); textArea.setBorder(new EmptyBorder(10,10,0,10)); textArea.setBackground(bckcolor); container.add(textArea); tempPane = new JPanel(); tempPane.setLayout(new BorderLayout()); tempPane.setBackground(new Color(176,208,176)); paneArray = new ArrayList(); picture_scroll = new JPanel(); row = 1; picture_scroll.setLayout(new GridLayout(0,1)); picture_scroll.setBackground(new Color(176,208,176)); tempPane.add(picture_scroll,BorderLayout.PAGE_START); JPanel btnPanel; btnPanel = new JPanel(); btnPanel.setBackground(new Color(176,208,176)); remove = new JButton("Remove"); remove.setActionCommand("Remove"); remove.addActionListener(new ActionListener () { public void actionPerformed(ActionEvent e) { Object obj; JPanel pane; if (paneArray.size() == 0) System.out.println("There is no panel here!!"); else { pane = (JPanel) paneArray.get((row - 2)); obj = picAndPane.get(pane); obj = null; picAndPane.remove(pane); paneArray.remove((row - 2)); if (paneArray.size() == 0) remove.setVisible(false); picture_scroll.remove(pane); row--; picture_scroll.setSize(picture_scroll.getPreferredSize()); picture_scroll.revalidate(); picture_scroll.repaint(); tempPane.setSize(tempPane.getPreferredSize()); tempPane.revalidate(); tempPane.repaint(); } } }); remove.setToolTipText("Remove last thumbnail"); remove.setBackground(new Color(176,208,176)); remove.setVisible(false); btnPanel.add(remove); tempPane.add(btnPanel,BorderLayout.PAGE_END); JScrollPane pict_scroll; pict_scroll = new JScrollPane(tempPane); pict_scroll.setBackground(bckcolor); pict_scroll.setPreferredSize(new Dimension(300,300)); pict_scroll.setBorder(new EmptyBorder(0,10,10,10)); container.add(pict_scroll); JPanel pane; pane = new JPanel(); pane.setBackground(bckcolor); pane.setLayout(new GridLayout(0,2)); pane.setBorder(new EmptyBorder(10,10,10,10)); JLabel txt_type; txt_type = new JLabel(messages.getString("Whatkindofproblemisit") + "? "); txt_type.setBackground(bckcolor); pane.add(txt_type); String [] type = {" ",messages.getString("ContentError"), messages.getString("ImageNotShow"), messages.getString("StrangeBehaviour"), messages.getString("SomethingUnexpectedHappen"), messages.getString("HardToUse"), messages.getString("Other")}; problem_type = new JComboBox(type); problem_type.addActionListener(this); problem_type.setBackground(bckcolor); pane.add(problem_type); JLabel txt_urgent; txt_urgent = new JLabel(messages.getString("Howbadistheproblem")+"? "); txt_urgent.setBackground(bckcolor); pane.add(txt_urgent); String[] urgent = {" ",messages.getString("Critical"), messages.getString("Serious"), messages.getString("Medium"),messages.getString("Minor"), messages.getString("Trivial")}; problem_urgency = new JComboBox(urgent); problem_urgency.addActionListener(this); problem_urgency.setBackground(bckcolor); pane.add(problem_urgency); /*JLabel txt_screenshot; txt_screenshot= new JLabel(messages.getString("Doyouwanttosendthescreenshot") + "? "); txt_screenshot.setBackground(new Color(108,168,108)); pane.add(txt_screenshot); String[] screenshot = {messages.getString("Yes"), messages.getString("No")}; problem_screenshot = new JComboBox(screenshot); problem_screenshot.addActionListener(this); problem_screenshot.setBackground(new Color(108,168,108)); pane.add(problem_screenshot);*/ /*JLabel txt_smtp; txt_smtp = new JLabel(messages.getString("SMTPaddress") + "? "); txt_smtp.setBackground(new Color(176,208,176)); pane.add(txt_smtp); smtp_address = new JTextField(); smtp_address.setBackground(new Color(224,240,224)); pane.add(smtp_address);*/ /*JLabel txt_email; txt_email = new JLabel(messages.getString("Emailaddress") + "? "); txt_email.setBackground(new Color(176,208,176)); pane.add(txt_email); email_address = new JTextField(); email_address.setBackground(new Color(224,240,224)); pane.add(email_address);*/ JLabel empty; empty = new JLabel (" "); empty.setBackground(bckcolor); pane.add(empty); JLabel empty2; empty2 = new JLabel (" "); empty2.setBackground(bckcolor); pane.add(empty2); container.add(pane); JPanel panely; panely = new JPanel(); panely.setLayout(new GridLayout(0,3)); panely.setBackground(bckcolor); panely.setBorder(new EmptyBorder(new Insets(10,10,10,10))); view_button = new JButton("Details . . ."); view_button.setActionCommand(messages.getString("Preview")); view_button.addActionListener(this); view_button.setToolTipText(messages.getString("ConformationPreview")); view_button.setBackground(bckcolor); panely.add(view_button); send_button = new JButton(messages.getString("Send")); send_button.setActionCommand(messages.getString("Send")); send_button.addActionListener(this); send_button.setDefaultCapable(true); send_button.setToolTipText(messages.getString("FeedbackSendButton")); send_button.setBackground(bckcolor); panely.add(send_button); notsend_button = new JButton("Cancel"); notsend_button.setActionCommand(messages.getString("NotSend")); notsend_button.addActionListener(this); notsend_button.setToolTipText(messages.getString("FeedbackNotSendButton")); notsend_button.setBackground(bckcolor); panely.add(notsend_button); container.add(panely); //Align the left edges of the components. textArea.setAlignmentX(Component.LEFT_ALIGNMENT); pict_scroll.setAlignmentX(Component.LEFT_ALIGNMENT); pane.setAlignmentX(Component.LEFT_ALIGNMENT); panely.setAlignmentX(Component.LEFT_ALIGNMENT); String about; about = messages.getString("FeedbackAboutText"); JTextArea about_txt; about_txt = new JTextArea(about); about_txt.setEditable(false); about_txt.setLineWrap(true); about_txt.setWrapStyleWord(true); about_txt.setBackground(bckcolor); about_txt.setBorder(new EmptyBorder(10,10,10,10)); String privacy; privacy = messages.getString("FeedbackPrivacyText"); JTextArea privacy_txt; privacy_txt = new JTextArea(privacy); privacy_txt.setEditable(false); privacy_txt.setLineWrap(true); privacy_txt.setWrapStyleWord(true); privacy_txt.setBackground(bckcolor); privacy_txt.setBorder(new EmptyBorder(10,10,10,10)); JTabbedPane tab; tab = new JTabbedPane(); tab.setBackground(bckcolor); tab.addTab(messages.getString("Form"),container); tab.addTab(messages.getString("About"),about_txt); tab.addTab(messages.getString("Privacy"),privacy_txt); tab.setBorder(new EmptyBorder(5,5,5,5)); JPanel panelx; panelx = new JPanel(); panelx.setLayout(new BoxLayout(panelx,BoxLayout.PAGE_AXIS)); panelx.setBackground(bckcolor); panelx.setBorder(new EmptyBorder(new Insets(10,10,10,10))); wait_lbl = new JLabel(messages.getString("Pleasewait")); wait_lbl.setBackground(bckcolor); wait_lbl.setVisible(false); panelx.add(wait_lbl); progressBar = new JProgressBar (); progressBar.setBackground(bckcolor); progressBar.setVisible(false); panelx.add(progressBar); JLabel emp2; emp2 = new JLabel (" "); emp2.setBackground(bckcolor); panelx.add(emp2); wait_lbl.setAlignmentX(Component.CENTER_ALIGNMENT); progressBar.setAlignmentX(Component.CENTER_ALIGNMENT); emp2.setAlignmentX(Component.CENTER_ALIGNMENT); final String p1; final String p2; p1 = "Tab"; p2 = "ProgressBar"; final JPanel cards; cards = new JPanel(new CardLayout()); cards.setBackground(bckcolor); cards.add(tab,p1); cards.add(panelx,p2); window.add(cards); timer = new Timer(1000, new ActionListener() { public void actionPerformed(ActionEvent evt) { if (finish == true) { if (sendThread != null) { sendThread.interrupt(); sendThread = null; } if (prevThread != null) { prevThread.interrupt(); prevThread = null; } Component glass_pane; glass_pane = frame.getGlassPane(); glass_pane.setVisible(false); glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); glass_pane.removeMouseListener(mouse_blocker_listener); wait_lbl.setVisible(false); progressBar.setIndeterminate(false); progressBar.setVisible(false); frame.setTitle(messages.getString("SendFeedbackForm")); CardLayout cl = (CardLayout)(cards.getLayout()); cl.show(cards,p1); if (selected == true) frame.dispose(); timer.stop(); } else { Component glass_pane; glass_pane = frame.getGlassPane(); glass_pane.addMouseListener(mouse_blocker_listener); glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); glass_pane.setVisible(true); frame.setTitle("Please wait..."); CardLayout cl = (CardLayout)(cards.getLayout()); cl.show(cards,p2); wait_lbl.setVisible(true); progressBar.setIndeterminate(true); progressBar.setVisible(true); } } }); } /** * This method will set the finish variable values. * When the sending files is finished, the sending application will set the finish value to true. * @param fin whether or not the send files is finished. */ public static void setFinish (boolean fin) { finish = fin; } /** * This is the class to represent the whole panel that hold the screenshot and the comments * about the screenshot. */ private class ThumbnailPic implements Serializable { /** * This is the panel that hold a thumbnail for a screenshot and a comments text area. */ private JPanel picpane; /** * This hold the BufferedImages for the whole screen version of screenshot. */ private BufferedImage[] screenimages; /** * This hold the BufferedImages for the window version only. */ private BufferedImage[] windowimages; /** * This is the text area where user can enter their comments. */ private JTextArea problem_details; /** * This is a flag to tell us which image user wants to send.Its defaults value is false. * If iswindow = true then it means user wants to send the window version only. * If iswindow = false then it means user wants to send the whole screen version. */ private boolean iswindow; /** * This is the titles for the panel. * Usually this is the title of the window where user wants to do the screenshot. * If the title is more than 40 characters then we will trim it and add ... at the back of it. */ private String titles; /** * This is the width of the image user wants to send. */ private String iw; /** * This is the height of the image user wants to send. */ private String ih; /** * This is the x-coordinate where the window located inside the whole screen image. */ private int xcoord; /** * This is the y-coordinate where the window located inside the whole screen image. */ private int ycoord; /** * This is the width of the window inside the whole screen image. */ private int width; /** * This is the height of the window inside the whole screen image. */ private int height; /** * This is the constructor that will setup the panel that contains * a thumbnail screenshot and a comments text area. * @param image the whole screen screenshot image. * @param text the title for this pane. * @param x the x-coordinate of the window inside the whole screen image. * @param y the y-coordinate of the window inside the whole screen image. * @param w the width of the window inside the whole screen image. * @param h the height of the window inside the whole screen image. */ //public ThumbnailPic (BufferedImage screen,byte[] image,String text) public ThumbnailPic (BufferedImage image,String text,int x,int y,int w,int h) { xcoord = x; ycoord = y; width = w; height = h; iswindow = false; titles = text; screenimages = new BufferedImage[3]; windowimages = new BufferedImage[3]; //screenimages[0] = screen; screenimages[0] = image; screenimages[1] = null; screenimages[2] = null; windowimages[0] = null; windowimages[1] = null; windowimages[2] = null; addPanel(image); } /** * This method will setup the components inside the panel properly. * @param image the whole screen screenshot image. */ //public void addPanel (byte[] image) public void addPanel (BufferedImage image) { picpane = new JPanel(); picpane.setLayout(new BorderLayout()); final JButton picture; picture = new JButton(); int w; int h; w = (int) (150/2); h = (int) (150/2); iw = "" + image.getWidth(); ih = "" + image.getHeight(); ImageIcon thumbnail; thumbnail = new ImageIcon(image.getScaledInstance(w,h,Image.SCALE_SMOOTH)); picture.setIcon(thumbnail); picture.setText("Draw . . ."); picture.setActionCommand("Scribble"); picture.addActionListener(new ActionListener() { public void actionPerformed (ActionEvent e) { frame.addMouseListener(mouse_blocker_listener); frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); SelectPicture select; select = new SelectPicture(screenimages,windowimages,iswindow,problem_details.getText(),messages); frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); frame.removeMouseListener(mouse_blocker_listener); select.setWindowBounds(xcoord,ycoord,width,height); iswindow = select.getIsWindow(); screenimages[0] = select.getImage3(); screenimages[1] = select.getImage(); screenimages[2] = select.getImage2(); if (iswindow == true) { windowimages[0] = select.getWindowImage3(); windowimages[1] = select.getWindowImage(); windowimages[2] = select.getWindowImage2(); } else { windowimages[0] = null; windowimages[1] = null; windowimages[2] = null; } problem_details.setText(select.getDetails()); int w,h; w = (int) (150/2); h = (int) (150/2); ImageIcon thumbnail; if (iswindow == false) thumbnail = new ImageIcon(screenimages[1].getScaledInstance(w,h,Image.SCALE_SMOOTH)); else thumbnail = new ImageIcon(windowimages[1].getScaledInstance(w,h,Image.SCALE_SMOOTH)); picture.setIcon(thumbnail); if (select.getSendNow() == true) { ActionEvent evt; evt = new ActionEvent(send_button,ActionEvent.ACTION_PERFORMED,messages.getString("Send")); frame.actionPerformed(evt); } } }); picture.setToolTipText("Click if you want to draw on it"); picture.setMargin(new Insets(5,5,5,5)); picture.setVerticalTextPosition(AbstractButton.BOTTOM); picture.setHorizontalTextPosition(AbstractButton.CENTER); picture.setBackground(new Color(176,208,176)); picpane.add(picture,BorderLayout.LINE_START); JPanel txtPane; txtPane = new JPanel(new BorderLayout()); txtPane.setBackground(new Color(176,208,176)); txtPane.setBorder(new EmptyBorder(5,5,5,5)); JLabel lbldesc = new JLabel("Comments :"); lbldesc.setBackground(new Color(176,208,176)); txtPane.add(lbldesc,BorderLayout.PAGE_START); problem_details = new JTextArea(); problem_details.setWrapStyleWord(true); problem_details.setEditable(true); problem_details.setBackground(new Color(224,240,224)); JScrollPane scroll; scroll = new JScrollPane(problem_details); scroll.setBackground(new Color(176,208,176)); scroll.setPreferredSize(new Dimension(300,150)); txtPane.add(scroll,BorderLayout.LINE_START); picpane.setSize(new Dimension(150,150)); picpane.add(txtPane,BorderLayout.CENTER); } /** * This method will get the width of the image user wants to send. * @return the width of the image. */ public String getWidth() { if (iswindow == false) return "" + screenimages[0].getWidth(); else { return "" + windowimages[0].getWidth(); } } /** * This method will get the height of the image user wants to send. * @return the height of the image. */ public String getHeight() { if (iswindow == false) return "" + screenimages[0].getHeight(); else { return "" + windowimages[0].getHeight(); } } /** * This method will get the titles of this panel. * @return the panel's title. */ public String getTitles() { return titles; } /** * This method will get user comments inside the text area. * @return the user's comments. */ public String getProblemDetails () { String txt; txt = problem_details.getText(); if (txt == null) return " "; else return txt; } /** * This method will setting up the text inside the text area. * @param comments the text set to the text area. */ public void setComments (String comments) { problem_details.setText(comments); } /** * This method will get the image that user wants to send. * @return image going to be send. */ public BufferedImage[] getImages () { if (iswindow == false) return screenimages; else return windowimages; } /** * This method will get the non-scribble lines image that user wants to send. * @return the string representation of the non-scribble lines image. */ public String getScreenImage () { if (iswindow == false) return convert(screenimages[0]); else return convert(windowimages[1]); } /** * This method will get the scribble lines image that user wants to send. * @return the string representation of the scribble lines image. */ public String getScreenAndLineImage () { if (iswindow == false) { if (screenimages[1]!= null) return convert(screenimages[1]); else return convert(screenimages[0]); } else { if (windowimages[1]!= null) return convert(windowimages[1]); else return convert(windowimages[0]); } } /** * This method will get only scribble lines image that user wants to send. * @return the string representation of the only scribble lines image. */ public String getLineForScreenImage () { if (iswindow == false) { if (screenimages[2] != null) return convert(screenimages[2]); else return ""; } else { if (windowimages[2] != null) return convert(windowimages[2]); else return ""; } } /** * This method will get the panel that hold a thumbnail and a text area. * @return panel that represent the thumbnail and the text area. */ public JPanel getPanel() { return picpane; } } /** * This method will setting up the comments to be displayed inside the latest added panel. * So if the window where user wants to take the screenshot at the moment is a modal window * then it will setting the comments to ask user to close the window before they can enter * their comments there. * @param modal the modality of the window where user wants to take the screenshot. */ public void setComment (boolean modal) { if (paneArray.size() == 0) System.out.println("There is no panel here!!"); else { JPanel pane; pane = (JPanel) paneArray.get((row - 2)); ThumbnailPic obj; obj = (ThumbnailPic) picAndPane.get(pane); String text; if (modal == true) text = "Please close '" + obj.getTitles() + "' window \nbefore you can enter comments here."; else text = " "; obj.setComments(text); } } /** * This method will add a panel that contains the thumbnail button and the text area. * @param title the window's title. * @param image the whole screen image. * @param x the window's x-coordinate in the image. * @param y the window's y-coordinate in the image. * @param width the window's width in the image. * @param height the window's height in the image. */ //public void addScreenPanel (String title,BufferedImage screen,byte[] image) public void addScreenPanel (String title,BufferedImage image,int x,int y,int width,int height) { final JPanel pane; pane = new JPanel(); pane.setLayout(new BorderLayout()); pane.setBackground(new Color(176,208,176)); Border loweredetched; loweredetched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); String ttl; if (title.length() > 41) ttl = title.substring(0,40) + " . . . "; else ttl = title; TitledBorder border; border = BorderFactory.createTitledBorder(loweredetched, title); border.setTitleJustification(TitledBorder.LEFT); pane.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(5,5,5,5),border)); ThumbnailPic pic; //pic = new ThumbnailPic(screen,image,title); pic = new ThumbnailPic(image,title,x,y,width,height); picAndPane.put(pane,pic); pane.add(pic.getPanel(),BorderLayout.LINE_START); remove.setVisible(true); picture_scroll.add(pane); paneArray.add(pane); row++; picture_scroll.setSize(picture_scroll.getPreferredSize()); picture_scroll.revalidate(); picture_scroll.repaint(); tempPane.setSize(tempPane.getPreferredSize()); tempPane.revalidate(); tempPane.repaint(); } /** * This method will generate the unique code that will be used as the * reference number of the feedback that user are about to send. * @return the unique code. */ public String getPrevData () { try { UID id = new UID(); code = "" + InetAddress.getLocalHost().hashCode() + id.hashCode(); } catch (UnknownHostException exp) {} return code; } /** * This method allows another class to get the unique code that can be used as * the reference number of the feedback that user are about to send. * This method should be called only if * getPrevData() method already been called before.Otherwise it will return null. * @return the unique code */ public static String getCode() { return code; } /** * This method will encode BufferedImage into their String representation using * Base64 encoder. * (Precondition: (image != null)) * @param image is the image that we want to encode to String. */ public String convert (BufferedImage image) { String txt; txt = null; try { ByteArrayOutputStream stream = new ByteArrayOutputStream(); ImageIO.write(image,"jpeg",stream); byte[] bytes = stream.toByteArray(); txt = Base64.encodeBytes(bytes); } catch(IOException ex) {} return txt; } /** * This method is to make sure that there is no thread running at the moment. */ private void ensureEventThread() { if(SwingUtilities.isEventDispatchThread()) { return; } throw new RuntimeException(messages.getString("file")); } /** * This method will create all 6 xml files, jarred them into one file, deletes all xml files and * sending it. * The xml files for: *
1.The history & information of all the actions done and windows opened by the application * after user choose to start the sequence of sending feedback. *
2.The history of all the commands (actions) done by the user before choosing * after start the sequence of sending feedback. *
3.The informations we get from the feedback interface form period. *
will be getting from vector and the temp_feedbackhist.log file. * (Precondition: (sx != null) && (vector != null) && (err_array != null)) * @param sx the xml parser. * @param vector the vector that hold the history and information. * @param err_array the arrays of information we take from the feedback interface period. * @param imgFile the arrays of information we take from the panels inside feedback interface form. */ private void sendState (SaveToXML sx,Vector vector,String[] err_array,String[] imgFile) { String dirname; dirname = "xmlfeedback/"; File dir = new File("xmlfeedback"); if (dir.isDirectory() == false) dir.mkdir(); sx.saveFeedback(err_array,imgFile); sx.open(dirname + "feedbackcontent" + FeedbackInterface.getCode() + ".xml", "HISTORY"); SaveToXML sx2; sx2 = new SaveToXML(messages); sx2.open(dirname + "feedbackcommand" + FeedbackInterface.getCode() + ".xml", "COMMANDS"); for (int i = 0 ; i < vector.size() ; i++) { History log; log = (History) vector.get(i); log.sendXML(sx); log.sendXMLComm(sx2); } Vector stack; stack = getPrev_log(); if (stack != null) { for (int i = 0 ; i < stack.size() ; i++) { History log; log = (History) stack.get(i); log.sendXML(sx); log.sendXMLComm(sx2); } stack.removeAllElements(); System.gc(); stack = null; } sx2.close("COMMANDS"); sx.close("HISTORY"); getHistPrev_log(sx,sx2); ZipFile zip; zip = new ZipFile(); zip.sendZipXMLFile(); File f; f = new File (dirname + "feedback" + FeedbackInterface.getCode() + ".xml"); f.delete(); f = new File (dirname + "feedbackcontent" + FeedbackInterface.getCode() + ".xml"); f.delete(); f = new File (dirname + "feedbackcommand" + FeedbackInterface.getCode() + ".xml"); f.delete(); /*f = new File (dirname + "content" + FeedbackInterface.getCode() + ".xml"); f.delete();*/ f = new File (dirname + "command" + FeedbackInterface.getCode() + ".xml"); f.delete(); String[] args = new String[5]; args[0] = "vl6@cs.waikato.ac.nz"; args[1] = dirname + "Jar" + FeedbackInterface.getCode() + "File.jar"; args[4] = "lib/parser.jar"; args[2] = err_array[19]; args[3] = err_array[20]; SendHTTP sm = new SendHTTP(); //SendMail sm = new SendMail(); sm.sendMail(args,messages,FeedbackInterface.getCode()); } /** * This method will create the 2 xml files. * The xml files are: *
1.The history & information of all the actions done and windows opened by the application * before user choose to start the sequence of sending feedback. *
2.The history of all the commands (actions) done by the user before choosing * to start the sequence of sending feedback. *
The information will be getting from history.log file and the temp_history.log file. * (Precondition: (sx != null) && (sx2 != null)) * @param sx the xml parser for the history xml file. * @param sx2 the xml parser for the command xml file. */ private void getHistPrev_log(SaveToXML sx,SaveToXML sx2) { Vector stack = null; try { File f = new File("history.log"); if (f.exists() == true) { FileInputStream fis = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(fis); stack = (Vector) ois.readObject(); String dirname; dirname = "xmlfeedback/"; /*sx.open(dirname + "content" + FeedbackInterface.getCode() + ".xml", "HISTORY");*/ sx2.open(dirname + "command" + FeedbackInterface.getCode() + ".xml", "COMMANDS"); if (stack != null) { for (int i = 0 ; i < stack.size() ; i++) { History log; log = (History) stack.get(i); //log.sendXML(sx); log.sendXMLComm(sx2); } stack.removeAllElements(); System.gc(); stack = null; } stack = (Vector) ois.readObject(); if (stack != null) { for (int i = 0 ; i < stack.size() ; i++) { History log; log = (History) stack.get(i); //log.sendXML(sx); log.sendXMLComm(sx2); } stack.removeAllElements(); System.gc(); stack = null; } sx2.close("COMMANDS"); //sx.close("HISTORY"); ois.close(); } } catch (IOException exp) {exp.printStackTrace();} catch (ClassNotFoundException exp2) { System.out.println("class exp");} } /** * This method will get the Vector stored in temp_feedbackhist.log file. * @return the vector stored in temp_feedbackhist.log file. */ public Vector getPrev_log() { Vector stack = null; try { File f = new File("temp_feedbackhist.log"); if (f.exists() == true) { FileInputStream fis = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(fis); stack = (Vector) ois.readObject(); ois.close(); return stack; } else stack = null; } catch (IOException exp) {exp.printStackTrace();} catch (ClassNotFoundException exp2) { System.out.println("class exp");} return stack; } /** * This is the thread that will start when user click send button and it will * make 6 xml files,jarred them together into 1 jar file, deletes the 6 xml files and send it. * @param vector the vector stored the current actions history. * @param err_array the array that stored all the information took during feedback interface period. * @param imgFile the array of that stored all the information from all the panels inside feedback interface form. */ public void sendMethod (final Vector vector,final String err_array[], final String imgFile[]) { ensureEventThread(); Runnable sendRun; sendRun = new Runnable() { public void run () { finish = false; selected = true; SaveToXML sx; sx = new SaveToXML(messages); sendState(sx,vector,err_array,imgFile); finish = true; } }; sendThread = new Thread(sendRun); sendThread.start(); } /** * This method will called the window that will display the preview of all * the file going to be send. * @param vector the vector stored the current actions history. * @param err_array the array that stored all the information took during feedback interface period. * @param imgFile the array of that stored all the information from all the panels inside feedback interface form. */ public void viewMethod (final Vector vector,final String err_array[], final String imgFile[]) { ensureEventThread(); Runnable prevRun; prevRun = new Runnable() { public void run () { finish = false; selected = false; ReportDetails rd; rd = new ReportDetails(vector,err_array,imgFile,messages,true); finish = true; } }; prevThread = new Thread(prevRun); prevThread.start(); } /** * This method will save a BufferedImage to a jpeg file with the specified filename. * This method is a thread that will caused the thread save to be started and stop * if the saving process is finished. * (Precondition: (I != null)) * @param I is the BufferedImage that we want to save. * @param picScreen name of the jpeg file where we want to store the BufferedImage */ public void saveGraph(final BufferedImage I,final String picScreen) { ensureEventThread(); Runnable saveRun; saveRun = new Runnable () { public void run() { try { File file; file = new File(picScreen); FileOutputStream out; out = new FileOutputStream(file); JPEGImageEncoder encoder; encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param; param = encoder.getDefaultJPEGEncodeParam(I); param.setQuality(1.0f, false); encoder.setJPEGEncodeParam(param); encoder.encode(I); out.close(); save = null; } catch (Exception ex) {} } }; save = new Thread(saveRun); save.start(); } /** * This method will get all the informations from the all the panels inside the feedback interface form. * @return the arrays of information from all the panels. */ public String[] getimgFile() { String[] imgFile; imgFile = null; /*String answer; answer = (String) problem_screenshot.getSelectedItem(); if(answer == messages.getString("Yes")) {*/ if (paneArray.size() > 0) { imgFile = new String[(paneArray.size() * 10)]; int step; for (step = 0 ; step < (paneArray.size()*10) ; step=step+10) { JPanel pane; ThumbnailPic obj; pane = (JPanel) paneArray.get((step/10)); obj = (ThumbnailPic) picAndPane.get(pane); //obj.setSize(); String title; title = obj.getTitles(); imgFile[step+0] = title; imgFile[step+1] = obj.getScreenImage(); title = "Window" + pane.hashCode() + "File"; imgFile[step+2] = messages.getString("screen")+title+step+".jpg"; imgFile[step+3] = obj.getScreenAndLineImage(); imgFile[step+4] = messages.getString("ErrorLineAnd")+imgFile[step+2]; imgFile[step+5] = obj.getLineForScreenImage(); imgFile[step+6] = messages.getString("ErrorLineFor")+imgFile[step+2]; imgFile[step+7] = obj.getWidth(); imgFile[step+8] = obj.getHeight(); imgFile[step+9] = obj.getProblemDetails(); } } return imgFile; } /** * This method will get all the informations taken during feedback interface period, such as os version. * @return then arrays of informations. */ public String[] geterr_array() { String[] err_array; err_array = null; String os_name; os_name = System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch"); Date problem_date; String err_date,java_info,screen_res; problem_date = new Date(); err_date = problem_date.toString(); java_info = System.getProperty("java.vendor")+ " " + System.getProperty("java.class.version"); Dimension dim; dim = Toolkit.getDefaultToolkit().getScreenSize(); screen_res = "" + dim.width + "x" + dim.height; try { err_array = new String[24]; err_array[0] = code; err_array[1] = frameName; err_array[2] = ""; err_array[3] = (String) problem_type.getSelectedItem(); err_array[4] = (String) problem_urgency.getSelectedItem(); err_array[5] = System.getProperty("user.name"); err_array[6] = System.getProperty("user.home"); err_array[7] = System.getProperty("user.dir"); err_array[8] = curr_date.toString(); err_array[9] = err_date; err_array[10] = os_name; err_array[11] = java_info; err_array[12] = "" + Locale.getDefault(); err_array[13] = Utility.PROGRAM_NAME + " " + Utility.PROGRAM_VERSION; err_array[14] = InetAddress.getLocalHost().getHostName(); err_array[15] = InetAddress.getLocalHost().getHostAddress(); err_array[16] = screen_res; err_array[17] = ""; /*String test_txt; test_txt = smtp_address.getText(); if ((test_txt == null)||(test_txt.length() < 5))*/ err_array[19] = "mail.waikato.ac.nz"; /*else err_array[19] = test_txt; test_txt = email_address.getText(); if ((test_txt == null)||(test_txt.length() < 5))*/ err_array[20] = "vl6@cs.waikato.ac.nz"; //else //err_array[20] = test_txt; Runtime run; run = Runtime.getRuntime(); err_array[21] = formatFileSize(run.totalMemory()); err_array[22] = formatFileSize(run.maxMemory()); err_array[23] = formatFileSize(run.freeMemory()); } catch(UnknownHostException exp) {} return err_array; } /** * This method will format the file size given into more elegant form,e.g. 2KB * @param length the file size. * @return the more elegant string representations of the file size. */ public String formatFileSize(long length) { String BYTE_SUFFIX; BYTE_SUFFIX = " B"; long GIGABYTE; GIGABYTE = 1024000000l; String GIGABYTE_SUFFIX; GIGABYTE_SUFFIX = " GB"; long KILOBYTE; KILOBYTE = 1024l; String KILOBYTE_SUFFIX; KILOBYTE_SUFFIX = " KB"; long MEGABYTE; MEGABYTE = 1024000l; String MEGABYTE_SUFFIX; MEGABYTE_SUFFIX = " MB"; StringBuffer result; result = new StringBuffer(""); float number; number = 0f; String suffix; suffix = null; if(length >= GIGABYTE) { number = (float) length / (float) GIGABYTE; suffix = GIGABYTE_SUFFIX; } else if(length >= MEGABYTE) { number = (float) length / (float) MEGABYTE; suffix = MEGABYTE_SUFFIX; } else if(length >= KILOBYTE) { number = (float) length / (float) KILOBYTE; suffix = KILOBYTE_SUFFIX; } else { return length + BYTE_SUFFIX; } String number_str; number_str = Float.toString(number); char number_char[] = number_str.toCharArray(); int pos,i; pos = 0; while(number_char != null && pos < number_char.length && number_char[pos] != '.') { result.append(number_char[pos]); pos++; } if(pos < number_char.length) { result.append(number_char[pos]); pos++; for(i = 0; i < 2 && pos < number_char.length; i++, pos++) result.append(number_char[pos]); while(pos < number_char.length && number_char[pos] != 'E') pos++; while(pos < number_char.length) { result.append(number_char[pos]); pos++; } } result.append(suffix); return result.toString(); } /** * This method will decide what action should be done if the user entered a button in * the Feedback form. *
If user click cancel button then all the information taken in this form will be deleted * and user will be quitted from the Reporting Feedback sequence. *
If user click the send button then all the information taken will be stored in array which * then will be saved into xml files and sent when user confirm to send all the files. *
If user click the details button then they can view all the xml files that are going to be send. * @param e the button that user clicked */ public void actionPerformed (ActionEvent e) { getPrevData(); if(messages.getString("Send").equals(e.getActionCommand())) { String[] imgFile; String[] err_array; imgFile = getimgFile(); err_array = geterr_array(); timer.start(); sendMethod(dialog.getVector(),err_array,imgFile); } if(messages.getString("Preview").equals(e.getActionCommand())) { String[] imgFile; String[] err_array; imgFile = getimgFile(); err_array = geterr_array(); timer.start(); viewMethod(dialog.getVector(),err_array,imgFile); } if(messages.getString("NotSend").equals(e.getActionCommand())) { dispose(); } } }