Create embeddable spreadsheets, and use that on the AFE Job Detail tab.

Signed-off-by: James Ren <[email protected]>

--- autotest/apache/conf/all-directives 2010-05-27 14:44:25.000000000 -0700
+++ autotest/apache/conf/all-directives 2010-05-27 14:44:25.000000000 -0700
@@ -8,5 +8,6 @@
 Include "/usr/local/autotest/apache/conf/tko-directives"
 Include "/usr/local/autotest/apache/conf/new-tko-directives"
 Include "/usr/local/autotest/apache/conf/embedded-tko-directives"
+Include "/usr/local/autotest/apache/conf/embedded-spreadsheet-directives"
 Include "/usr/local/autotest/apache/conf/planner-directives"
 Include "/usr/local/autotest/apache/conf/site-directives"
--- /dev/null   2009-12-17 12:29:38.000000000 -0800
+++ autotest/apache/conf/embedded-spreadsheet-directives        2010-05-27 
14:44:25.000000000 -0700
@@ -0,0 +1 @@
+Alias /embedded_spreadsheet 
"/usr/local/autotest/frontend/client/www/autotest.EmbeddedSpreadsheetClient"
--- /dev/null   2009-12-17 12:29:38.000000000 -0800
+++ autotest/frontend/client/EmbeddedSpreadsheetClient.launch   2010-05-27 
14:44:25.000000000 -0700
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/AfeClient"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" 
value="true"/>
+<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
+<listEntry value="&lt;?xml version=&quot;1.0&quot; 
encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry 
containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER&quot; 
javaProject=&quot;AfeClient&quot; path=&quot;1&quot; 
type=&quot;4&quot;/&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; 
encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry 
internalArchive=&quot;/AfeClient/src&quot; path=&quot;3&quot; 
type=&quot;2&quot;/&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; 
encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry 
id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento
 
project=&quot;AfeClient&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; 
encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry 
externalArchive=&quot;/usr/local/lib/gwt/gwt-dev.jar&quot; path=&quot;3&quot; 
type=&quot;2&quot;/&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; 
encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry 
externalArchive=&quot;/usr/local/lib/gwt/gwt-incubator.jar&quot; 
path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" 
value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" 
value="com.google.gwt.dev.DevMode"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" 
value="-startupUrl 
http://localhost:8000/new_tko/server/autotest.EmbeddedSpreadsheetClient/EmbeddedSpreadsheetClient.html
 autotest.EmbeddedSpreadsheetClient"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" 
value="AfeClient"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx512M 
-ea"/>
+</launchConfiguration>
--- /dev/null   2009-12-17 12:29:38.000000000 -0800
+++ autotest/frontend/client/src/autotest/EmbeddedSpreadsheetClient.gwt.xml     
2010-05-27 14:44:25.000000000 -0700
@@ -0,0 +1,15 @@
+<module>
+  <inherits name='com.google.gwt.user.User'/>
+  <inherits name='com.google.gwt.json.JSON'/>
+  <inherits name='com.google.gwt.http.HTTP'/>
+
+  <source path="tko"/>
+  <source path="common"/>
+  <entry-point class='autotest.tko.EmbeddedSpreadsheetClient'/>
+
+  <stylesheet src='common.css'/>
+  <stylesheet src='standard.css'/>
+  <stylesheet src='afeclient.css'/>
+  <stylesheet src='tkoclient.css'/>
+
+</module>
--- autotest/frontend/client/src/autotest/afe/JobDetailView.java        
2010-05-27 14:44:25.000000000 -0700
+++ autotest/frontend/client/src/autotest/afe/JobDetailView.java        
2010-05-27 14:44:25.000000000 -0700
@@ -18,13 +18,9 @@
 import autotest.common.ui.NotifyManager;
 import autotest.common.ui.TableActionsPanel.TableActionsListener;
 
+import com.google.gwt.dom.client.Element;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.http.client.Request;
-import com.google.gwt.http.client.RequestBuilder;
-import com.google.gwt.http.client.RequestCallback;
-import com.google.gwt.http.client.RequestException;
-import com.google.gwt.http.client.Response;
 import com.google.gwt.json.client.JSONArray;
 import com.google.gwt.json.client.JSONBoolean;
 import com.google.gwt.json.client.JSONNumber;
@@ -34,31 +30,35 @@
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.DisclosurePanel;
+import com.google.gwt.user.client.ui.Frame;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.ScrollPanel;
 import com.google.gwt.user.client.ui.Widget;
 
 import java.util.Set;
 
 public class JobDetailView extends DetailView implements TableWidgetFactory, 
TableActionsListener {
     private static final String[][] JOB_HOSTS_COLUMNS = {
-        {DataTable.CLICKABLE_WIDGET_COLUMN, ""}, // selection checkbox 
-        {"hostname", "Host"}, {"full_status", "Status"}, 
+        {DataTable.CLICKABLE_WIDGET_COLUMN, ""}, // selection checkbox
+        {"hostname", "Host"}, {"full_status", "Status"},
         {"host_status", "Host Status"}, {"host_locked", "Host Locked"},
         // columns for status log and debug log links
-        {DataTable.CLICKABLE_WIDGET_COLUMN, ""}, 
{DataTable.CLICKABLE_WIDGET_COLUMN, ""}  
+        {DataTable.CLICKABLE_WIDGET_COLUMN, ""}, 
{DataTable.CLICKABLE_WIDGET_COLUMN, ""}
     };
     public static final String NO_URL = "about:blank";
     public static final int NO_JOB_ID = -1;
     public static final int HOSTS_PER_PAGE = 30;
-    
+    public static final String RESULTS_MAX_WIDTH = "700px";
+    public static final String RESULTS_MAX_HEIGHT = "500px";
+    public static final String EMBEDDED_SPREADSHEET_URL =
+            "/embedded_spreadsheet/EmbeddedSpreadsheetClient.html";
+
     public interface JobDetailListener {
         public void onHostSelected(String hostname);
         public void onCloneJob(JSONValue result);
         public void onCreateRecurringJob(int id);
     }
-    
+
     protected int jobId = NO_JOB_ID;
 
     private JobStatusDataSource jobStatusDataSource = new 
JobStatusDataSource();
@@ -68,18 +68,37 @@
     protected Button abortButton = new Button("Abort job");
     protected Button cloneButton = new Button("Clone job");
     protected Button recurringButton = new Button("Create recurring job");
-    protected HTML tkoResultsHtml = new HTML();
-    protected ScrollPanel tkoResultsScroller = new ScrollPanel(tkoResultsHtml);
+    protected Frame tkoResultsFrame = new Frame(EMBEDDED_SPREADSHEET_URL);
+
     protected JobDetailListener listener;
     private SelectionManager selectionManager;
-    
+
     private Label controlFile = new Label();
     private DisclosurePanel controlFilePanel = new DisclosurePanel("");
-    
+
     protected StaticDataRepository staticData = 
StaticDataRepository.getRepository();
-    
+
     public JobDetailView(JobDetailListener listener) {
         this.listener = listener;
+        setupSpreadsheetListener(Utils.getBaseUrl());
+    }
+
+    private native void setupSpreadsheetListener(String baseUrl) /*-{
+        var ins = this;
+        $wnd.onSpreadsheetLoad = function(event) {
+            if (event.origin !== baseUrl) {
+                return;
+            }
+            
[email protected]::resizeResultsFrame(Ljava/lang/String;)(event.data);
+        }
+
+        $wnd.addEventListener("message", $wnd.onSpreadsheetLoad, false);
+    }-*/;
+
+    @SuppressWarnings("unused") // called from native
+    private void resizeResultsFrame(String message) {
+        String[] parts = message.split(" ");
+        tkoResultsFrame.setSize(parts[0], parts[1]);
     }
 
     @Override
@@ -101,7 +120,7 @@
                 }
                 String name = Utils.jsonToString(jobObject.get("name"));
                 String runVerify = 
Utils.jsonToString(jobObject.get("run_verify"));
-                
+
                 showText(name, "view_label");
                 showField(jobObject, "owner", "view_owner");
                 showField(jobObject, "priority", "view_priority");
@@ -115,27 +134,27 @@
                 showField(jobObject, "parse_failed_repair", 
"view_parse_failed_repair");
                 showField(jobObject, "synch_count", "view_synch_count");
                 showField(jobObject, "dependencies", "view_dependencies");
-                
+
                 if 
(staticData.getData("drone_sets_enabled").isBoolean().booleanValue()) {
                     showField(jobObject, "drone_set", "view_drone_set");
                 }
-                
+
                 String header = 
Utils.jsonToString(jobObject.get("control_type")) + " control file";
                 controlFilePanel.getHeaderTextAccessor().setText(header);
                 
controlFile.setText(Utils.jsonToString(jobObject.get("control_file")));
-                
+
                 JSONObject counts = jobObject.get("status_counts").isObject();
                 String countString = AfeUtils.formatStatusCounts(counts, ", ");
                 showText(countString, "view_status");
                 abortButton.setVisible(isAnyEntryAbortable(counts));
-                
+
                 String jobTag = AfeUtils.getJobTag(jobObject);
-                pointToResults(getResultsURL(jobId), getLogsURL(jobTag), 
+                pointToResults(getResultsURL(jobId), getLogsURL(jobTag),
                                getOldResultsUrl(jobId), getTriageUrl(jobId));
-                
+
                 String jobTitle = "Job: " + name + " (" + jobTag + ")";
                 displayObjectData(jobTitle);
-                
+
                 jobFilter.setParameter("job", new JSONNumber(jobId));
                 hostsTable.refresh();
             }
@@ -148,11 +167,11 @@
             }
         });
     }
-    
+
     protected boolean isAnyEntryAbortable(JSONObject statusCounts) {
         Set<String> statuses = statusCounts.keySet();
         for (String status : statuses) {
-            if (!(status.equals("Completed") || 
+            if (!(status.equals("Completed") ||
                   status.equals("Failed") ||
                   status.equals("Stopped") ||
                   status.startsWith("Aborted"))) {
@@ -161,13 +180,13 @@
         }
         return false;
     }
-    
+
     @Override
     public void initialize() {
         super.initialize();
-        
+
         idInput.setVisibleLength(5);
-        
+
         hostsTable.setRowsPerPage(HOSTS_PER_PAGE);
         hostsTable.setClickable(true);
         hostsTable.addListener(new DynamicTableListener() {
@@ -186,54 +205,54 @@
         selectionManager = tableDecorator.addSelectionManager(false);
         tableDecorator.addTableActionsPanel(this, true);
         addWidget(tableDecorator, "job_hosts_table");
-        
+
         abortButton.addClickHandler(new ClickHandler() {
             public void onClick(ClickEvent event) {
                 abortJob();
             }
         });
         addWidget(abortButton, "view_abort");
-        
+
         cloneButton.addClickHandler(new ClickHandler() {
             public void onClick(ClickEvent event) {
                 cloneJob();
-            } 
+            }
         });
         addWidget(cloneButton, "view_clone");
-        
+
         recurringButton.addClickHandler(new ClickHandler() {
             public void onClick(ClickEvent event) {
                 createRecurringJob();
-            } 
+            }
         });
         addWidget(recurringButton, "view_recurring");
-        
-        tkoResultsScroller.setStyleName("results-frame");
-        addWidget(tkoResultsScroller, "tko_results");
-        
+
+        tkoResultsFrame.getElement().setAttribute("scrolling", "no");
+        addWidget(tkoResultsFrame, "tko_results");
+
         controlFile.addStyleName("code");
         controlFilePanel.setContent(controlFile);
         addWidget(controlFilePanel, "view_control_file");
-        
+
         if 
(!staticData.getData("drone_sets_enabled").isBoolean().booleanValue()) {
             AfeUtils.removeElement("view_drone_set_wrapper");
         }
     }
 
-    
+
     protected void addTableFilters() {
         hostsTable.addFilter(jobFilter);
-        
+
         SearchFilter hostnameFilter = new SearchFilter("host__hostname", true);
         ListFilter statusFilter = new ListFilter("status");
         StaticDataRepository staticData = StaticDataRepository.getRepository();
         JSONArray statuses = staticData.getData("job_statuses").isArray();
         statusFilter.setChoices(Utils.JSONtoStrings(statuses));
-        
+
         tableDecorator.addFilter("Hostname", hostnameFilter);
         tableDecorator.addFilter("Status", statusFilter);
     }
-    
+
     private void abortJob() {
         JSONObject params = new JSONObject();
         params.put("job__id", new JSONNumber(jobId));
@@ -269,32 +288,32 @@
                 JSONObject queueEntryFilterData = new JSONObject();
                 String sql = "(status = 'Failed' OR aborted = TRUE OR " +
                              "(host_id IS NULL AND meta_host IS NULL))";
-                
+
                 queueEntryFilterData.put("extra_where", new JSONString(sql));
                 cloneJob(true, queueEntryFilterData);
             }
         });
-        
-        menu.showAt(cloneButton.getAbsoluteLeft(), 
+
+        menu.showAt(cloneButton.getAbsoluteLeft(),
                 cloneButton.getAbsoluteTop() + cloneButton.getOffsetHeight());
     }
-    
+
     private void cloneJobOnSelectedHosts() {
         Set<JSONObject> hostsQueueEntries = 
selectionManager.getSelectedObjects();
         JSONArray queueEntryIds = new JSONArray();
         for (JSONObject queueEntry : hostsQueueEntries) {
           queueEntryIds.set(queueEntryIds.size(), queueEntry.get("id"));
         }
-        
+
         JSONObject queueEntryFilterData = new JSONObject();
         queueEntryFilterData.put("id__in", queueEntryIds);
         cloneJob(true, queueEntryFilterData);
     }
-    
+
     private void cloneJob(boolean preserveMetahosts) {
         cloneJob(preserveMetahosts, new JSONObject());
     }
-    
+
     private void cloneJob(boolean preserveMetahosts, JSONObject 
queueEntryFilterData) {
         JSONObject params = new JSONObject();
         params.put("id", new JSONNumber(jobId));
@@ -312,35 +331,35 @@
     private void createRecurringJob() {
         listener.onCreateRecurringJob(jobId);
     }
-    
+
     private String getResultsURL(int jobId) {
         return 
"/new_tko/#tab_id=spreadsheet_view&row=hostname&column=test_name&" +
                "condition=afe_job_id+%253d+" + Integer.toString(jobId) + "&" +
                "show_incomplete=true";
     }
-    
+
     private String getOldResultsUrl(int jobId) {
         return "/tko/compose_query.cgi?" +
-               "columns=test&rows=hostname&condition=tag%7E%27" + 
+               "columns=test&rows=hostname&condition=tag%7E%27" +
                Integer.toString(jobId) + "-%25%27&title=Report";
     }
-    
+
     private String getTriageUrl(int jobId) {
         /*
          * Having a hard-coded path like this is very unfortunate, but there's 
no simple way
          * in the current design to generate this link by code.
-         * 
+         *
          * TODO: Redesign the system so that we can generate these links by 
code.
-         * 
+         *
          * Idea: Be able to instantiate a TableView object, ask it to set up 
to triage this job ID,
          *       and then ask it for the history URL.
          */
-        
+
         return 
"/new_tko/#tab_id=table_view&columns=test_name%252Cstatus%252Cgroup_count%252C" 
+
                
"reason&sort=test_name%252Cstatus%252Creason&condition=afe_job_id+%253D+" + 
jobId +
                "+AND+status+%253C%253E+%2527GOOD%2527&show_invalid=false";
     }
-    
+
     /**
      * Get the path for a job's raw result files.
      * @param jobLogsId id-owner, e.g. "172-showard"
@@ -348,52 +367,40 @@
     protected String getLogsURL(String jobLogsId) {
         return Utils.getRetrieveLogsUrl(jobLogsId);
     }
-    
+
     protected void pointToResults(String resultsUrl, String logsUrl,
                                   String oldResultsUrl, String triageUrl) {
         getElementById("results_link").setAttribute("href", resultsUrl);
         getElementById("old_results_link").setAttribute("href", oldResultsUrl);
         getElementById("raw_results_link").setAttribute("href", logsUrl);
         getElementById("triage_failures_link").setAttribute("href", triageUrl);
-        if (resultsUrl.equals(NO_URL)) {
-            tkoResultsHtml.setHTML("");
-            return;
-        }
 
-        RequestBuilder requestBuilder =
-            new RequestBuilder(RequestBuilder.GET, oldResultsUrl + "&brief=1");
-        try {
-            requestBuilder.sendRequest("", new RequestCallback() {
-                public void onError(Request request, Throwable exception) {
-                    tkoResultsHtml.setHTML("");
-                    NotifyManager.getInstance().showError(
-                        exception.getLocalizedMessage());
-                }
-                public void onResponseReceived(Request request,
-                                               Response response) {
-                    tkoResultsHtml.setHTML(response.getText());
-                }
-            });
-        } catch (RequestException ex) {
-          NotifyManager.getInstance().showError(ex.getLocalizedMessage());
+        tkoResultsFrame.setSize(RESULTS_MAX_WIDTH, RESULTS_MAX_HEIGHT);
+        if (!resultsUrl.equals(NO_URL)) {
+            updateResultsFrame(tkoResultsFrame.getElement(),
+                    String.valueOf(jobId), Utils.getBaseUrl());
         }
     }
-    
+
+    private native void updateResultsFrame(Element frame, String jobId, String 
baseUrl) /*-{
+        frame.contentWindow.postMessage(jobId, baseUrl);
+    }-*/;
+
     @Override
     protected String getNoObjectText() {
         return "No job selected";
     }
-    
+
     @Override
     protected String getFetchControlsElementId() {
         return "job_id_fetch_controls";
     }
-    
+
     @Override
     protected String getDataElementId() {
         return "view_data";
     }
-    
+
     @Override
     protected String getTitleElementId() {
         return "view_title";
@@ -401,11 +408,12 @@
 
     @Override
     protected String getObjectId() {
-        if (jobId == NO_JOB_ID)
+        if (jobId == NO_JOB_ID) {
             return NO_OBJECT;
+        }
         return Integer.toString(jobId);
     }
-    
+
     @Override
     public String getElementId() {
         return "view_job";
@@ -422,7 +430,7 @@
         }
         this.jobId = newJobId;
     }
-    
+
     public Widget createWidget(int row, int cell, JSONObject hostQueueEntry) {
         if (cell == 0) {
             return selectionManager.createWidget(row, cell, hostQueueEntry);
@@ -452,19 +460,19 @@
 
     public ContextMenu getActionMenu() {
         ContextMenu menu = new ContextMenu();
-        
+
         menu.addItem("Abort hosts", new Command() {
             public void execute() {
                 abortSelectedHosts();
             }
         });
-        
+
         menu.addItem("Clone job on selected hosts", new Command() {
             public void execute() {
                 cloneJobOnSelectedHosts();
             }
         });
-        
+
         return menu;
     }
 }
--- autotest/frontend/client/src/autotest/common/Utils.java     2010-05-27 
14:44:25.000000000 -0700
+++ autotest/frontend/client/src/autotest/common/Utils.java     2010-05-27 
14:44:25.000000000 -0700
@@ -314,4 +314,8 @@
         }
         return list;
     }
+
+    public static String getBaseUrl() {
+        return Window.Location.getProtocol() + "//" + 
Window.Location.getHost();
+    }
 }
--- /dev/null   2009-12-17 12:29:38.000000000 -0800
+++ autotest/frontend/client/src/autotest/public/EmbeddedSpreadsheetClient.html 
2010-05-27 14:44:25.000000000 -0700
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Embedded Spreadsheet</title>
+  <script type='text/javascript'
+          src='autotest.EmbeddedSpreadsheetClient.nocache.js'>
+  </script>
+</head>
+<body></body>
--- autotest/frontend/client/src/autotest/public/afeclient.css  2010-05-27 
14:44:25.000000000 -0700
+++ autotest/frontend/client/src/autotest/public/afeclient.css  2010-05-27 
14:44:25.000000000 -0700
@@ -134,13 +134,6 @@
   margin: 0.2em;
 }
 
-.results-frame {
-  max-width: 700px;
-  max-height: 500px;
-  margin-bottom: 0.2em;
-  border: 2px solid gray;
-}
-
 .gwt-DialogBox {
   background: white;
   border: 2px solid #f4f4f4;
--- /dev/null   2009-12-17 12:29:38.000000000 -0800
+++ autotest/frontend/client/src/autotest/tko/EmbeddedSpreadsheetClient.java    
2010-05-27 14:44:25.000000000 -0700
@@ -0,0 +1,79 @@
+package autotest.tko;
+
+import autotest.common.JsonRpcProxy;
+import autotest.common.spreadsheet.Spreadsheet;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.json.client.JSONNumber;
+import com.google.gwt.json.client.JSONObject;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.ui.RootPanel;
+
+import java.util.Collections;
+
+public class EmbeddedSpreadsheetClient implements EntryPoint {
+    private static class SimpleHeaderField extends HeaderField {
+        protected SimpleHeaderField(String name) {
+            super(name, name);
+        }
+
+        @Override
+        public String getSqlCondition(String value) {
+            throw new UnsupportedOperationException("No SQL condition");
+        }
+    }
+
+    public static final String ROW_HEADER = "hostname";
+    public static final String COLUMN_HEADER = "test_name";
+
+    private Spreadsheet spreadsheet = new Spreadsheet();
+    private SpreadsheetDataProcessor spreadsheetProcessor =
+            new SpreadsheetDataProcessor(spreadsheet);
+
+    @Override
+    public void onModuleLoad() {
+        JsonRpcProxy.setDefaultBaseUrl(JsonRpcProxy.TKO_BASE_URL);
+        setupListener();
+
+        
spreadsheetProcessor.setDataSource(TestGroupDataSource.getStatusCountDataSource());
+        spreadsheetProcessor.setHeaders(
+                Collections.singletonList(new SimpleHeaderField(ROW_HEADER)),
+                Collections.singletonList(new 
SimpleHeaderField(COLUMN_HEADER)),
+                new JSONObject());
+
+        RootPanel.get().add(spreadsheet);
+    }
+
+    private native void setupListener() /*-{
+        var instance = this;
+        $wnd.onGotJobId = function(event) {
+            var jobId = parseInt(event.data);
+            
[email protected]::createSpreadsheet(I)(jobId);
+        }
+
+        $wnd.addEventListener("message", $wnd.onGotJobId, false);
+    }-*/;
+
+    @SuppressWarnings("unused") // called from native
+    private void createSpreadsheet(int afeJobId) {
+        spreadsheet.clear();
+        final JSONObject condition = getFilterCondition(afeJobId);
+        spreadsheetProcessor.refresh(condition, new Command() {
+            public void execute() {
+                condition.put("extra_info", null);
+                notifyParent(spreadsheet.getElement().getClientWidth(),
+                        spreadsheet.getElement().getClientHeight());
+            }
+        });
+    }
+
+    private JSONObject getFilterCondition(int afeJobId) {
+        JSONObject condition = new JSONObject();
+        condition.put("afe_job_id", new JSONNumber(afeJobId));
+        return condition;
+    }
+
+    private native void notifyParent(int width, int height) /*-{
+        $wnd.parent.postMessage(width + 'px ' + height + 'px', '*');
+    }-*/;
+}
--- autotest/frontend/client/src/autotest/tko/SpreadsheetDataProcessor.java     
2010-05-27 14:44:25.000000000 -0700
+++ autotest/frontend/client/src/autotest/tko/SpreadsheetDataProcessor.java     
2010-05-27 14:44:25.000000000 -0700
@@ -187,7 +187,8 @@
         onFinished.execute();
     }
 
-    public void setHeaders(List<HeaderField> rowFields, List<HeaderField> 
columnFields,
+    public void setHeaders(List<? extends HeaderField> rowFields,
+                           List<? extends HeaderField> columnFields,
                            JSONObject queryParameters) {
         this.rowFields = getHeaderSqlNames(rowFields);
         this.columnFields = getHeaderSqlNames(columnFields);
@@ -199,7 +200,7 @@
         dataSource.setQueryParameters(queryParameters);
     }
 
-    private Header getHeaderSqlNames(List<HeaderField> fields) {
+    private Header getHeaderSqlNames(List<? extends HeaderField> fields) {
         Header header = new HeaderImpl();
         for (HeaderField field : fields) {
             header.add(field.getSqlName());
--- autotest/frontend/client/src/autotest/tko/TestGroupDataSource.java  
2010-05-27 14:44:25.000000000 -0700
+++ autotest/frontend/client/src/autotest/tko/TestGroupDataSource.java  
2010-05-27 14:44:25.000000000 -0700
@@ -22,24 +22,24 @@
     public static final String PASS_COUNT_FIELD = "pass_count";
     public static final String COMPLETE_COUNT_FIELD = "complete_count";
     public static final String INCOMPLETE_COUNT_FIELD = "incomplete_count";
-    
+
     private JSONArray groupByFields;
     private JSONArray headerGroups;
     private JSONArray headerGroupValues;
     private JSONObject queryParameters;
-    
+
     public static TestGroupDataSource getTestGroupDataSource() {
         return new TestGroupDataSource(GROUP_COUNTS_RPC);
     }
-    
+
     public static TestGroupDataSource getStatusCountDataSource() {
         return new TestGroupDataSource(STATUS_COUNTS_RPC);
     }
-    
+
     public static TestGroupDataSource getLatestTestsDataSource() {
         return new TestGroupDataSource(LATEST_TESTS_RPC);
     }
-    
+
     // force construction to go through above factory methods
     private TestGroupDataSource(String dataMethodName) {
         super(dataMethodName, NUM_GROUPS_RPC);
@@ -69,7 +69,7 @@
         headerGroupValues = resultObject.get("header_values").isArray();
         return new 
JSONArrayList<JSONObject>(resultObject.get("groups").isArray());
     }
-    
+
     public void setGroupColumns(String[] columns) {
         groupByFields = new JSONArray();
         for (String field : columns) {
@@ -77,7 +77,7 @@
         }
         headerGroups = null;
     }
-    
+
     public void setHeaderGroups(List<List<String>> headerFieldGroups) {
         groupByFields = new JSONArray();
         headerGroups = new JSONArray();
@@ -88,9 +88,9 @@
             }
         }
     }
-    
+
     /**
-     * Get a list of values for the header group with the given index, as 
specified to 
+     * Get a list of values for the header group with the given index, as 
specified to
      * setHeaderGroups().
      */
     public List<List<String>> getHeaderGroupValues(int groupIndex) {
_______________________________________________
Autotest mailing list
[email protected]
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

Reply via email to