View Javadoc

1   /*--------------------------------------------------------------------------
2    *  Copyright 2007 utgenome.org
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *--------------------------------------------------------------------------*/
16  //--------------------------------------
17  // UTGBMedaka Project
18  //
19  // KeywordSearchTrack.java
20  // Since: Aug 6, 2007
21  //
22  // $URL$ 
23  // $Author$
24  //--------------------------------------
25  package org.utgenome.gwt.utgb.client.track.lib;
26  
27  import java.util.ArrayList;
28  import java.util.HashMap;
29  
30  import org.utgenome.gwt.utgb.client.bio.KeywordSearchResult;
31  import org.utgenome.gwt.utgb.client.bio.KeywordSearchResult.Entry;
32  import org.utgenome.gwt.utgb.client.track.Track;
33  import org.utgenome.gwt.utgb.client.track.TrackBase;
34  import org.utgenome.gwt.utgb.client.track.TrackFrame;
35  import org.utgenome.gwt.utgb.client.track.TrackGroup;
36  import org.utgenome.gwt.utgb.client.track.TrackGroupPropertyWriter;
37  import org.utgenome.gwt.utgb.client.track.TrackWindow;
38  import org.utgenome.gwt.utgb.client.track.UTGBProperty;
39  import org.utgenome.gwt.utgb.client.ui.FixedWidthLabel;
40  import org.utgenome.gwt.utgb.client.ui.FormLabel;
41  import org.utgenome.gwt.utgb.client.util.CanonicalProperties;
42  import org.utgenome.gwt.utgb.client.util.JSONUtil;
43  import org.utgenome.gwt.utgb.client.util.StringUtil;
44  import org.utgenome.gwt.widget.client.Style;
45  
46  import com.google.gwt.core.client.GWT;
47  import com.google.gwt.event.dom.client.ClickEvent;
48  import com.google.gwt.event.dom.client.ClickHandler;
49  import com.google.gwt.event.dom.client.KeyCodes;
50  import com.google.gwt.event.dom.client.KeyUpEvent;
51  import com.google.gwt.event.dom.client.KeyUpHandler;
52  import com.google.gwt.user.client.rpc.AsyncCallback;
53  import com.google.gwt.user.client.ui.Anchor;
54  import com.google.gwt.user.client.ui.Button;
55  import com.google.gwt.user.client.ui.Composite;
56  import com.google.gwt.user.client.ui.DockPanel;
57  import com.google.gwt.user.client.ui.FlexTable;
58  import com.google.gwt.user.client.ui.HTML;
59  import com.google.gwt.user.client.ui.HorizontalPanel;
60  import com.google.gwt.user.client.ui.Image;
61  import com.google.gwt.user.client.ui.Label;
62  import com.google.gwt.user.client.ui.PopupPanel;
63  import com.google.gwt.user.client.ui.TextBox;
64  import com.google.gwt.user.client.ui.VerticalPanel;
65  import com.google.gwt.user.client.ui.Widget;
66  
67  /**
68   * Keyword Search using utgb-keyword service
69   * 
70   * @author leo
71   * 
72   */
73  public class KeywordSearchTrack extends TrackBase {
74  	public static TrackFactory factory() {
75  		return new TrackFactory() {
76  			@Override
77  			public Track newInstance() {
78  				return new KeywordSearchTrack();
79  			}
80  		};
81  	}
82  
83  	private DockPanel basePanel = new DockPanel();
84  	private HorizontalPanel layoutPanel = new HorizontalPanel();
85  	private SearchInput keywordPanel;
86  	private VerticalPanel searchResultPanel = new VerticalPanel();
87  	private Pager pager = new Pager();
88  	private PopupPanel keywordHelpPopup = new PopupPanel(true);
89  	private ArrayList<String> keywordExampleList = new ArrayList<String>();
90  	final HTML keywordHelp = new HTML("");
91  	private String speciesScope = "any";
92  
93  	class SearchInput extends Composite {
94  		private Label _label;
95  		private Widget _form;
96  		private HorizontalPanel _layoutPanel = new HorizontalPanel();
97  
98  		public SearchInput(String label, Widget form) {
99  			_label = new Label(label);
100 			_label.setStyleName("search-label");
101 			_form = form;
102 			_form.setStyleName("search-field");
103 			_layoutPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
104 			_layoutPanel.add(_label);
105 			_layoutPanel.add(_form);
106 
107 			initWidget(_layoutPanel);
108 		}
109 
110 		public String getInput() {
111 			return ((TextBox) _form).getText();
112 		}
113 
114 	}
115 
116 	class Pager extends Composite {
117 		int page = 0;
118 		int maxPage = 0;
119 		HorizontalPanel panel = new HorizontalPanel();
120 		String keyword = "";
121 
122 		public Pager() {
123 			panel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
124 			panel.setStyleName("pager");
125 			initWidget(panel);
126 		}
127 
128 		public void update(String keyword, int page, int maxPage) {
129 			this.keyword = keyword;
130 			this.page = page;
131 			this.maxPage = maxPage;
132 			panel.clear();
133 			panel.add(new FormLabel("page: "));
134 			int minPagerPage = (page / 10) * 10 >= 0 ? ((page / 10) * 10) : page;
135 			if (minPagerPage <= 0)
136 				minPagerPage = 1;
137 			int maxPagerPage = (minPagerPage + 10) > maxPage ? maxPage + 1 : minPagerPage + 10;
138 			if (minPagerPage > 1) {
139 				panel.add(getPagerLink(minPagerPage - 1, "<<"));
140 				panel.add(getPagerLink(page - 1, "prev"));
141 			}
142 			for (int i = minPagerPage; i < maxPagerPage; i++) {
143 				final int pageNum = i;
144 				final String currentKeyword = keyword;
145 				String pageNumStr = Integer.toString(pageNum);
146 				if (i == page) {
147 					Label label = new Label(pageNumStr);
148 					Style.set(label, "color", "#FF9999");
149 					Style.margin(label, Style.LEFT | Style.RIGHT, 2);
150 					Style.bold(label);
151 					//label.setStyleName("current");
152 					panel.add(label);
153 				}
154 				else {
155 					panel.add(getPagerLink(pageNum, pageNumStr));
156 				}
157 			}
158 			if (maxPage > 1) {
159 				if (page < maxPage) {
160 					panel.add(getPagerLink(page + 1, "next"));
161 				}
162 				if (maxPagerPage < maxPage)
163 					panel.add(getPagerLink(maxPagerPage, ">>"));
164 			}
165 		}
166 
167 		private Anchor getPagerLink(final int pageNum, String label) {
168 			Anchor link = new Anchor(label);
169 			Style.margin(link, Style.LEFT | Style.RIGHT, 2);
170 			link.addClickHandler(new ClickHandler() {
171 				public void onClick(ClickEvent e) {
172 					performSearch(keyword, pageNum, 10);
173 				}
174 			});
175 			return link;
176 		}
177 	}
178 
179 	private class LocationMover implements ClickHandler {
180 		private final Entry e;
181 
182 		public LocationMover(final Entry e) {
183 			this.e = e;
184 		}
185 
186 		public void onClick(ClickEvent event) {
187 
188 			TrackGroupPropertyWriter writer = getTrackGroup().getPropertyWriter();
189 			HashMap<String, String> property = new HashMap<String, String>();
190 			property.put(UTGBProperty.REVISION, e.ref);
191 			property.put(UTGBProperty.TARGET, e.chr);
192 
193 			TrackWindow win = getTrackGroup().getTrackWindow();
194 
195 			int width = win.getEndOnGenome() - win.getStartOnGenome();
196 			int left = e.start;
197 			int right = e.end;
198 			if (width < 0) {
199 				width = -width;
200 			}
201 
202 			// locate the new window so that the target region will be at 20% from the left side 
203 			int newLeft = left - (int) (width * 0.3);
204 			int newRight = right + (int) (width * 0.3);
205 
206 			try {
207 				writer.setProperyChangeNotifaction(false);
208 				if (!win.isReverseStrand())
209 					writer.setTrackWindow(newLeft, newRight);
210 				else
211 					writer.setTrackWindow(newRight, newLeft);
212 			}
213 			finally {
214 				writer.setProperyChangeNotifaction(true);
215 			}
216 			writer.setProperty(property);
217 		}
218 	}
219 
220 	private void performSearch(final String keyword, int numPage, int entriesPerPage) {
221 		getFrame().setNowLoading();
222 		String species = null;
223 		if (!speciesScope.equals("any"))
224 			species = getTrackGroup().getPropertyReader().getProperty(UTGBProperty.SPECIES, "");
225 		String revision = getTrackGroup().getPropertyReader().getProperty(UTGBProperty.REVISION, "");
226 		getBrowserService().keywordSearch(species, revision, keyword, entriesPerPage, numPage, new AsyncCallback<KeywordSearchResult>() {
227 			public void onFailure(Throwable caught) {
228 				getFrame().loadingDone();
229 				GWT.log("search failed:", caught);
230 			}
231 
232 			public void onSuccess(KeywordSearchResult foundEntryList) {
233 				if (foundEntryList == null) {
234 					getFrame().loadingDone();
235 					return;
236 				}
237 				searchResultPanel.clear();
238 				if (foundEntryList.count <= 0) {
239 					searchResultPanel.add(new FormLabel("no entry is found"));
240 				}
241 				else {
242 					pager.update(keyword, foundEntryList.page, foundEntryList.maxPage);
243 					searchResultPanel.add(pager);
244 
245 					//String species = getTrackGroupProperty(UTGBProperty.SPECIES);
246 
247 					FlexTable table = new FlexTable();
248 					int row = 0;
249 					for (Entry e : foundEntryList.result) {
250 
251 						// col1
252 						Image icon = new Image("theme/image/item.gif");
253 						Style.margin(icon, Style.LEFT, 10);
254 						table.setWidget(row, 0, icon);
255 
256 						// col2 
257 						String label = e.ref + "/" + e.chr + ":" + StringUtil.formatNumber(e.start) + "-" + StringUtil.formatNumber(e.end) + "";
258 						Anchor link = new Anchor(label);
259 						Style.fontSize(link, 12);
260 						//link.setStyleName("searchresult");
261 						link.addClickHandler(new LocationMover(e));
262 						table.setWidget(row, 1, link);
263 						// col3
264 						FixedWidthLabel tagLabel = new FixedWidthLabel(e.name, 300);
265 						tagLabel.setStyleName("label");
266 						Style.fontSize(tagLabel, 13);
267 						Style.margin(tagLabel, Style.LEFT, 3);
268 						table.setWidget(row, 2, tagLabel);
269 
270 						table.getRowFormatter().setVerticalAlign(row, HorizontalPanel.ALIGN_MIDDLE);
271 						row++;
272 					}
273 					searchResultPanel.add(table);
274 				}
275 				refresh();
276 				getFrame().loadingDone();
277 			}
278 
279 		});
280 	}
281 
282 	class KeywordTextBox extends TextBox {
283 		public KeywordTextBox() {
284 			super();
285 
286 			addKeyUpHandler(new KeyUpHandler() {
287 				public void onKeyUp(KeyUpEvent e) {
288 					if (e.getNativeKeyCode() == KeyCodes.KEY_ENTER)
289 						performSearch(keywordPanel.getInput(), 1, 10);
290 				}
291 			});
292 			addClickHandler(new ClickHandler() {
293 				public void onClick(ClickEvent e) {
294 					KeywordTextBox.this.setFocus(true);
295 				}
296 			});
297 
298 		}
299 	}
300 
301 	public KeywordSearchTrack() {
302 		super("Keyword Search");
303 		basePanel.setStyleName("form");
304 		//searchResultPanel.setStyleName("searchresult");
305 
306 		final KeywordTextBox keywordBox = new KeywordTextBox();
307 
308 		keywordPanel = new SearchInput("Keyword", keywordBox);
309 		final HorizontalPanel hp = new HorizontalPanel();
310 		hp.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
311 		hp.add(keywordPanel);
312 		Button button = new Button("Search");
313 		button.addClickHandler(new ClickHandler() {
314 			public void onClick(ClickEvent e) {
315 				performSearch(keywordPanel.getInput(), 1, 10);
316 			}
317 		});
318 		hp.add(button);
319 
320 		// keywordHelp.setStyleName("");
321 		keywordHelpPopup.add(keywordHelp);
322 		keywordHelpPopup.setStyleName("helpPopup");
323 		final Label helpLabel = new Label("keyword help");
324 		helpLabel.setStyleName("help");
325 		helpLabel.addClickHandler(new ClickHandler() {
326 			public void onClick(ClickEvent e) {
327 				keywordHelpPopup.setPopupPosition(helpLabel.getAbsoluteLeft() + 5, helpLabel.getAbsoluteTop() + 10);
328 				keywordHelpPopup.show();
329 			}
330 		});
331 		hp.add(helpLabel);
332 		layoutPanel.add(hp);
333 
334 		basePanel.add(layoutPanel, DockPanel.CENTER);
335 		basePanel.add(searchResultPanel, DockPanel.SOUTH);
336 	}
337 
338 	public Widget getWidget() {
339 		return basePanel;
340 	}
341 
342 	@Override
343 	public void setUp(TrackFrame trackFrame, TrackGroup group) {
344 		trackFrame.pack();
345 		// trackFrame.disableClose();
346 	}
347 
348 	@Override
349 	public void draw() {
350 		StringBuilder htmlBuf = new StringBuilder();
351 		htmlBuf.append("<b>Keyword Examples:</b>");
352 		htmlBuf.append("<ul>");
353 		for (String e : keywordExampleList) {
354 			htmlBuf.append("<li>");
355 			htmlBuf.append(e);
356 			htmlBuf.append("</li>");
357 		}
358 		htmlBuf.append("</ul>");
359 
360 		keywordHelp.setHTML(htmlBuf.toString());
361 	}
362 
363 	@Override
364 	public void restoreProperties(CanonicalProperties properties) {
365 		keywordExampleList.clear();
366 		keywordExampleList.addAll(JSONUtil.parseJSONArray(properties.get("keyword.examples", "[]")));
367 
368 		speciesScope = properties.get("species.scope", "unknown");
369 	}
370 
371 	@Override
372 	public void saveProperties(CanonicalProperties saveData) {
373 		saveData.add("keyword.examples", JSONUtil.toJSONArray(keywordExampleList));
374 		saveData.add("species.scope", speciesScope);
375 	}
376 }