User collection results are shown in result table. Basic infrastructure for geeklist id and family id (TODO).pull/2/head
| @@ -0,0 +1,224 @@ | |||
| package xyz.veronie.bgg.result; | |||
| import java.io.BufferedReader; | |||
| import java.io.IOException; | |||
| import java.io.InputStreamReader; | |||
| import java.io.StringReader; | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.net.HttpURLConnection; | |||
| import java.net.MalformedURLException; | |||
| import java.net.URL; | |||
| import java.net.URLEncoder; | |||
| import java.util.ArrayList; | |||
| import java.util.Iterator; | |||
| import java.util.Map.Entry; | |||
| import javax.inject.Inject; | |||
| import javax.xml.parsers.DocumentBuilder; | |||
| import javax.xml.parsers.DocumentBuilderFactory; | |||
| import javax.xml.parsers.ParserConfigurationException; | |||
| import org.eclipse.e4.core.di.annotations.Creatable; | |||
| import org.w3c.dom.Document; | |||
| import org.w3c.dom.Element; | |||
| import org.w3c.dom.Node; | |||
| import org.w3c.dom.NodeList; | |||
| import org.xml.sax.InputSource; | |||
| import org.xml.sax.SAXException; | |||
| import xyz.veronie.bgg.types.FilterFlagState; | |||
| import xyz.veronie.bgg.types.Subtype; | |||
| import xyz.veronie.bgg.types.UserFlag; | |||
| @Creatable | |||
| public class BggApi { | |||
| @Inject private ResultConfigManager configManager; | |||
| public static String BASE_URL = "https://www.boardgamegeek.com/xmlapi2/"; | |||
| public static String USER = "user"; | |||
| public static String COLLECTION = "collection"; | |||
| public static String SEARCH = "search"; | |||
| public static String FAMILY = "family"; | |||
| public static String GEEKLIST = "geeklist"; | |||
| private static int RETRIES = 5; | |||
| public ArrayList<ThingMetaData> getThingsForUser(String user) { | |||
| ResultConfig resultConfig = configManager.getResultConfig(); | |||
| StringBuilder urlStr = new StringBuilder(); | |||
| urlStr.append(BASE_URL + COLLECTION | |||
| + "?username=" + resultConfig.user | |||
| + "&subtype=" + resultConfig.subtype.toApiString() + "&"); | |||
| if(resultConfig.subtype == Subtype.BOARDGAME) { | |||
| urlStr.append("excludesubtype=" + Subtype.BGEXPANSION.toApiString() + "&"); | |||
| } | |||
| Iterator<Entry<UserFlag, FilterFlagState>> ufIterator | |||
| = resultConfig.userFlags.entrySet().iterator(); | |||
| try { | |||
| while(ufIterator.hasNext()) { | |||
| Entry<UserFlag, FilterFlagState> elem = ufIterator.next(); | |||
| String apiString = elem.getKey().toApiString(); | |||
| FilterFlagState state = elem.getValue(); | |||
| if(state == FilterFlagState.IS) { | |||
| urlStr.append(URLEncoder.encode(apiString, "UTF-8")); | |||
| urlStr.append("=1&"); | |||
| } else if (state == FilterFlagState.ISNOT) { | |||
| urlStr.append(URLEncoder.encode(apiString, "UTF-8")); | |||
| urlStr.append("=0&"); | |||
| } | |||
| } | |||
| } | |||
| catch (UnsupportedEncodingException e) { | |||
| e.printStackTrace(); | |||
| return null; | |||
| } | |||
| return getThings(urlStr.toString()); | |||
| } | |||
| public ArrayList<ThingMetaData> getThingsForGeeklist(int geeklistId) { | |||
| ResultConfig resultConfig = configManager.getResultConfig(); | |||
| StringBuilder urlStr = new StringBuilder(); | |||
| urlStr.append(BASE_URL + GEEKLIST + "/" + String.valueOf(resultConfig.geeklistId)); | |||
| return getThings(urlStr.toString()); | |||
| } | |||
| private ArrayList<ThingMetaData> getThings(String urlString) { | |||
| System.out.println("URL: " + urlString); | |||
| try { | |||
| int retry = 0; | |||
| do { | |||
| // send a GET request and check for ok... | |||
| URL url = new URL(urlString); | |||
| HttpURLConnection con = (HttpURLConnection) url.openConnection(); | |||
| con.setRequestMethod("GET"); | |||
| int status = con.getResponseCode(); | |||
| if(status == HttpURLConnection.HTTP_ACCEPTED) { | |||
| Thread.sleep(2000); | |||
| System.out.println("Waiting for server to prepare result..."); | |||
| } | |||
| else if(status != HttpURLConnection.HTTP_OK) { | |||
| System.out.println("Http Response: " + status); | |||
| con.disconnect(); | |||
| return null; | |||
| } else { | |||
| // HTTP_OK, go on... | |||
| BufferedReader in = new BufferedReader( | |||
| new InputStreamReader(con.getInputStream())); | |||
| String inputLine; | |||
| StringBuffer content = new StringBuffer(); | |||
| while ((inputLine = in.readLine()) != null) { | |||
| content.append(inputLine); | |||
| } | |||
| in.close(); | |||
| con.disconnect(); | |||
| // do something with the content | |||
| System.out.println(content.toString()); | |||
| ArrayList<ThingMetaData> output = parseThingMetas(content.toString()); | |||
| return output; | |||
| } | |||
| ++retry; | |||
| } while (retry < RETRIES); | |||
| } | |||
| catch (MalformedURLException e) { | |||
| System.out.println("[ERROR] Malformed URL: " + urlString); | |||
| e.printStackTrace(); | |||
| } catch (IOException e) { | |||
| System.out.println("[ERROR] Could not open connection for URL: " + urlString); | |||
| e.printStackTrace(); | |||
| } catch (InterruptedException e) { | |||
| // this will not happen, but we have to catch it anyways... | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| private ArrayList<ThingMetaData> parseThingMetas(String content) { | |||
| ArrayList<ThingMetaData> metas = new ArrayList<ThingMetaData>(); | |||
| DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | |||
| try { | |||
| DocumentBuilder builder = factory.newDocumentBuilder(); | |||
| InputSource is = new InputSource(new StringReader(content)); | |||
| is.setEncoding("UTF-8"); | |||
| Document doc = builder.parse(is); | |||
| Element root = doc.getDocumentElement(); | |||
| // BGG XMLAPI2 | |||
| if(root.getTagName() == "items") { | |||
| NodeList nList = doc.getElementsByTagName("item"); | |||
| for(int i = 0; i < nList.getLength(); i++) { | |||
| Node nNode = nList.item(i); | |||
| if (nNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element eElement = (Element) nNode; | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| Integer.parseInt(eElement.getAttribute("objectid")), | |||
| getValue(eElement, "name"), | |||
| getValue(eElement, "image"), | |||
| getValue(eElement, "thumbnail"), | |||
| getValue(eElement, "comment"), | |||
| Integer.parseInt(getValue(eElement, "numplays")) | |||
| ); | |||
| metas.add(tmd); | |||
| } | |||
| } | |||
| } | |||
| // for geeklist result (XMLAPI) | |||
| else if(root.getTagName() == "geeklist") { | |||
| NodeList nList = doc.getElementsByTagName("item"); | |||
| for(int i = 0; i < nList.getLength(); i++) { | |||
| Node nNode = nList.item(i); | |||
| if (nNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element eElement = (Element) nNode; | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| Integer.parseInt(eElement.getAttribute("objectid")), | |||
| eElement.getAttribute("objectname"), | |||
| "", "", "", null); | |||
| metas.add(tmd); | |||
| } | |||
| } | |||
| } | |||
| return metas; | |||
| } catch (ParserConfigurationException e) { | |||
| e.printStackTrace(); | |||
| } catch (SAXException e) { | |||
| e.printStackTrace(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| private String getValue(Element eElement, String key) { | |||
| Node node = eElement.getElementsByTagName(key).item(0); | |||
| if(node == null) { | |||
| return ""; | |||
| } else { | |||
| return node.getTextContent(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,5 @@ | |||
| package xyz.veronie.bgg.result; | |||
| public class BggFamily { | |||
| } | |||
| @@ -15,15 +15,7 @@ public class ResultConfig { | |||
| public SourceFilter source = SourceFilter.BGG_USER; | |||
| public ResultAction action = ResultAction.ADD; | |||
| public HashMap<Subtype,Boolean> subTypes = new HashMap<Subtype,Boolean>() { | |||
| private static final long serialVersionUID = -8718858283141976457L; | |||
| { | |||
| for (Subtype st : Subtype.values()) { | |||
| put(st, false); | |||
| } | |||
| put(Subtype.BOARDGAME, true); | |||
| }}; | |||
| public Subtype subtype = Subtype.BOARDGAME; | |||
| // bgg user filter settings | |||
| public String user = ""; | |||
| @@ -11,7 +11,7 @@ import org.eclipse.e4.ui.di.UIEventTopic; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| import xyz.veronie.bgg.types.ResultAction; | |||
| import xyz.veronie.bgg.types.SourceFilter; | |||
| import xyz.veronie.bgg.types.SubtypeEvent; | |||
| import xyz.veronie.bgg.types.Subtype; | |||
| import xyz.veronie.bgg.types.UserFlagEvent; | |||
| @@ -43,9 +43,9 @@ public class ResultConfigManager { | |||
| @Optional | |||
| private void subscribeTopicSubtypesChanged | |||
| (@UIEventTopic(EventConstants.TOPIC_SUBTYPE_CHANGED) | |||
| SubtypeEvent se) { | |||
| getResultConfig().subTypes.put(se.subtype, se.checked); | |||
| System.out.println("TOPIC_SUBTYPE_CHANGED: " + (se.checked?"[x] ":"[ ] ") + se.subtype); | |||
| Subtype subtype) { | |||
| getResultConfig().subtype = subtype; | |||
| System.out.println("TOPIC_SUBTYPE_CHANGED: " + subtype); | |||
| } | |||
| @Inject | |||
| @@ -75,7 +75,25 @@ public class ResultConfigManager { | |||
| getResultConfig().action = action; | |||
| System.out.println("TOPIC_ACTION_CHANGED: action = " + action); | |||
| } | |||
| @Inject | |||
| @Optional | |||
| private void subscribeTopicResultGeeklistChanged | |||
| (@UIEventTopic(EventConstants.TOPIC_GEEKLIST_CHANGED) | |||
| Integer id) { | |||
| getResultConfig().geeklistId = id; | |||
| System.out.println("TOPIC_GEEKLIST_CHANGED: geeklistId = " + id); | |||
| } | |||
| @Inject | |||
| @Optional | |||
| private void subscribeTopicResultFamilyChanged | |||
| (@UIEventTopic(EventConstants.TOPIC_FAMILY_CHANGED) | |||
| Integer id) { | |||
| getResultConfig().familyId = id; | |||
| System.out.println("TOPIC_FAMILY_CHANGED: geeklistId = " + id); | |||
| } | |||
| public ResultConfig getResultConfig() { | |||
| return resultConfig; | |||
| } | |||
| @@ -3,25 +3,32 @@ package xyz.veronie.bgg.result; | |||
| import java.beans.PropertyChangeListener; | |||
| import java.beans.PropertyChangeSupport; | |||
| public class ThingMetaData { | |||
| private int id; | |||
| private Integer rating; | |||
| private String name; | |||
| private String imgURL; | |||
| private String thumbURL; | |||
| private String comment; | |||
| private Integer otherId; // ??? | |||
| private String username; | |||
| private Integer numPlays; | |||
| private static String[] titles = { "Id", "Name", "Image", "Thumb", "comment", "# plays"}; | |||
| private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); | |||
| public ThingMetaData(int id, Integer rating, String imgURL, String thumbURL, String comment, Integer otherId, String username) { | |||
| public ThingMetaData(int id, String name, | |||
| String imgURL, String thumURL, | |||
| String comment, Integer numPlays) { | |||
| this.setId(id); | |||
| this.setRating(rating); | |||
| this.setName(name); | |||
| this.setImgURL(imgURL); | |||
| this.setThumbURL(thumbURL); | |||
| this.setThumbURL(thumURL); | |||
| this.setComment(comment); | |||
| this.setOtherId(otherId); | |||
| this.setUsername(username); | |||
| this.setNumPlays(numPlays); | |||
| } | |||
| public static String[] getTitles() { | |||
| return titles; | |||
| } | |||
| public void addPropertyChangeListener(String propertyName, | |||
| @@ -32,6 +39,42 @@ public class ThingMetaData { | |||
| public void removePropertyChangeListener(PropertyChangeListener listener) { | |||
| propertyChangeSupport.removePropertyChangeListener(listener); | |||
| } | |||
| /// get field at idx, order of titles | |||
| public String getField(int idx) { | |||
| if(idx >= titles.length) { | |||
| } | |||
| String returnStr; | |||
| switch(idx) { | |||
| case 0: | |||
| returnStr = String.valueOf(this.id); | |||
| break; | |||
| case 1: | |||
| returnStr = this.name; | |||
| break; | |||
| case 2: | |||
| returnStr = this.imgURL; | |||
| break; | |||
| case 3: | |||
| returnStr = this.thumbURL; | |||
| break; | |||
| case 4: | |||
| returnStr = this.comment; | |||
| break; | |||
| case 5: | |||
| returnStr = String.valueOf(this.numPlays); | |||
| break; | |||
| default: | |||
| throw new ArrayIndexOutOfBoundsException( | |||
| "idx " + String.valueOf(idx) + " must be in [0," + (titles.length-1) + "]"); | |||
| } | |||
| return returnStr; | |||
| } | |||
| public int getId() { | |||
| return id; | |||
| @@ -42,15 +85,16 @@ public class ThingMetaData { | |||
| this.id = id); | |||
| } | |||
| public Integer getRating() { | |||
| return rating; | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| public void setRating(Integer rating) { | |||
| propertyChangeSupport.firePropertyChange("rating", this.rating, | |||
| this.rating = rating); | |||
| public void setName(String name) { | |||
| propertyChangeSupport.firePropertyChange("name", this.name, | |||
| this.name = name); | |||
| } | |||
| public String getImgURL() { | |||
| return imgURL; | |||
| } | |||
| @@ -63,44 +107,34 @@ public class ThingMetaData { | |||
| public String getThumbURL() { | |||
| return thumbURL; | |||
| } | |||
| public void setThumbURL(String thumbURL) { | |||
| propertyChangeSupport.firePropertyChange("thumb", this.thumbURL, | |||
| this.thumbURL = thumbURL); | |||
| } | |||
| public String getComment() { | |||
| return comment; | |||
| public int getNumPlays() { | |||
| return numPlays; | |||
| } | |||
| public void setComment(String comment) { | |||
| propertyChangeSupport.firePropertyChange("comment", this.comment, | |||
| this.comment = comment); | |||
| public void setNumPlays(Integer numPlays) { | |||
| this.numPlays = numPlays; | |||
| } | |||
| public Integer getOtherId() { | |||
| return otherId; | |||
| } | |||
| public void setOtherId(Integer otherId) { | |||
| propertyChangeSupport.firePropertyChange("otherId", this.otherId, | |||
| this.otherId = otherId); | |||
| public String getComment() { | |||
| return comment; | |||
| } | |||
| public String getUsername() { | |||
| return username; | |||
| public void setComment(String comment) { | |||
| propertyChangeSupport.firePropertyChange("comment", this.comment, | |||
| this.comment = comment); | |||
| } | |||
| public void setUsername(String username) { | |||
| propertyChangeSupport.firePropertyChange("username", this.username, | |||
| this.username = username); | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return String.valueOf(id); | |||
| } | |||
| } | |||
| @@ -10,17 +10,10 @@ public enum ThingProvider { | |||
| private ThingProvider() { | |||
| thingMetas = new ArrayList<ThingMetaData>(); | |||
| // TODO: retrieve data from BGG | |||
| // ...and iterate: | |||
| thingMetas.add(new ThingMetaData( | |||
| 286053, | |||
| null, | |||
| "https://cf.geekdo-images.com/original/img/vKBCxo7d6maBDC_X9nmC5MWzIC8=/0x0/pic4880614.jpg", | |||
| "https://cf.geekdo-images.com/thumb/img/gpeB-GrXrknzAqFKEky1JOvcY4w=/fit-in/200x150/pic4880614.jpg", | |||
| "", | |||
| 65212097, | |||
| "veronie")); | |||
| } | |||
| public void setThingMetas(ArrayList<ThingMetaData> metas) { | |||
| this.thingMetas = metas; | |||
| } | |||
| public List<ThingMetaData> getThingMetas() { | |||
| @@ -1,6 +0,0 @@ | |||
| package xyz.veronie.bgg.types; | |||
| /// This class contains and handles the result table for BGG things | |||
| public class BggResult { | |||
| } | |||
| @@ -2,7 +2,7 @@ package xyz.veronie.bgg.types; | |||
| public interface EventConstants { | |||
| String TOPIC_CONFIG_CHANGED = "CONFIG_CHANGED/*"; | |||
| String TOPIC_CONFIG_CHANGED = "CONFIG_CHANGED"; | |||
| String TOPIC_SOURCE_CHANGED = "CONFIG_CHANGED/FILTER"; | |||
| @@ -16,4 +16,9 @@ public interface EventConstants { | |||
| String TOPIC_GEEKLIST_CHANGED = "CONFIG_CHANGED/GEEKLIST"; | |||
| String TOPIC_FAMILY_CHANGED = "CONFIG_CHANGED/FAMILY"; | |||
| String TOPIC_RESULT_CHANGED = "RESULT_CHANGED"; | |||
| } | |||
| @@ -20,9 +20,10 @@ public enum Subtype { | |||
| public String toString() { | |||
| return this.name; | |||
| } | |||
| /// return the string used in BGG XMLAPI2 to identify the thingtype | |||
| public String toSubtypeString() { | |||
| public String toApiString() { | |||
| return this.thingTypeString; | |||
| } | |||
| } | |||
| @@ -1,6 +0,0 @@ | |||
| package xyz.veronie.bgg.types; | |||
| public class SubtypeEvent { | |||
| public Subtype subtype; | |||
| public Boolean checked; | |||
| } | |||
| @@ -2,23 +2,42 @@ package xyz.veronie.bgg.types; | |||
| public enum UserFlag { | |||
| OWN("owned"), | |||
| PREVIOUSLY_OWNED("previously owned"), | |||
| FOR_TRADE("for trade"), | |||
| WANTED("wanted"), | |||
| WTP("want to play"), | |||
| WTB("want to buy"), | |||
| WISHLIST("on wishlist"), | |||
| PREORDERED("preordered"); | |||
| OWN("owned", "own"), | |||
| PREVIOUSLY_OWNED("previously owned", "prevowned"), | |||
| TRADE("for trade", "trade"), | |||
| WANT("wanted", "want"), | |||
| WTP("want to play", "wanttoplay"), | |||
| WTB("want to buy", "wanttobuy"), | |||
| WISHLIST("on wishlist", "wishlist"), | |||
| PREORDERED("pre-ordered", "preordered"), | |||
| RATED("rated", "rated"), | |||
| PLAYED("played", "played"), | |||
| COMMENT("commented", "comment"); | |||
| // MINRATING("min rating", "minrating"), | |||
| // MAXRATING("max rating", "rating"), | |||
| // MIN_BGG_RATING("min BGG rating", "minbggrating"), | |||
| // MAX_BGG_RATING("max BGG rating", "bggrating"), | |||
| // MIN_PLAYS("min plays", "minplays"), | |||
| // MAX_PLAYS("max plays, "maxplays"), | |||
| // MODIFIED_SINCE("modified since", "modifiedsince"); | |||
| private String flag; | |||
| private String apiString; | |||
| private UserFlag(String flag) { | |||
| private UserFlag(String flag, String apiString) { | |||
| this.flag = flag; | |||
| this.apiString = apiString; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return this.flag; | |||
| } | |||
| public String toApiString() { | |||
| return this.apiString; | |||
| } | |||
| } | |||
| @@ -106,12 +106,17 @@ public class BggUserSourceFilter { | |||
| makeFilter(parent, UserFlag.PREVIOUSLY_OWNED); | |||
| makeFilter(parent, UserFlag.WTB); | |||
| makeFilter(parent, UserFlag.FOR_TRADE); | |||
| makeFilter(parent, UserFlag.TRADE); | |||
| makeFilter(parent, UserFlag.WISHLIST); | |||
| makeFilter(parent, UserFlag.WANTED); | |||
| makeFilter(parent, UserFlag.WANT); | |||
| makeFilter(parent, UserFlag.PREORDERED); | |||
| makeFilter(parent, UserFlag.RATED); | |||
| makeFilter(parent, UserFlag.COMMENT); | |||
| makeFilter(parent, UserFlag.PLAYED); | |||
| parent.layout(); | |||
| } | |||
| @@ -1,5 +1,10 @@ | |||
| package xyz.veronie.bgg.ui.filters; | |||
| import javax.inject.Inject; | |||
| import org.eclipse.e4.core.di.annotations.Creatable; | |||
| import org.eclipse.e4.core.services.events.IEventBroker; | |||
| import org.eclipse.jface.dialogs.MessageDialog; | |||
| import org.eclipse.swt.SWT; | |||
| import org.eclipse.swt.events.FocusEvent; | |||
| import org.eclipse.swt.events.FocusListener; | |||
| @@ -11,11 +16,17 @@ import org.eclipse.swt.widgets.Combo; | |||
| import org.eclipse.swt.widgets.Composite; | |||
| import org.eclipse.swt.widgets.Label; | |||
| import xyz.veronie.bgg.result.ResultConfigManager; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| /// These are the controls to retrieve thing IDs for a given family ID | |||
| @Creatable | |||
| public class FamilySourceFilter { | |||
| private static int familyId; | |||
| public static void create(Composite parent, int style) { | |||
| @Inject private IEventBroker eventBroker; | |||
| @Inject private ResultConfigManager configManager; | |||
| public void create(Composite parent, int style) { | |||
| GridLayout filterLayout = new GridLayout(2, false); | |||
| parent.setLayout(filterLayout); | |||
| @@ -27,16 +38,28 @@ public class FamilySourceFilter { | |||
| cbFamilyId.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); | |||
| cbFamilyId.addSelectionListener(new SelectionAdapter() { | |||
| public void widgetDefaultSelected(SelectionEvent e) { | |||
| setFamilyId(Integer.getInteger(cbFamilyId.getText())); | |||
| System.out.println("set geeklist id to '" + getFamilyId() + "'"); | |||
| try { | |||
| setFamilyId(Integer.parseInt(cbFamilyId.getText())); | |||
| System.out.println("set family id to '" + configManager.getResultConfig().geeklistId + "'"); | |||
| } | |||
| catch (NumberFormatException ex) { | |||
| MessageDialog.openError(parent.getShell(), "Input error", "FamilyId must be a whole number."); | |||
| } | |||
| System.out.println("set family id to '" + configManager.getResultConfig().familyId + "'"); | |||
| } | |||
| }); | |||
| cbFamilyId.addFocusListener(new FocusListener() { | |||
| @Override | |||
| public void focusLost(FocusEvent e) { | |||
| setFamilyId(Integer.getInteger(cbFamilyId.getText())); | |||
| System.out.println("set geeklist id to '" + getFamilyId() + "'"); | |||
| try { | |||
| setFamilyId(Integer.parseInt(cbFamilyId.getText())); | |||
| System.out.println("set family id to '" + configManager.getResultConfig().geeklistId + "'"); | |||
| } | |||
| catch (NumberFormatException ex) { | |||
| MessageDialog.openError(parent.getShell(), "Input error", "FamilyId must be a whole number."); | |||
| } | |||
| System.out.println("set family id to '" + configManager.getResultConfig().familyId + "'"); | |||
| } | |||
| @Override | |||
| @@ -47,11 +70,12 @@ public class FamilySourceFilter { | |||
| parent.layout(); | |||
| } | |||
| public static int getFamilyId() { | |||
| return familyId; | |||
| } | |||
| public static void setFamilyId(int familyId) { | |||
| FamilySourceFilter.familyId = familyId; | |||
| public void setFamilyId(int familyId) { | |||
| if(eventBroker != null) { | |||
| eventBroker.post(EventConstants.TOPIC_FAMILY_CHANGED, familyId); | |||
| } else { | |||
| System.out.println("setFamilyId: eventBroker is null."); | |||
| } | |||
| } | |||
| } | |||
| @@ -4,6 +4,7 @@ import javax.inject.Inject; | |||
| import org.eclipse.e4.core.di.annotations.Creatable; | |||
| import org.eclipse.e4.core.services.events.IEventBroker; | |||
| import org.eclipse.jface.dialogs.MessageDialog; | |||
| import org.eclipse.swt.SWT; | |||
| import org.eclipse.swt.events.FocusEvent; | |||
| import org.eclipse.swt.events.FocusListener; | |||
| @@ -23,7 +24,7 @@ import xyz.veronie.bgg.types.EventConstants; | |||
| public class GeeklistSourceFilter { | |||
| @Inject private IEventBroker eventBroker; | |||
| @Inject ResultConfigManager configManager; | |||
| @Inject private ResultConfigManager configManager; | |||
| public void create(Composite parent, int style) { | |||
| GridLayout filterLayout = new GridLayout(2, false); | |||
| @@ -37,16 +38,27 @@ public class GeeklistSourceFilter { | |||
| cbGeeklistId.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); | |||
| cbGeeklistId.addSelectionListener(new SelectionAdapter() { | |||
| public void widgetDefaultSelected(SelectionEvent e) { | |||
| setGeeklistId(Integer.getInteger(cbGeeklistId.getText())); | |||
| System.out.println("set geeklist id to '" + configManager.getResultConfig().geeklistId + "'"); | |||
| try { | |||
| setGeeklistId(Integer.parseInt(cbGeeklistId.getText())); | |||
| System.out.println("set geeklist id to '" + configManager.getResultConfig().geeklistId + "'"); | |||
| } | |||
| catch (NumberFormatException ex) { | |||
| MessageDialog.openError(parent.getShell(), "Input error", "GeeklistId must be a whole number."); | |||
| } | |||
| } | |||
| }); | |||
| cbGeeklistId.addFocusListener(new FocusListener() { | |||
| @Override | |||
| public void focusLost(FocusEvent e) { | |||
| setGeeklistId(Integer.getInteger(cbGeeklistId.getText())); | |||
| System.out.println("set geeklist id to '" + configManager.getResultConfig().geeklistId + "'"); | |||
| try { | |||
| setGeeklistId(Integer.parseInt(cbGeeklistId.getText())); | |||
| System.out.println("set geeklist id to '" + configManager.getResultConfig().geeklistId + "'"); | |||
| } | |||
| catch (NumberFormatException ex) { | |||
| MessageDialog.openError(parent.getShell(), "Input error", "GeeklistId must be a whole number."); | |||
| } | |||
| } | |||
| @Override | |||
| @@ -1,54 +0,0 @@ | |||
| package xyz.veronie.bgg.ui.filters; | |||
| import java.util.HashMap; | |||
| import org.eclipse.e4.core.services.events.IEventBroker; | |||
| import org.eclipse.swt.SWT; | |||
| import org.eclipse.swt.events.SelectionAdapter; | |||
| import org.eclipse.swt.events.SelectionEvent; | |||
| import org.eclipse.swt.layout.GridData; | |||
| import org.eclipse.swt.layout.GridLayout; | |||
| import org.eclipse.swt.widgets.Button; | |||
| import org.eclipse.swt.widgets.Composite; | |||
| import org.eclipse.swt.widgets.Group; | |||
| import xyz.veronie.bgg.result.ResultConfigManager; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| import xyz.veronie.bgg.types.Subtype; | |||
| import xyz.veronie.bgg.types.SubtypeEvent; | |||
| public class SubtypeGroup { | |||
| private HashMap<Subtype, Button> buttons; | |||
| public void create(Composite parent, IEventBroker eventBroker, ResultConfigManager configManager) { | |||
| Group gSubtype = new Group(parent, SWT.LEFT); | |||
| gSubtype.setText("Subtypes"); | |||
| gSubtype.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); | |||
| gSubtype.setLayout(new GridLayout(1, false)); | |||
| buttons = new HashMap<Subtype, Button>(); | |||
| for (Subtype st : Subtype.values()) { | |||
| Button bb = new Button(gSubtype, SWT.CHECK); | |||
| bb.setText(st.toString()); | |||
| bb.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); | |||
| // init | |||
| HashMap<Subtype, Boolean> configuredTypes = configManager.getResultConfig().subTypes; | |||
| bb.setSelection(configuredTypes.get(st)); | |||
| bb.addSelectionListener(new SelectionAdapter() | |||
| { | |||
| @Override | |||
| public void widgetSelected(SelectionEvent e) | |||
| { | |||
| SubtypeEvent stEvent = new SubtypeEvent(); | |||
| stEvent.subtype = st; | |||
| stEvent.checked = bb.getSelection(); | |||
| eventBroker.send(EventConstants.TOPIC_SUBTYPE_CHANGED, stEvent); | |||
| } | |||
| }); | |||
| buttons.put(st, bb); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,7 +1,10 @@ | |||
| package xyz.veronie.bgg.ui.parts; | |||
| import javax.annotation.PostConstruct; | |||
| import javax.inject.Inject; | |||
| import org.eclipse.e4.core.di.annotations.Optional; | |||
| import org.eclipse.e4.ui.di.UIEventTopic; | |||
| import org.eclipse.jface.viewers.ArrayContentProvider; | |||
| import org.eclipse.jface.viewers.ColumnLabelProvider; | |||
| import org.eclipse.jface.viewers.TableViewer; | |||
| @@ -15,10 +18,11 @@ import org.eclipse.swt.widgets.TableColumn; | |||
| import xyz.veronie.bgg.result.ThingMetaData; | |||
| import xyz.veronie.bgg.result.ThingProvider; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| public class BggResultPart { | |||
| private TableViewer viewer; | |||
| @PostConstruct | |||
| public void createControls(Composite parent) { | |||
| Composite main = new Composite(parent, SWT.FILL); | |||
| @@ -61,79 +65,19 @@ public class BggResultPart { | |||
| // This will create the columns for the table | |||
| private void createColumns(final Composite parent, final TableViewer viewer) { | |||
| String[] titles = { "Id", "Rating", "Image", "Thumb", "comment", "other Id", "User name" }; | |||
| int[] bounds = { 100, 100, 100, 100, 100, 100, 100 }; | |||
| // First column id | |||
| TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| ThingMetaData t = (ThingMetaData) element; | |||
| return String.valueOf(t.getId()); | |||
| } | |||
| }); | |||
| // Second column rating | |||
| col = createTableViewerColumn(titles[1], bounds[1], 1); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| ThingMetaData t = (ThingMetaData) element; | |||
| return String.valueOf(t.getRating()); | |||
| } | |||
| }); | |||
| // now img url | |||
| col = createTableViewerColumn(titles[2], bounds[2], 2); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| ThingMetaData t = (ThingMetaData) element; | |||
| return t.getImgURL(); | |||
| } | |||
| }); | |||
| // thumb url | |||
| col = createTableViewerColumn(titles[3], bounds[3], 3); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| ThingMetaData t = (ThingMetaData) element; | |||
| return t.getThumbURL(); | |||
| } | |||
| }); | |||
| String[] titles = ThingMetaData.getTitles(); | |||
| int[] bounds = { 100, 100, 100, 100, 100, 100 }; | |||
| // comment | |||
| col = createTableViewerColumn(titles[4], bounds[4], 4); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| ThingMetaData t = (ThingMetaData) element; | |||
| return t.getComment(); | |||
| } | |||
| }); | |||
| // other id | |||
| col = createTableViewerColumn(titles[5], bounds[5], 5); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| ThingMetaData t = (ThingMetaData) element; | |||
| return String.valueOf(t.getOtherId()); | |||
| } | |||
| }); | |||
| // username | |||
| col = createTableViewerColumn(titles[6], bounds[6], 6); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| ThingMetaData t = (ThingMetaData) element; | |||
| return String.valueOf(t.getUsername()); | |||
| } | |||
| }); | |||
| for(int i = 0; i < titles.length; ++i) { | |||
| TableViewerColumn col = createTableViewerColumn(titles[i], bounds[i], i); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| ThingMetaData t = (ThingMetaData) element; | |||
| return t.getField((int)col.getColumn().getData()); | |||
| } | |||
| }); | |||
| } | |||
| } | |||
| private TableViewerColumn createTableViewerColumn(String title, int bound, final int colNumber) { | |||
| @@ -144,6 +88,7 @@ public class BggResultPart { | |||
| column.setWidth(bound); | |||
| column.setResizable(true); | |||
| column.setMoveable(true); | |||
| column.setData(colNumber); | |||
| return viewerColumn; | |||
| } | |||
| @@ -154,5 +99,16 @@ public class BggResultPart { | |||
| public void setFocus() { | |||
| viewer.getControl().setFocus(); | |||
| } | |||
| @Inject | |||
| @Optional | |||
| private void subscribeTopicResultChanged | |||
| (@UIEventTopic(EventConstants.TOPIC_RESULT_CHANGED) | |||
| String empty) { | |||
| System.out.println("TOPIC_RESULT_CHANGED"); | |||
| viewer.setInput(ThingProvider.INSTANCE.getThingMetas()); | |||
| viewer.refresh(); | |||
| } | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| package xyz.veronie.bgg.ui.parts; | |||
| import java.util.Arrays; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import javax.annotation.PostConstruct; | |||
| @@ -26,17 +26,21 @@ import org.eclipse.swt.widgets.Display; | |||
| import org.eclipse.swt.widgets.Group; | |||
| import org.eclipse.swt.widgets.Label; | |||
| import xyz.veronie.bgg.result.BggApi; | |||
| import xyz.veronie.bgg.result.ResultConfig; | |||
| import xyz.veronie.bgg.result.ResultConfigManager; | |||
| import xyz.veronie.bgg.result.ThingMetaData; | |||
| import xyz.veronie.bgg.result.ThingProvider; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| import xyz.veronie.bgg.types.ResultAction; | |||
| import xyz.veronie.bgg.types.SourceFilter; | |||
| import xyz.veronie.bgg.types.Subtype; | |||
| import xyz.veronie.bgg.ui.filters.AgeSourceFilter; | |||
| import xyz.veronie.bgg.ui.filters.BggUserSourceFilter; | |||
| import xyz.veronie.bgg.ui.filters.FamilySourceFilter; | |||
| import xyz.veronie.bgg.ui.filters.GeeklistSourceFilter; | |||
| import xyz.veronie.bgg.ui.filters.RankSourceFilter; | |||
| import xyz.veronie.bgg.ui.filters.SearchSourceFilter; | |||
| import xyz.veronie.bgg.ui.filters.SubtypeGroup; | |||
| import xyz.veronie.bgg.ui.filters.YearSourceFilter; | |||
| @@ -53,6 +57,8 @@ public class LoadFromBggPart { | |||
| // inject all source filter composites | |||
| @Inject private BggUserSourceFilter bggUserSourceFilter; | |||
| @Inject private GeeklistSourceFilter geeklistSourceFilter; | |||
| @Inject private FamilySourceFilter familySourceFilter; | |||
| @Inject private BggApi bggApi; | |||
| @PostConstruct | |||
| public void createControls(Composite parent) { | |||
| @@ -80,9 +86,10 @@ public class LoadFromBggPart { | |||
| ComboViewer cbSource = new ComboViewer(dlConfigGroup, SWT.READ_ONLY); | |||
| cbSource.setContentProvider(ArrayContentProvider.getInstance()); | |||
| List<SourceFilter> sources = Arrays.asList(new SourceFilter[] { | |||
| SourceFilter.BGG_USER, SourceFilter.GEEKLIST, SourceFilter.FAMILY, | |||
| SourceFilter.RANK, SourceFilter.YEAR, SourceFilter.AGE, SourceFilter.SEARCH }); | |||
| List<SourceFilter> sources = new ArrayList<SourceFilter>(); | |||
| for(SourceFilter sf : SourceFilter.values()) { | |||
| sources.add(sf); | |||
| } | |||
| cbSource.setInput(sources); | |||
| // TODO: implement all the sources | |||
| @@ -90,14 +97,27 @@ public class LoadFromBggPart { | |||
| // listener is configured further below | |||
| // choose the bgg sub-site | |||
| // choose the thing sub-type | |||
| Label lblSubtype = new Label(dlConfigGroup, SWT.LEFT); | |||
| lblSubtype.setText("Subtypes: "); | |||
| lblSubtype.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, false)); | |||
| SubtypeGroup gSubtypes = new SubtypeGroup(); | |||
| gSubtypes.create(dlConfigGroup, eventBroker, configManager); | |||
| ComboViewer cbSubtypes = new ComboViewer(dlConfigGroup, SWT.READ_ONLY); | |||
| cbSubtypes.setContentProvider(ArrayContentProvider.getInstance()); | |||
| List<Subtype> subtypes = new ArrayList<Subtype>(); | |||
| for (Subtype st : Subtype.values()) { | |||
| subtypes.add(st); | |||
| } | |||
| cbSubtypes.setInput(subtypes); | |||
| cbSubtypes.setSelection(new StructuredSelection(configManager.getResultConfig().subtype)); | |||
| cbSubtypes.addSelectionChangedListener(new ISelectionChangedListener() { | |||
| @Override | |||
| public void selectionChanged(SelectionChangedEvent event) { | |||
| IStructuredSelection selection = (IStructuredSelection) event.getSelection(); | |||
| eventBroker.send(EventConstants.TOPIC_SUBTYPE_CHANGED, selection.getFirstElement()); | |||
| } | |||
| }); | |||
| // choose action on result list | |||
| Label lblAct = new Label(dlConfigGroup, SWT.LEFT); | |||
| lblAct.setText("Action on result: "); | |||
| @@ -105,13 +125,13 @@ public class LoadFromBggPart { | |||
| ComboViewer cbAct = new ComboViewer(dlConfigGroup, SWT.READ_ONLY); | |||
| cbAct.setContentProvider(ArrayContentProvider.getInstance()); | |||
| List<ResultAction> actions = Arrays.asList(new ResultAction[] { | |||
| ResultAction.ADD, ResultAction.REP, ResultAction.SUB, | |||
| ResultAction.AND, ResultAction.MIS }); | |||
| List<ResultAction> actions = new ArrayList<ResultAction>(); | |||
| for(ResultAction act : ResultAction.values()) { | |||
| actions.add(act); | |||
| } | |||
| cbAct.setInput(actions); | |||
| cbAct.setSelection(new StructuredSelection(configManager.getResultConfig().action)); | |||
| cbAct.addSelectionChangedListener(new ISelectionChangedListener() { | |||
| @Override | |||
| public void selectionChanged(SelectionChangedEvent event) { | |||
| IStructuredSelection selection = (IStructuredSelection) event.getSelection(); | |||
| @@ -156,21 +176,45 @@ public class LoadFromBggPart { | |||
| @Override | |||
| public void widgetSelected(SelectionEvent e) { | |||
| System.out.println("Downloading " + cbSource.getSelection().toString()); | |||
| ResultConfig resultConfig = configManager.getResultConfig(); | |||
| IStructuredSelection selection = (IStructuredSelection) cbSource.getSelection(); | |||
| if(selection.size() == 0) return; | |||
| if(selection.getFirstElement() == SourceFilter.BGG_USER) { | |||
| String user = configManager.getResultConfig().user; | |||
| String user = resultConfig.user; | |||
| if(user == null || user.isEmpty()) { | |||
| System.out.println("Please enter a user name."); | |||
| return; | |||
| } else { | |||
| System.out.println("...for user '" + user + "'"); | |||
| ArrayList<ThingMetaData> thingMetas = bggApi.getThingsForUser(user); | |||
| ThingProvider.INSTANCE.setThingMetas(thingMetas); | |||
| eventBroker.send(EventConstants.TOPIC_RESULT_CHANGED, ""); | |||
| } | |||
| System.out.println("...for user '" + user + "'"); | |||
| } else if(selection.getFirstElement() == SourceFilter.GEEKLIST) { | |||
| System.out.println("...for geeklist id '" + configManager.getResultConfig().geeklistId + "'"); | |||
| Integer geeklistId = resultConfig.geeklistId; | |||
| if(geeklistId == null) { | |||
| System.out.println("Please enter a geeklist id."); | |||
| return; | |||
| } else { | |||
| System.out.println("...for geeklist id '" + geeklistId + "'"); | |||
| ArrayList<ThingMetaData> thingMetas = bggApi.getThingsForGeeklist(geeklistId); | |||
| ThingProvider.INSTANCE.setThingMetas(thingMetas); | |||
| eventBroker.send(EventConstants.TOPIC_RESULT_CHANGED, ""); | |||
| } | |||
| } else if(selection.getFirstElement() == SourceFilter.FAMILY) { | |||
| System.out.println("...for family id '" + FamilySourceFilter.getFamilyId() + "'"); | |||
| Integer familyId = resultConfig.familyId; | |||
| if(familyId == null) { | |||
| System.out.println("Please enter a family id."); | |||
| return; | |||
| } else { | |||
| System.out.println("...for family id '" + familyId + "'"); | |||
| //ArrayList<ThingMetaData> thingMetas = bggApi.getThingsForFamily(familyId); | |||
| //ThingProvider.INSTANCE.setThingMetas(thingMetas); | |||
| //eventBroker.send(EventConstants.TOPIC_RESULT_CHANGED, ""); | |||
| } | |||
| } | |||
| } | |||
| }); | |||
| @@ -202,7 +246,7 @@ public class LoadFromBggPart { | |||
| break; | |||
| case FAMILY: | |||
| System.out.println("construct " + elem); | |||
| FamilySourceFilter.create(parent, SWT.FILL); | |||
| familySourceFilter.create(parent, SWT.FILL); | |||
| break; | |||
| case RANK: | |||
| RankSourceFilter.create(parent, SWT.FILL); | |||