View Javadoc

1   /**********************************************
2    * Copyright (C) 2010 Lukas Laag
3    * This file is part of svgreal.
4    * 
5    * svgreal is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    * 
10   * svgreal is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License
16   * along with svgreal.  If not, see http://www.gnu.org/licenses/
17   **********************************************/
18  package org.vectomatic.svg.edit.client.load;
19  
20  import java.io.IOException;
21  import java.util.Iterator;
22  
23  import org.vectomatic.dom.svg.OMAttr;
24  import org.vectomatic.dom.svg.OMElement;
25  import org.vectomatic.dom.svg.OMNode;
26  import org.vectomatic.dom.svg.impl.SVGParserImpl;
27  import org.vectomatic.dom.svg.utils.DOMHelper;
28  import org.vectomatic.dom.svg.utils.XPathPrefixResolver;
29  import org.vectomatic.svg.edit.client.AppConstants;
30  import org.vectomatic.svg.edit.client.AppMessages;
31  import org.vectomatic.svg.edit.client.SvgrealApp;
32  
33  import com.extjs.gxt.ui.client.Style.Scroll;
34  import com.extjs.gxt.ui.client.data.BeanModel;
35  import com.extjs.gxt.ui.client.data.BeanModelFactory;
36  import com.extjs.gxt.ui.client.data.BeanModelLookup;
37  import com.extjs.gxt.ui.client.data.BeanModelTag;
38  import com.extjs.gxt.ui.client.event.ButtonEvent;
39  import com.extjs.gxt.ui.client.event.Events;
40  import com.extjs.gxt.ui.client.event.Listener;
41  import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
42  import com.extjs.gxt.ui.client.event.SelectionListener;
43  import com.extjs.gxt.ui.client.store.ListStore;
44  import com.extjs.gxt.ui.client.util.Format;
45  import com.extjs.gxt.ui.client.widget.Dialog;
46  import com.extjs.gxt.ui.client.widget.ListView;
47  import com.google.gwt.core.client.GWT;
48  import com.google.gwt.dom.client.Document;
49  import com.google.gwt.http.client.Request;
50  import com.google.gwt.http.client.RequestBuilder;
51  import com.google.gwt.http.client.RequestCallback;
52  import com.google.gwt.http.client.RequestException;
53  import com.google.gwt.http.client.Response;
54  
55  /**
56   * Dialog to display the OpenClipArt 'new svg' RSS feed.
57   * @author laaglu
58   */
59  public class RSSReader extends Dialog {
60  	/**
61  	 * Bean to represent a single entry in the
62  	 * OpenClipArt 'new svg' RSS feed. 
63  	 * @author laaglu
64  	 */
65  	public static class RSSEntry implements BeanModelTag {
66  		private String pngPath;
67  		private String svgPath;
68  		public RSSEntry() {
69  		}
70  
71  		public void setPngPath(String pngPath) {
72  			this.pngPath = pngPath;
73  		}
74  
75  		public String getPngPath() {
76  			return pngPath;
77  		}
78  
79  		public void setSvgPath(String svgPath) {
80  			this.svgPath = svgPath;
81  		}
82  		
83  		public String getName() {
84  			int index = svgPath.lastIndexOf('/');
85  			return (index != -1) ? svgPath.substring(1 + index) : svgPath;
86  		}
87  
88  		public String getSvgPath() {
89  			return svgPath;
90  		}
91  	}
92  
93  	/**
94  	 * The list view
95  	 */
96  	private ListView<BeanModel> view;
97  	/**
98  	 * A store from which the list view fetches
99  	 * RSS records
100 	 */
101 	private ListStore<BeanModel> store;
102 	/**
103 	 * A bean factory to wrap RSSEntry into BeanModel
104 	 * to make them compatible with ListView
105 	 */
106 	private BeanModelFactory beanFactory;
107 	
108 	public RSSReader() {
109 		super();
110 		okText = AppConstants.INSTANCE.openButton();
111 		cancelText = AppConstants.INSTANCE.cancelButton();
112 		setButtons(Dialog.OKCANCEL);
113 		setScrollMode(Scroll.AUTO);
114 		setHideOnButtonClick(true);
115 		setHeading(AppConstants.INSTANCE.openRssFeedMenuItem());
116 		setModal(true);
117 		setSize(520, 300);
118 		getButtonById(OK).addSelectionListener(new SelectionListener<ButtonEvent>() {
119 			@Override
120 			public void componentSelected(ButtonEvent ce) {
121 				for (BeanModel beanModel :  view.getSelectionModel().getSelectedItems()) {
122 					RSSEntry rssEntry = (RSSEntry)beanModel.getBean();
123 					new UrlLoadRequest(rssEntry.getSvgPath()).load();
124 				}
125 			}
126 		});
127 		
128 		beanFactory = BeanModelLookup.get().getFactory(RSSEntry.class);
129 		store = new ListStore<BeanModel>();
130 		view = new ListView<BeanModel>() {
131 			@Override
132 			protected BeanModel prepareData(BeanModel model) {
133 				String s = model.get("name");
134 				model.set("shortName", Format.ellipse(s, 15));
135 				return model;
136 			}
137 		};
138 	    view.setTemplate(getTemplate());
139 	    view.setStore(store);
140 	    view.setItemSelector("div.thumb-wrap");
141 	    view.getSelectionModel().addListener(Events.SelectionChange,
142             new Listener<SelectionChangedEvent<BeanModel>>() {
143               public void handleEvent(SelectionChangedEvent<BeanModel> be) {
144             	  BeanModel beanModel = be.getSelectedItem();
145             	  if (beanModel != null) {
146 	            	  RSSEntry rssEntry = (RSSEntry)beanModel.getBean();
147 	            	  GWT.log("Selected: " + rssEntry.getName());
148             	  }
149               }
150         });
151 	    add(view);
152 	}
153 
154 	public void load() {
155 
156 		final String url = "http://www.openclipart.org/rss/new.xml";
157 		String resourceUrl = FetchUtils.getFetchUrl(url, "text/xml");
158 		RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, resourceUrl);
159 		requestBuilder.setCallback(new RequestCallback() {
160 			public void onError(Request request, Throwable e) {
161 				GWT.log("Cannot fetch " + url, e);
162 				SvgrealApp.getApp().info(AppConstants.INSTANCE.openRssFeedMenuItem(), AppMessages.INSTANCE.loadErrorMessage(url, e.getMessage()));
163 			}
164 
165 			private void onSuccess(Request request, Response response) {
166 				store.removeAll();
167 				
168 				// Create a store of BeanModel of RSSEntry
169 				SVGParserImpl impl = GWT.create(SVGParserImpl.class);
170 				String responseText = response.getText();
171 				Document doc = impl.parseFromString(responseText, "text/xml").cast();
172 				OMElement root = OMNode.convert(doc.getDocumentElement());
173 
174 
175 				Iterator<OMAttr> iterator = DOMHelper.evaluateXPath(root, "//rss/channel/item/enclosure/@url", null);
176 				while(iterator.hasNext()) {
177 					RSSEntry rssEntry = new RSSEntry();
178 					rssEntry.setSvgPath(iterator.next().getValue());
179 					store.add(beanFactory.createModel(rssEntry));
180 				}
181 
182 				iterator = DOMHelper.evaluateXPath(root, "//rss/channel/item/media:thumbnail/@url", new XPathPrefixResolver() {
183 
184 					@Override
185 					public String resolvePrefix(String prefix) {
186 						if ("media".equals(prefix)) {
187 							return "http://search.yahoo.com/mrss/";
188 						}
189 						return null;
190 					}
191 				});
192 				int index = 0;
193 				while(iterator.hasNext()) {
194 					BeanModel beanModel = store.getAt(index++);
195 					RSSEntry rssEntry = (RSSEntry)beanModel.getBean();
196 					rssEntry.setPngPath(iterator.next().getValue());
197 					store.update(beanModel);
198 				}
199 			}
200 			
201 			public void onResponseReceived(Request request, Response response) {
202 				if (response.getStatusCode() == Response.SC_OK) {
203 					onSuccess(request, response);
204 				} else {
205 					onError(request, new IOException(AppMessages.INSTANCE.httpErrorMessage(Integer.toString(response.getStatusCode()))));
206 				}
207 			}
208 		});
209 		try {
210 			requestBuilder.send();
211 		} catch (RequestException e) {
212 			GWT.log("Cannot fetch " + url, e);
213 			SvgrealApp.getApp().info(AppConstants.INSTANCE.openRssFeedMenuItem(), AppMessages.INSTANCE.loadErrorMessage(url, e.getMessage()));
214 		}
215 	}
216 	
217 	private static native String getTemplate() /*-{
218 		return ['<tpl for=".">',
219 		'<div class="thumb-wrap" id="{svgPath}">',
220 		'<div class="thumb"><img src="{pngPath}" title="{name}"></div>',
221 		'<span class="x-editable">{shortName}</span></div>',
222 		'</tpl>',
223 		'<div class="x-clear"></div>'].join("");
224 	}-*/;
225 }