1package autotest.tko;
2
3import autotest.common.SimpleCallback;
4import autotest.common.Utils;
5import autotest.common.ui.NotifyManager;
6import autotest.tko.TkoUtils.FieldInfo;
7
8import com.google.gwt.event.dom.client.ClickEvent;
9import com.google.gwt.event.dom.client.ClickHandler;
10import com.google.gwt.json.client.JSONObject;
11import com.google.gwt.json.client.JSONString;
12import com.google.gwt.user.client.ui.Anchor;
13import com.google.gwt.user.client.ui.CheckBox;
14import com.google.gwt.user.client.ui.Composite;
15import com.google.gwt.user.client.ui.FlexTable;
16import com.google.gwt.user.client.ui.HTML;
17import com.google.gwt.user.client.ui.HTMLPanel;
18import com.google.gwt.user.client.ui.HorizontalPanel;
19import com.google.gwt.user.client.ui.Label;
20import com.google.gwt.user.client.ui.Panel;
21import com.google.gwt.user.client.ui.PopupPanel;
22import com.google.gwt.user.client.ui.RootPanel;
23import com.google.gwt.user.client.ui.TextArea;
24import com.google.gwt.user.client.ui.VerticalPanel;
25import com.google.gwt.user.client.ui.Widget;
26import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
27
28import java.util.HashSet;
29import java.util.Map;
30import java.util.Set;
31
32class CommonPanel extends Composite implements ClickHandler, PositionCallback {
33    private static final String WIKI_URL = "http://autotest.kernel.org/wiki/TkoHowTo";
34    private static final String SHOW_QUICK_REFERENCE = "Show quick reference";
35    private static final String HIDE_QUICK_REFERENCE = "Hide quick reference";
36    private static final String SHOW_CONTROLS = "Show controls";
37    private static final String HIDE_CONTROLS = "Hide controls";
38
39    private static CommonPanel theInstance = new CommonPanel();
40
41    private String savedSqlCondition;
42    private boolean savedShowInvalid = false;
43    private HeaderFieldCollection headerFields = new HeaderFieldCollection();
44
45    private ParameterizedFieldListPresenter parameterizedFieldPresenter =
46        new ParameterizedFieldListPresenter(headerFields);
47
48    private HTMLPanel htmlPanel;
49    private TextArea customSqlBox = new TextArea();
50    private CheckBox showInvalid = new CheckBox("Show invalidated tests");
51    private Anchor quickReferenceLink = new Anchor(SHOW_QUICK_REFERENCE);
52    private PopupPanel quickReferencePopup;
53    private Anchor showHideControlsLink = new Anchor(HIDE_CONTROLS);
54    private Panel allControlsPanel = RootPanel.get("common_all_controls");
55    private Set<CommonPanelListener> listeners = new HashSet<CommonPanelListener>();
56    private ParameterizedFieldListDisplay parameterizedFieldDisplay =
57        new ParameterizedFieldListDisplay();
58
59
60    public static interface CommonPanelListener {
61        /**
62         * Called to show or hide tab-specific controls.
63         */
64        public void onSetControlsVisible(boolean visible);
65
66        /**
67         * Called when the set of HeaderFields has changed.
68         */
69        public void onFieldsChanged();
70    }
71
72    private CommonPanel() {
73        htmlPanel = Utils.divToPanel("common_panel");
74        initWidget(htmlPanel);
75    }
76
77    public void initialize() {
78        customSqlBox.setSize("50em", "5em");
79        quickReferenceLink.addClickHandler(this);
80        showHideControlsLink.addClickHandler(this);
81
82        Panel titlePanel = new HorizontalPanel();
83        titlePanel.add(getFieldLabel("Custom fields:"));
84        titlePanel.add(new HTML("&nbsp;<a href=\"" + Utils.escape(WIKI_URL) + "#custom_fields\" " +
85                                "target=\"_blank\">[?]</a>"));
86        Panel attributeFilters = new VerticalPanel();
87        attributeFilters.setStyleName("box");
88        attributeFilters.add(titlePanel);
89        attributeFilters.add(parameterizedFieldDisplay);
90
91        Panel commonFilterPanel = new VerticalPanel();
92        commonFilterPanel.add(customSqlBox);
93        commonFilterPanel.add(attributeFilters);
94        commonFilterPanel.add(showInvalid);
95        htmlPanel.add(commonFilterPanel, "common_filters");
96        htmlPanel.add(quickReferenceLink, "common_quick_reference");
97        htmlPanel.add(showHideControlsLink, "common_show_hide_controls");
98        generateQuickReferencePopup();
99
100        headerFields.populateFromList("all_fields");
101        notifyOnFieldsChanged();
102
103        parameterizedFieldPresenter.bindDisplay(parameterizedFieldDisplay);
104        parameterizedFieldPresenter.setListener(new SimpleCallback() {
105            @Override
106            public void doCallback(Object source) {
107                notifyOnFieldsChanged();
108            }
109        });
110    }
111
112    private Widget getFieldLabel(String string) {
113        Label label = new Label(string);
114        label.setStyleName("field-name");
115        return label;
116    }
117
118    public static CommonPanel getPanel() {
119        return theInstance;
120    }
121
122    /**
123     * For testability.
124     */
125    public static void setInstance(CommonPanel panel) {
126        theInstance = panel;
127    }
128
129    public void setConditionVisible(boolean visible) {
130        Utils.setElementVisible("common_condition_div", visible);
131    }
132
133    public void setSqlCondition(String text) {
134        savedSqlCondition = text;
135    }
136
137    public boolean isViewReadyForQuery() {
138        if (customSqlBox.getText().trim().equals("")) {
139            NotifyManager.getInstance().showError("Global filter cannot be empty");
140            return false;
141        }
142
143        return true;
144    }
145
146    public void updateStateFromView() {
147        savedSqlCondition = customSqlBox.getText().trim();
148        savedShowInvalid = showInvalid.getValue();
149    }
150
151    public void updateViewFromState() {
152        customSqlBox.setText(savedSqlCondition);
153        showInvalid.setValue(savedShowInvalid);
154    }
155
156    public JSONObject getConditionArgs() {
157        String condition = savedSqlCondition;
158        if (!savedShowInvalid) {
159            parameterizedFieldPresenter.addFieldIfNotPresent(TestLabelField.TYPE_NAME,
160                                                             "invalidated");
161            condition = "(" + condition + ") AND test_label_invalidated.id IS NULL";
162        }
163
164        JSONObject conditionArgs = new JSONObject();
165        addIfNonempty(conditionArgs, "extra_where", condition);
166        for (HeaderField field : headerFields) {
167            field.addQueryParameters(conditionArgs);
168        }
169
170        return conditionArgs;
171    }
172
173    private void addIfNonempty(JSONObject conditionArgs, String key, String value) {
174        if (value.equals("")) {
175            return;
176        }
177        conditionArgs.put(key, new JSONString(value));
178    }
179
180    public void refineCondition(String newCondition) {
181        setSqlCondition(TkoUtils.joinWithParens(" AND ", savedSqlCondition, newCondition));
182    }
183
184    public void refineCondition(TestSet tests) {
185        refineCondition(tests.getPartialSqlCondition());
186    }
187
188    public void handleHistoryArguments(Map<String, String> arguments) {
189        setSqlCondition(arguments.get("condition"));
190        savedShowInvalid = Boolean.valueOf(arguments.get("show_invalid"));
191        parameterizedFieldPresenter.handleHistoryArguments(arguments);
192        updateViewFromState();
193    }
194
195    public void addHistoryArguments(Map<String, String> arguments) {
196        arguments.put("condition", savedSqlCondition);
197        arguments.put("show_invalid", Boolean.toString(savedShowInvalid));
198        parameterizedFieldPresenter.addHistoryArguments(arguments);
199    }
200
201    public void fillDefaultHistoryValues(Map<String, String> arguments) {
202        Utils.setDefaultValue(arguments, "condition", "");
203        Utils.setDefaultValue(arguments, "show_invalid", Boolean.toString(savedShowInvalid));
204    }
205
206    public void onClick(ClickEvent event) {
207        if (event.getSource() == quickReferenceLink) {
208            handleQuickReferenceClick();
209        } else {
210            assert event.getSource() == showHideControlsLink;
211            handleShowHideControlsClick();
212        }
213    }
214
215    private void handleShowHideControlsClick() {
216        boolean areControlsVisible = showHideControlsLink.getText().equals(SHOW_CONTROLS);
217        allControlsPanel.setVisible(areControlsVisible);
218        showHideControlsLink.setText(areControlsVisible ? HIDE_CONTROLS : SHOW_CONTROLS);
219        for (CommonPanelListener listener : listeners) {
220            listener.onSetControlsVisible(areControlsVisible);
221        }
222    }
223
224    private void handleQuickReferenceClick() {
225        if (isQuickReferenceShowing()) {
226            quickReferencePopup.hide();
227            quickReferenceLink.setText(SHOW_QUICK_REFERENCE);
228        } else {
229            quickReferencePopup.setPopupPositionAndShow(this);
230            quickReferenceLink.setText(HIDE_QUICK_REFERENCE);
231        }
232    }
233
234    private boolean isQuickReferenceShowing() {
235        return quickReferenceLink.getText().equals(HIDE_QUICK_REFERENCE);
236    }
237
238    private void generateQuickReferencePopup() {
239        FlexTable fieldTable = new FlexTable();
240        fieldTable.setText(0, 0, "Name");
241        fieldTable.setText(0, 1, "Field");
242        fieldTable.getRowFormatter().setStyleName(0, "data-row-header");
243        int row = 1;
244        for (FieldInfo fieldInfo : TkoUtils.getFieldList("all_fields")) {
245            fieldTable.setText(row, 0, fieldInfo.name);
246            fieldTable.setText(row, 1, fieldInfo.field);
247            row++;
248        }
249        quickReferencePopup = new PopupPanel(false);
250        quickReferencePopup.add(fieldTable);
251    }
252
253    /**
254     * PopupListener callback.
255     */
256    public void setPosition(int offsetWidth, int offsetHeight) {
257        quickReferencePopup.setPopupPosition(
258             customSqlBox.getAbsoluteLeft() + customSqlBox.getOffsetWidth(),
259             customSqlBox.getAbsoluteTop());
260    }
261
262    public void addListener(CommonPanelListener listener) {
263        listeners.add(listener);
264    }
265
266    public HeaderFieldCollection getHeaderFields() {
267        return headerFields;
268    }
269
270    private void notifyOnFieldsChanged() {
271        for (CommonPanelListener listener : listeners) {
272            listener.onFieldsChanged();
273        }
274    }
275}
276