1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
69
70
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
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
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
246
247 FlexTable table = new FlexTable();
248 int row = 0;
249 for (Entry e : foundEntryList.result) {
250
251
252 Image icon = new Image("theme/image/item.gif");
253 Style.margin(icon, Style.LEFT, 10);
254 table.setWidget(row, 0, icon);
255
256
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
261 link.addClickHandler(new LocationMover(e));
262 table.setWidget(row, 1, link);
263
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
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
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
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 }