Implemented fetching of thing lists.pull/2/head
| @@ -3,8 +3,9 @@ | |||
| <children xsi:type="basic:TrimmedWindow" xmi:id="_QDxdgEqSEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.trimmedwindow.main" label="BGG Tool Another" width="700" height="700"> | |||
| <children xsi:type="basic:PartStack" xmi:id="_uw_Z4F9REeuvNqpgCDWpdQ" elementId="xyz.veronie.bgg.ui.partstack.0"> | |||
| <children xsi:type="basic:Part" xmi:id="_co2toF9CEeuvNqpgCDWpdQ" elementId="xyz.veronie.bgg.ui.part.batmain" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.parts.BatMain" label="Home"/> | |||
| <children xsi:type="basic:Part" xmi:id="_JsfvUF9YEeuvNqpgCDWpdQ" elementId="xyz.veronie.bgg.ui.part.fetch" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.parts.FetchPart" label="Fetch"/> | |||
| <children xsi:type="basic:Part" xmi:id="_ACADIF9cEeutIcDDGAEMFw" elementId="xyz.veronie.bgg.ui.part.prepare" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.parts.PreparePart" label="Prepare"/> | |||
| <children xsi:type="basic:Part" xmi:id="_JsfvUF9YEeuvNqpgCDWpdQ" elementId="xyz.veronie.bgg.ui.part.fetch" visible="false" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.parts.FetchPart" label="Fetch"> | |||
| <tags>View</tags> | |||
| </children> | |||
| </children> | |||
| <mainMenu xmi:id="_wtXeQEs0EeqGDvPDavxXPQ" elementId="org.eclipse.ui.main.menu"/> | |||
| <trimBars xmi:id="_I6MLEFv-EeqNgfoocONcgg" elementId="xyz.veronie.bgg.ui.trimbar.bottom" side="Bottom"> | |||
| @@ -14,6 +15,7 @@ | |||
| <children xsi:type="menu:ToolBar" xmi:id="_AX9yMIucEeqEpr8WQZMuMQ" elementId="xyz.veronie.bgg.ui.toolbar.testbar"/> | |||
| </trimBars> | |||
| </children> | |||
| <handlers xmi:id="_a0tuEGAUEeuNUoCJDLJTzQ" elementId="xyz.veronie.bgg.ui.handler.save" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.handlers.HandleSaveGamelist" command="_lA5t8F9TEeuvNqpgCDWpdQ"/> | |||
| <commands xmi:id="_lA5t8F9TEeuvNqpgCDWpdQ" elementId="xyz.veronie.bgg.ui.command.save" commandName="Save" description="save game list"/> | |||
| <addons xmi:id="_Lw_ZsUqSEeqT5sxfmvJ5Tg" elementId="org.eclipse.e4.core.commands.service" contributionURI="bundleclass://org.eclipse.e4.core.commands/org.eclipse.e4.core.commands.CommandServiceAddon"/> | |||
| <addons xmi:id="_Lw_ZskqSEeqT5sxfmvJ5Tg" elementId="org.eclipse.e4.ui.contexts.service" contributionURI="bundleclass://org.eclipse.e4.ui.services/org.eclipse.e4.ui.services.ContextServiceAddon"/> | |||
| @@ -20,6 +20,7 @@ Require-Bundle: org.eclipse.core.runtime, | |||
| Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | |||
| Import-Package: javax.annotation;version="1.0.0";resolution:=optional, | |||
| javax.inject;version="1.0.0", | |||
| org.eclipse.e4.core.commands, | |||
| org.eclipse.e4.ui.model.application.descriptor.basic, | |||
| org.eclipse.e4.ui.model.application.ui.basic | |||
| Automatic-Module-Name: de.wt.secondtry | |||
| @@ -1,5 +1,6 @@ | |||
| package xyz.veronie.bgg.localdb; | |||
| import java.sql.SQLException; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| @@ -21,7 +22,7 @@ public class LocalDbAdapterService { | |||
| /// Add a list of things with the given name (overwriting the old one) | |||
| // TODO: handle ask before overwrite | |||
| public void storeThingList(List<Thing> things, String name) { | |||
| public void storeThingList(List<Thing> things, String name) throws SQLException { | |||
| sqliteController.deleteThingList(name); | |||
| sqliteController.createThingListIfNotExists(name); | |||
| sqliteController.addToThingList(name, things); | |||
| @@ -112,102 +112,95 @@ public class SqliteController { | |||
| } | |||
| } | |||
| public void deleteThingList(String name) { | |||
| public void deleteThingList(String name) throws SQLException { | |||
| if(connection == null) { | |||
| throw new RuntimeException("ERROR: Couldn't create Schema, connection is null."); | |||
| } | |||
| try { | |||
| if(!hasThingList(name)) { | |||
| System.err.println("INFO: deleteThingList: Thing list '" + name + "' does not exist."); | |||
| return; | |||
| } | |||
| int listId = getThingListId(name); | |||
| Statement stmt = connection.createStatement(); | |||
| // insert new thing list if one with that name does not exist already | |||
| System.err.println("INFO: deleteThingList: Deleting thing list '" + name + "'."); | |||
| stmt.execute("DELETE FROM ThingListToThing where ListId = " + Integer.toString(listId) + ";"); | |||
| stmt.execute("DELETE FROM ThingList where name = '" + name + "');"); | |||
| stmt.close(); | |||
| } catch (SQLException e) { | |||
| System.err.println("deleteThingList: Couldn't delete thing list with handle " + name); | |||
| e.printStackTrace(); | |||
| } | |||
| if(!hasThingList(name)) { | |||
| System.err.println("INFO: deleteThingList: Thing list '" + name + "' does not exist."); | |||
| return; | |||
| } | |||
| int listId = getThingListId(name); | |||
| Statement stmt = connection.createStatement(); | |||
| // insert new thing list if one with that name does not exist already | |||
| System.err.println("INFO: deleteThingList: Deleting thing list '" + name + "'."); | |||
| stmt.execute("DELETE FROM ThingListToThing where ListId = " + Integer.toString(listId) + ";"); | |||
| stmt.execute("DELETE FROM ThingList where ListId = " + Integer.toString(listId) + ";"); | |||
| stmt.close(); | |||
| } | |||
| public boolean hasThingList(String name) { | |||
| public boolean hasThingList(String name) throws SQLException { | |||
| if(getThingListId(name) != -1) { | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| public int getThingListId(String name) { | |||
| public int getThingListId(String name) throws SQLException { | |||
| if(connection == null) { | |||
| throw new RuntimeException("ERROR: Couldn't create Schema, connection is null."); | |||
| } | |||
| int listId = -1; | |||
| Statement stmt = connection.createStatement(); | |||
| try { | |||
| Statement stmt = connection.createStatement(); | |||
| String str = "SELECT ListId from ThingList where name = '" + name + "'"; | |||
| System.out.println("TRACE: executeQuery: " + str); | |||
| ResultSet res = stmt.executeQuery(str); | |||
| if(res.getFetchSize() == 1) { | |||
| listId = res.getInt(1); | |||
| System.out.println("DEBUG: ListId = " + listId); | |||
| return listId; | |||
| } | |||
| } catch (SQLException e) { | |||
| System.err.println("Couldn't add to thing list with handle " + name); | |||
| e.printStackTrace(); | |||
| String countStr = "SELECT COUNT(*) as count from ThingList where name = '" + name + "'"; | |||
| ResultSet res = stmt.executeQuery(countStr); | |||
| int count = res.getInt("count"); | |||
| if(count == 0) { | |||
| stmt.close(); | |||
| return -1; | |||
| } | |||
| String str = "SELECT ListId from ThingList where name = '" + name + "'"; | |||
| System.out.println("TRACE: executeQuery: " + str); | |||
| res = stmt.executeQuery(str); | |||
| int listId = res.getInt(1); | |||
| System.out.println("DEBUG: ListId = " + listId); | |||
| stmt.close(); | |||
| return listId; | |||
| } | |||
| public void addToThingList(String name, List<Thing> things) { | |||
| public void addToThingList(String name, List<Thing> things) throws SQLException { | |||
| if(connection == null) { | |||
| throw new RuntimeException("ERROR: Couldn't create Schema, connection is null."); | |||
| } | |||
| try { | |||
| int listId = getThingListId(name); | |||
| int listId = getThingListId(name); | |||
| PreparedStatement thingStatement = connection | |||
| .prepareStatement("INSERT INTO Thing VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT REPLACE;"); | |||
| PreparedStatement listToThingStatement = connection | |||
| .prepareStatement("INSERT INTO ThingListToThing VALUES (?, ?)"); | |||
| for (Thing thing : things) { | |||
| ThingMetaData metaData = thing.getMetaData(); | |||
| thingStatement.setInt(1, metaData.getId()); | |||
| thingStatement.setString(2, metaData.getName()); | |||
| thingStatement.setString(3, metaData.getImgURL()); | |||
| thingStatement.setString(4, metaData.getThumbURL()); | |||
| thingStatement.setString(5, metaData.getComment()); | |||
| PreparedStatement thingStatement = connection | |||
| .prepareStatement("INSERT OR REPLACE INTO Thing VALUES (?, ?, ?, ?, ?, ?);"); | |||
| PreparedStatement listToThingStatement = connection | |||
| .prepareStatement("INSERT INTO ThingListToThing VALUES (?, ?);"); | |||
| for (Thing thing : things) { | |||
| ThingMetaData metaData = thing.getMetaData(); | |||
| thingStatement.setInt(1, metaData.getId()); | |||
| thingStatement.setString(2, metaData.getName()); | |||
| thingStatement.setString(3, metaData.getImgURL()); | |||
| thingStatement.setString(4, metaData.getThumbURL()); | |||
| thingStatement.setString(5, metaData.getComment()); | |||
| if(metaData.getNumPlays() != null) { | |||
| thingStatement.setInt(6, metaData.getNumPlays()); | |||
| thingStatement.addBatch(); | |||
| // get generated id | |||
| ResultSet keys = thingStatement.getGeneratedKeys(); | |||
| int thingId = keys.getInt(0); | |||
| listToThingStatement.setInt(0, listId); | |||
| listToThingStatement.setInt(1, thingId); | |||
| listToThingStatement.addBatch(); | |||
| } else { | |||
| thingStatement.setNull(6, java.sql.Types.INTEGER); | |||
| } | |||
| connection.setAutoCommit(false); | |||
| thingStatement.executeBatch(); | |||
| connection.setAutoCommit(true); | |||
| } catch (SQLException e) { | |||
| System.err.println("Couldn't add to thing list with handle " + name); | |||
| e.printStackTrace(); | |||
| } | |||
| thingStatement.execute(); | |||
| // get generated id | |||
| ResultSet keys = thingStatement.getGeneratedKeys(); | |||
| int thingId = keys.getInt(1); | |||
| System.out.println("TRACE: ThingId = " + thingId + ", ListId = " + listId); | |||
| listToThingStatement.setInt(1, listId); | |||
| listToThingStatement.setInt(2, thingId); | |||
| listToThingStatement.addBatch(); | |||
| } | |||
| connection.setAutoCommit(false); | |||
| listToThingStatement.executeBatch(); | |||
| connection.setAutoCommit(true); | |||
| } | |||
| @@ -30,6 +30,7 @@ import org.xml.sax.SAXException; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| import xyz.veronie.bgg.types.FamilyType; | |||
| import xyz.veronie.bgg.types.FilterFlagState; | |||
| import xyz.veronie.bgg.types.SourceFilter; | |||
| import xyz.veronie.bgg.types.Subtype; | |||
| import xyz.veronie.bgg.types.UserFlag; | |||
| @@ -48,6 +49,20 @@ public class BggApi { | |||
| private static int RETRIES = 5; | |||
| public ArrayList<Thing> getThings(SourceFilter source, Object id) { | |||
| switch(source) { | |||
| default: | |||
| case BGG_USER: | |||
| return getThingsForUser((String)id); | |||
| case FAMILY: | |||
| return getThingsForFamily((Integer)id); | |||
| case GEEKLIST: | |||
| return getThingsForGeeklist((Integer)id); | |||
| } | |||
| } | |||
| public ArrayList<Thing> getThingsForUser(String user) throws IllegalArgumentException { | |||
| ResultConfig resultConfig = configManager.getResultConfig(); | |||
| @@ -84,7 +99,6 @@ public class BggApi { | |||
| return getThings(urlStr.toString()); | |||
| } | |||
| public ArrayList<Thing> getThingsForGeeklist(int geeklistId) throws IllegalArgumentException { | |||
| ResultConfig resultConfig = configManager.getResultConfig(); | |||
| @@ -4,7 +4,6 @@ import java.util.HashMap; | |||
| import xyz.veronie.bgg.types.FamilyType; | |||
| import xyz.veronie.bgg.types.FilterFlagState; | |||
| import xyz.veronie.bgg.types.ResultAction; | |||
| import xyz.veronie.bgg.types.SourceFilter; | |||
| import xyz.veronie.bgg.types.Subtype; | |||
| import xyz.veronie.bgg.types.UserFlag; | |||
| @@ -15,7 +14,6 @@ public class ResultConfig { | |||
| // TODO: integrate different filters (or extend?) | |||
| public SourceFilter source = SourceFilter.BGG_USER; | |||
| public ResultAction action = ResultAction.ONLY_NEW; | |||
| public Subtype subtype = Subtype.BOARDGAME; | |||
| // bgg user filter settings | |||
| @@ -35,9 +33,6 @@ public class ResultConfig { | |||
| public Integer familyId = null; | |||
| public FamilyType familyType = FamilyType.ALL; | |||
| // TODO: add others | |||
| @Override | |||
| public String toString() { | |||
| switch(source) { | |||
| @@ -10,7 +10,6 @@ import org.eclipse.e4.ui.di.UIEventTopic; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| import xyz.veronie.bgg.types.FamilyType; | |||
| import xyz.veronie.bgg.types.ResultAction; | |||
| import xyz.veronie.bgg.types.SourceFilter; | |||
| import xyz.veronie.bgg.types.Subtype; | |||
| import xyz.veronie.bgg.types.UserFlagEvent; | |||
| @@ -68,15 +67,6 @@ public class ResultConfigManager { | |||
| System.out.println("TOPIC_USERFLAG_CHANGED: " + e.flag + " " + e.state); | |||
| } | |||
| @Inject | |||
| @Optional | |||
| private void subscribeTopicResultActionChanged | |||
| (@UIEventTopic(EventConstants.TOPIC_ACTION_CHANGED) | |||
| ResultAction action) { | |||
| getResultConfig().action = action; | |||
| System.out.println("TOPIC_ACTION_CHANGED: action = " + action); | |||
| } | |||
| @Inject | |||
| @Optional | |||
| private void subscribeTopicResultGeeklistChanged | |||
| @@ -26,7 +26,7 @@ public class Thing { | |||
| private Image thumbImage; | |||
| public static final String IdHeader = "ID"; | |||
| public static final String ThumbHeader = ""; | |||
| public static final String ThumbHeader = "Thumbnail"; | |||
| public static final String NameHeader = "Name"; | |||
| public static final String DetailsHeader = "Details"; | |||
| public static final String ExportFlagHeader = "Export"; | |||
| @@ -98,13 +98,13 @@ public class Thing { | |||
| switch(idx) { | |||
| case 0: | |||
| returnStr = String.valueOf(this.id); | |||
| returnStr = ""; | |||
| break; | |||
| case 1: | |||
| returnStr = ""; | |||
| returnStr = this.getMetaData().getName(); | |||
| break; | |||
| case 2: | |||
| returnStr = this.getMetaData().getName(); | |||
| returnStr = String.valueOf(this.id); | |||
| break; | |||
| case 3: | |||
| returnStr = (this.getDetails() != null) ? "yes" : "no"; | |||
| @@ -78,7 +78,7 @@ public class ThingMetaData implements java.io.Serializable { | |||
| this.thumbURL = thumbURL); | |||
| } | |||
| public int getNumPlays() { | |||
| public Integer getNumPlays() { | |||
| return numPlays; | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| package xyz.veronie.bgg.result; | |||
| import java.sql.SQLException; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import java.util.function.Predicate; | |||
| @@ -87,10 +88,13 @@ public class ThingProvider { | |||
| } | |||
| /// store current list in DB | |||
| public void storeList(String listName) { | |||
| public void storeList(String listName) throws SQLException { | |||
| localDbAdapterService.storeThingList(this.things, listName); | |||
| } | |||
| public int numberOfThings() { | |||
| return things.size(); | |||
| } | |||
| // return the current list of ids | |||
| public List<Thing> getThings() { | |||
| @@ -10,8 +10,6 @@ public interface EventConstants { | |||
| String TOPIC_USERFLAG_CHANGED = "CONFIG_CHANGED/USERFLAG"; | |||
| String TOPIC_ACTION_CHANGED = "CONFIG_CHANGED/ACTION"; | |||
| String TOPIC_USER_CHANGED = "CONFIG_CHANGED/USER"; | |||
| String TOPIC_GEEKLIST_CHANGED = "CONFIG_CHANGED/GEEKLIST"; | |||
| @@ -32,5 +30,6 @@ public interface EventConstants { | |||
| String TOPIC_THING_SELECTION = "SELECTION_CHANGED"; | |||
| String TOPIC_THINGS_SAVED = "THINGS_SAVED"; | |||
| } | |||
| @@ -2,9 +2,9 @@ package xyz.veronie.bgg.types; | |||
| public enum ResultAction { | |||
| ADD("add to"), | |||
| REP("replace"), | |||
| SUB("subtract from"), | |||
| AND("intersect with"), | |||
| REPLACE("replace"), | |||
| SUBTRACT("subtract from"), | |||
| INTERSECT("intersect with"), | |||
| ONLY_NEW("keep if not in"); | |||
| private String name; | |||
| @@ -8,6 +8,7 @@ import org.eclipse.swt.events.ModifyListener; | |||
| import org.eclipse.swt.graphics.Point; | |||
| 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.Control; | |||
| import org.eclipse.swt.widgets.Label; | |||
| @@ -22,6 +23,8 @@ public class SaveGameListDialog extends Dialog { | |||
| private String entryString; | |||
| private Button btnOk; | |||
| /** | |||
| * Create the dialog. | |||
| * @param parentShell | |||
| @@ -61,6 +64,8 @@ public class SaveGameListDialog extends Dialog { | |||
| public void modifyText(ModifyEvent e) { | |||
| Text t = (Text) e.widget; | |||
| entryString = t.getText(); | |||
| boolean enableOk = entryString != null && !entryString.isEmpty(); | |||
| btnOk.setEnabled(enableOk); | |||
| } | |||
| }); | |||
| textField.setFont(SWTResourceManager.getFont("Segoe UI", 11, SWT.NORMAL)); | |||
| @@ -76,7 +81,10 @@ public class SaveGameListDialog extends Dialog { | |||
| @Override | |||
| protected void createButtonsForButtonBar(Composite parent) { | |||
| parent.setBackground(BatColors.getBackgroundColor()); | |||
| createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); | |||
| btnOk = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); | |||
| btnOk.setEnabled(false); | |||
| createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); | |||
| } | |||
| @@ -1,43 +1,59 @@ | |||
| package xyz.veronie.bgg.ui.handlers; | |||
| import javax.inject.Inject; | |||
| import org.eclipse.e4.core.di.annotations.CanExecute; | |||
| import org.eclipse.e4.core.di.annotations.Execute; | |||
| import org.eclipse.e4.core.services.events.IEventBroker; | |||
| import org.eclipse.jface.dialogs.Dialog; | |||
| import org.eclipse.swt.SWT; | |||
| import org.eclipse.swt.widgets.MessageBox; | |||
| import org.eclipse.swt.widgets.Shell; | |||
| import xyz.veronie.bgg.result.ThingProvider; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| import xyz.veronie.bgg.ui.dialogs.SaveGameListDialog; | |||
| public class HandleSaveGamelist { | |||
| // @Inject | |||
| @Inject | |||
| ThingProvider thingProvider; | |||
| public HandleSaveGamelist(ThingProvider thingProvider) { | |||
| this.thingProvider = thingProvider; | |||
| public HandleSaveGamelist() { | |||
| } | |||
| @Execute | |||
| public void execute(Shell shell) { | |||
| public void execute(Shell shell, IEventBroker eventBroker) { | |||
| // TODO: disable save if list is empty | |||
| if(thingProvider.numberOfThings() == 0) { | |||
| MessageBox msgBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK); | |||
| msgBox.setMessage("To save an empty game list would be like drawing from an empty deck."); | |||
| msgBox.open(); | |||
| return; | |||
| } | |||
| SaveGameListDialog saveDialog = new SaveGameListDialog(shell); | |||
| saveDialog.open(); | |||
| int returnCode = saveDialog.getReturnCode(); | |||
| if(returnCode == Dialog.OK) { | |||
| String listName = saveDialog.getEntryText(); | |||
| if(listName == null || listName == "") { | |||
| MessageBox msgBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK); | |||
| try { | |||
| thingProvider.storeList(listName); | |||
| eventBroker.post(EventConstants.TOPIC_THINGS_SAVED, listName); | |||
| } | |||
| catch (Exception e) { | |||
| MessageBox msgBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); | |||
| msgBox.setMessage("Could not save game list."); | |||
| msgBox.open(); | |||
| } | |||
| thingProvider.storeList(listName); | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| // ignore cancel | |||
| } | |||
| @@ -3,4 +3,5 @@ package xyz.veronie.bgg.ui.helpers; | |||
| public class Constants { | |||
| public static final String TMP_PREFIX = "BggToolAnother"; | |||
| public static final String THUMB_CACHE_DIR = "thumbs"; | |||
| public static final String APP_NAME = "BGG Tool Another"; | |||
| } | |||
| @@ -6,6 +6,9 @@ import java.util.List; | |||
| import javax.annotation.PostConstruct; | |||
| import javax.inject.Inject; | |||
| import org.eclipse.core.commands.ParameterizedCommand; | |||
| import org.eclipse.e4.core.commands.ECommandService; | |||
| import org.eclipse.e4.core.commands.EHandlerService; | |||
| import org.eclipse.e4.core.di.annotations.Optional; | |||
| import org.eclipse.e4.core.services.events.IEventBroker; | |||
| import org.eclipse.e4.ui.di.UIEventTopic; | |||
| @@ -39,10 +42,23 @@ import org.eclipse.wb.swt.SWTResourceManager; | |||
| import xyz.veronie.bgg.result.Thing; | |||
| import xyz.veronie.bgg.result.ThingProvider; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| import xyz.veronie.bgg.ui.handlers.HandleSaveGamelist; | |||
| import xyz.veronie.bgg.ui.helpers.BatColors; | |||
| import xyz.veronie.bgg.ui.helpers.BatLayouts; | |||
| // TODO: exchange only new and replace buttons | |||
| // TODO: remember config | |||
| // TODO: load thing list from DB | |||
| // TODO: image sizes | |||
| // TODO: display current thinglist name | |||
| // TODO: fetch details from BGG | |||
| // TODO: export to results.txt format | |||
| // TODO: generate PDF with nandeck | |||
| // TODO: handle thing list overwrite | |||
| // TODO: Display selection details on game | |||
| @SuppressWarnings("restriction") | |||
| public class BatMain { | |||
| private Table tableGameList; | |||
| private TableViewer tableViewer; | |||
| @@ -52,14 +68,19 @@ public class BatMain { | |||
| @Inject | |||
| private IEventBroker eventBroker; | |||
| private Label lblResultStatus; | |||
| private Button btnSave; | |||
| private Button btnUndo; | |||
| private Button btnExport; | |||
| @Inject | |||
| public BatMain() { | |||
| } | |||
| public BatMain() {} | |||
| @PostConstruct | |||
| public void postConstruct(Composite parent, MApplication application, EPartService partService, EModelService modelService) { | |||
| public void postConstruct(Composite parent, MApplication application, | |||
| EPartService partService, EModelService modelService, | |||
| ECommandService commandService, EHandlerService handlerService) | |||
| { | |||
| Color bgColor = BatColors.getBackgroundColor(); | |||
| parent.setBackground(bgColor); | |||
| @@ -99,8 +120,10 @@ public class BatMain { | |||
| List<MPart> parts = modelService.findElements(application, "xyz.veronie.bgg.ui.part.fetch", MPart.class); | |||
| if(parts != null && parts.size() >= 1) { | |||
| MPart fetchPart = parts.get(0); | |||
| partService.showPart(fetchPart, PartState.CREATE); | |||
| // partService.showPart(fetchPart, PartState.CREATE); | |||
| fetchPart.setVisible(true); | |||
| partService.showPart(fetchPart, PartState.ACTIVATE); | |||
| // modelService.detach(fetchPart, x, y, width, height); | |||
| } | |||
| } | |||
| }); | |||
| @@ -110,14 +133,14 @@ public class BatMain { | |||
| btnFetch.setBackground(SWTResourceManager.getColor(SWT.COLOR_TRANSPARENT)); | |||
| btnFetch.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_Download_60x60.png")); | |||
| Button btnSave = new Button(buttonRow, SWT.NONE); | |||
| btnSave = new Button(buttonRow, SWT.NONE); | |||
| btnSave.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| public void mouseUp(MouseEvent e) { | |||
| // TODO: find a loose coupling instead. Where is EHandlerService??? | |||
| HandleSaveGamelist handleSaveGameList = new HandleSaveGamelist(thingProvider); | |||
| if(handleSaveGameList.canExecute()) { | |||
| handleSaveGameList.execute(parent.getShell()); | |||
| ParameterizedCommand cmd = | |||
| commandService.createCommand("xyz.veronie.bgg.ui.command.save", null); | |||
| if (handlerService.canExecute(cmd)){ | |||
| handlerService.executeHandler(cmd); | |||
| } | |||
| } | |||
| }); | |||
| @@ -125,21 +148,24 @@ public class BatMain { | |||
| btnSave.setBackground(SWTResourceManager.getColor(SWT.COLOR_TRANSPARENT)); | |||
| btnSave.setForeground(SWTResourceManager.getColor(SWT.COLOR_TRANSPARENT)); | |||
| btnSave.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_Save_60x60.png")); | |||
| btnSave.setEnabled(false); | |||
| Button btnLoad = new Button(buttonRow, SWT.NONE); | |||
| btnLoad.setBackground(SWTResourceManager.getColor(SWT.COLOR_TRANSPARENT)); | |||
| btnLoad.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_open_60x60.png")); | |||
| btnLoad.setToolTipText("Load list of games"); | |||
| Button btnUndo = new Button(buttonRow, SWT.NONE); | |||
| btnUndo = new Button(buttonRow, SWT.NONE); | |||
| btnUndo.setToolTipText("Undo game list operation"); | |||
| btnUndo.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_Undo_60x60.png")); | |||
| btnUndo.setBackground(SWTResourceManager.getColor(SWT.COLOR_TRANSPARENT)); | |||
| btnUndo.setEnabled(false); | |||
| Button btnExport = new Button(buttonRow, SWT.NONE); | |||
| btnExport = new Button(buttonRow, SWT.NONE); | |||
| btnExport.setBackground(SWTResourceManager.getColor(SWT.COLOR_TRANSPARENT)); | |||
| btnExport.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/export_nandeck_60x60.png")); | |||
| btnExport.setToolTipText("Export for nanDeck"); | |||
| btnExport.setEnabled(false); | |||
| tableViewer = new TableViewer(main, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI); | |||
| tableGameList = tableViewer.getTable(); | |||
| @@ -177,7 +203,7 @@ public class BatMain { | |||
| BatLayouts.applyStandardSpacing(gl_statusRow); | |||
| statusRow.setLayout(gl_statusRow); | |||
| Label lblResultStatus = new Label(statusRow, SWT.NONE); | |||
| lblResultStatus = new Label(statusRow, SWT.NONE); | |||
| lblResultStatus.setText("0 items"); | |||
| } | |||
| @@ -194,18 +220,9 @@ public class BatMain { | |||
| // This will create the columns for the table | |||
| private void createColumns(final TableViewer viewer) { | |||
| // https://stackoverflow.com/questions/12641354/putting-an-image-in-to-a-jface-table-cell-is-causing-gap-for-image-to-appear-in | |||
| TableViewerColumn col = createTableViewerColumn(Thing.IdHeader, 250, 0); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| Thing t = (Thing) element; | |||
| return t.getField((int)col.getColumn().getData()); | |||
| } | |||
| }); | |||
| TableViewerColumn col2 = createTableViewerColumn(Thing.ThumbHeader, 150, 1); | |||
| col2.setLabelProvider(new ColumnLabelProvider() { | |||
| TableViewerColumn colThumbnail = createTableViewerColumn(Thing.ThumbHeader, 150, 0); | |||
| colThumbnail.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public Image getImage(Object element) { | |||
| Thing t = (Thing) element; | |||
| @@ -219,15 +236,27 @@ public class BatMain { | |||
| } | |||
| }); | |||
| TableViewerColumn colName = createTableViewerColumn(Thing.NameHeader, 400, 1); | |||
| colName.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| Thing t = (Thing) element; | |||
| return t.getField((int)colName.getColumn().getData()); | |||
| } | |||
| }); | |||
| TableViewerColumn col3 = createTableViewerColumn(Thing.NameHeader, 400, 2); | |||
| col3.setLabelProvider(new ColumnLabelProvider() { | |||
| // https://stackoverflow.com/questions/12641354/putting-an-image-in-to-a-jface-table-cell-is-causing-gap-for-image-to-appear-in | |||
| TableViewerColumn colId = createTableViewerColumn(Thing.IdHeader, 100, 2); | |||
| colId.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| Thing t = (Thing) element; | |||
| return t.getField((int)col3.getColumn().getData()); | |||
| return t.getField((int)colId.getColumn().getData()); | |||
| } | |||
| }); | |||
| } | |||
| private TableViewerColumn createTableViewerColumn(String title, int bound, final int colNumber) { | |||
| @@ -265,10 +294,24 @@ public class BatMain { | |||
| List<Thing> things = thingProvider.getThings(); | |||
| tableViewer.setInput(things); | |||
| tableViewer.refresh(true); | |||
| // if(things != null) { | |||
| // statsLabel.setText(Integer.toString(things.size()) + " items"); | |||
| // statsLabel.redraw(); | |||
| // } | |||
| if(things != null) { | |||
| btnSave.setEnabled(things.size() != 0); | |||
| btnExport.setEnabled(things.size() != 0); | |||
| lblResultStatus.setText(Integer.toString(things.size()) + " items"); | |||
| lblResultStatus.redraw(); | |||
| lblResultStatus.getParent().layout(); | |||
| } | |||
| } | |||
| @Inject | |||
| @Optional | |||
| private void subscribeTopicThingsSaved | |||
| (@UIEventTopic(EventConstants.TOPIC_THINGS_SAVED) | |||
| String listName) { | |||
| System.out.println("TOPIC_THINGS_SAVED for game list '" + listName + "'."); | |||
| btnSave.setEnabled(false); | |||
| // TODO: set list name in title | |||
| // TODO: implement undo | |||
| } | |||
| } | |||
| @@ -1,182 +0,0 @@ | |||
| package xyz.veronie.bgg.ui.parts; | |||
| import java.util.List; | |||
| import javax.annotation.PostConstruct; | |||
| import javax.inject.Inject; | |||
| import org.eclipse.e4.core.di.annotations.Optional; | |||
| import org.eclipse.e4.core.services.events.IEventBroker; | |||
| import org.eclipse.e4.ui.di.UIEventTopic; | |||
| import org.eclipse.jface.viewers.ArrayContentProvider; | |||
| import org.eclipse.jface.viewers.ColumnLabelProvider; | |||
| import org.eclipse.jface.viewers.ISelectionChangedListener; | |||
| import org.eclipse.jface.viewers.IStructuredSelection; | |||
| import org.eclipse.jface.viewers.OwnerDrawLabelProvider; | |||
| import org.eclipse.jface.viewers.SelectionChangedEvent; | |||
| import org.eclipse.jface.viewers.TableViewer; | |||
| import org.eclipse.jface.viewers.TableViewerColumn; | |||
| import org.eclipse.swt.SWT; | |||
| import org.eclipse.swt.graphics.Image; | |||
| import org.eclipse.swt.graphics.Rectangle; | |||
| import org.eclipse.swt.layout.GridData; | |||
| import org.eclipse.swt.layout.GridLayout; | |||
| import org.eclipse.swt.widgets.Composite; | |||
| import org.eclipse.swt.widgets.Event; | |||
| import org.eclipse.swt.widgets.Label; | |||
| import org.eclipse.swt.widgets.Table; | |||
| import org.eclipse.swt.widgets.TableColumn; | |||
| import org.eclipse.swt.widgets.TableItem; | |||
| import xyz.veronie.bgg.result.Thing; | |||
| import xyz.veronie.bgg.result.ThingProvider; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| public class BggResultPart { | |||
| private TableViewer viewer; | |||
| private Label statsLabel; | |||
| @Inject | |||
| private ThingProvider thingProvider; | |||
| @Inject | |||
| private IEventBroker eventBroker; | |||
| @PostConstruct | |||
| public void createContents(Composite parent) { | |||
| Composite main = new Composite(parent, SWT.FILL); | |||
| main.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); | |||
| GridLayout layout = new GridLayout(2, false); | |||
| main.setLayout(layout); | |||
| createViewer(main); | |||
| statsLabel = new Label(main, SWT.FILL); | |||
| statsLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); | |||
| statsLabel.setText("0 items"); | |||
| } | |||
| private void createViewer(Composite parent) { | |||
| viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | |||
| | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER ); | |||
| createColumns(parent, viewer); | |||
| final Table table = viewer.getTable(); | |||
| table.setHeaderVisible(true); | |||
| table.setLinesVisible(true); | |||
| viewer.setContentProvider(new ArrayContentProvider()); | |||
| // Get the content for the viewer, setInput will call getElements in the | |||
| // contentProvider | |||
| viewer.setInput(thingProvider.getThings()); | |||
| // make the selection available to other views | |||
| // TODO: getSite().setSelectionProvider(viewer); | |||
| // Set the sorter for the table | |||
| // Layout the viewer | |||
| GridData gridData = new GridData(); | |||
| gridData.verticalAlignment = GridData.FILL; | |||
| gridData.grabExcessHorizontalSpace = true; | |||
| gridData.grabExcessVerticalSpace = true; | |||
| gridData.horizontalAlignment = GridData.FILL; | |||
| gridData.horizontalSpan = 2; | |||
| viewer.getControl().setLayoutData(gridData); | |||
| viewer.addSelectionChangedListener(new ISelectionChangedListener() { | |||
| @Override | |||
| public void selectionChanged(SelectionChangedEvent event) { | |||
| IStructuredSelection selection = viewer.getStructuredSelection(); | |||
| Thing thing = (Thing)selection.getFirstElement(); | |||
| eventBroker.send(EventConstants.TOPIC_THING_SELECTION, thing); | |||
| } | |||
| }); | |||
| } | |||
| public TableViewer getViewer() { | |||
| return viewer; | |||
| } | |||
| // This will create the columns for the table | |||
| private void createColumns(final Composite parent, final TableViewer viewer) { | |||
| // https://stackoverflow.com/questions/12641354/putting-an-image-in-to-a-jface-table-cell-is-causing-gap-for-image-to-appear-in | |||
| TableViewerColumn col = createTableViewerColumn(Thing.IdHeader, 250, 0); | |||
| col.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| Thing t = (Thing) element; | |||
| return t.getField((int)col.getColumn().getData()); | |||
| } | |||
| }); | |||
| TableViewerColumn col2 = createTableViewerColumn(Thing.ThumbHeader, 150, 1); | |||
| col2.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public Image getImage(Object element) { | |||
| Thing t = (Thing) element; | |||
| Image img = t.getThumbnail(); | |||
| return img; | |||
| } | |||
| @Override | |||
| public String getText(Object element) { | |||
| return ""; | |||
| } | |||
| }); | |||
| TableViewerColumn col3 = createTableViewerColumn(Thing.NameHeader, 400, 2); | |||
| col3.setLabelProvider(new ColumnLabelProvider() { | |||
| @Override | |||
| public String getText(Object element) { | |||
| Thing t = (Thing) element; | |||
| return t.getField((int)col3.getColumn().getData()); | |||
| } | |||
| }); | |||
| } | |||
| private TableViewerColumn createTableViewerColumn(String title, int bound, final int colNumber) { | |||
| final TableViewerColumn viewerColumn = new TableViewerColumn(viewer, | |||
| SWT.NONE); | |||
| final TableColumn column = viewerColumn.getColumn(); | |||
| column.setText(title); | |||
| column.setWidth(bound); | |||
| column.setAlignment(SWT.LEFT); | |||
| column.setResizable(true); | |||
| column.setMoveable(true); | |||
| column.setData(colNumber); | |||
| return viewerColumn; | |||
| } | |||
| /** | |||
| * Passing the focus request to the viewer's control. | |||
| */ | |||
| public void setFocus() { | |||
| viewer.getControl().setFocus(); | |||
| } | |||
| @Inject | |||
| @Optional | |||
| private void subscribeTopicResultChanged | |||
| (@UIEventTopic(EventConstants.TOPIC_RESULT_CHANGED) | |||
| String empty) { | |||
| System.out.println("TOPIC_RESULT_CHANGED"); | |||
| List<Thing> things = thingProvider.getThings(); | |||
| viewer.setInput(things); | |||
| viewer.refresh(true); | |||
| if(things != null) { | |||
| statsLabel.setText(Integer.toString(things.size()) + " items"); | |||
| statsLabel.redraw(); | |||
| } | |||
| } | |||
| } | |||
| @@ -2,17 +2,21 @@ | |||
| package xyz.veronie.bgg.ui.parts; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import javax.annotation.PostConstruct; | |||
| import javax.inject.Inject; | |||
| import org.eclipse.e4.core.services.events.IEventBroker; | |||
| import org.eclipse.e4.ui.model.application.MApplication; | |||
| import org.eclipse.e4.ui.model.application.ui.basic.MPart; | |||
| import org.eclipse.e4.ui.workbench.modeling.EModelService; | |||
| import org.eclipse.e4.ui.workbench.modeling.EPartService; | |||
| import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState; | |||
| import org.eclipse.jface.dialogs.MessageDialog; | |||
| import org.eclipse.jface.viewers.IStructuredSelection; | |||
| import org.eclipse.swt.SWT; | |||
| import org.eclipse.swt.events.MouseAdapter; | |||
| import org.eclipse.swt.events.MouseEvent; | |||
| import org.eclipse.swt.events.SelectionEvent; | |||
| import org.eclipse.swt.layout.GridData; | |||
| import org.eclipse.swt.layout.GridLayout; | |||
| import org.eclipse.swt.widgets.Button; | |||
| @@ -27,13 +31,13 @@ import xyz.veronie.bgg.result.ResultConfigManager; | |||
| import xyz.veronie.bgg.result.Thing; | |||
| 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.ui.filters.BggUserSourceFilter; | |||
| import xyz.veronie.bgg.ui.filters.FamilySourceFilter; | |||
| import xyz.veronie.bgg.ui.filters.GeeklistSourceFilter; | |||
| import xyz.veronie.bgg.ui.helpers.BatColors; | |||
| import xyz.veronie.bgg.ui.helpers.BatLayouts; | |||
| import org.eclipse.swt.widgets.Label; | |||
| public class FetchPart { | |||
| @@ -48,6 +52,15 @@ public class FetchPart { | |||
| @Inject | |||
| private IEventBroker eventBroker; | |||
| @Inject | |||
| private MApplication application; | |||
| @Inject | |||
| private EModelService modelService; | |||
| @Inject | |||
| private EPartService partService; | |||
| @Inject | |||
| private ThingProvider thingProvider; | |||
| @@ -57,7 +70,6 @@ public class FetchPart { | |||
| private Button btnBggUser; | |||
| private Button btnFamily; | |||
| private Button btnGeeklist; | |||
| private SourceFilter source; | |||
| private Composite main; | |||
| private Group filterGroup; | |||
| @@ -131,41 +143,68 @@ public class FetchPart { | |||
| applyComposite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false, 1, 1)); | |||
| Button btnOnlyNew = new Button(applyComposite, SWT.NONE); | |||
| btnOnlyNew.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/only_new_60x60.png")); | |||
| btnOnlyNew.setToolTipText("Keep only new"); | |||
| btnOnlyNew.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| public void mouseUp(MouseEvent e) { | |||
| fetchEntries(ResultAction.ONLY_NEW); | |||
| } | |||
| }); | |||
| btnOnlyNew.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/only_new_60x60.png")); | |||
| btnOnlyNew.setToolTipText("Keep only new"); | |||
| Button btnReplace = new Button(applyComposite, SWT.NONE); | |||
| btnReplace.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_replace_60x60.png")); | |||
| btnReplace.setToolTipText("Replace"); | |||
| btnReplace.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| public void mouseUp(MouseEvent e) { | |||
| fetchEntries(ResultAction.REPLACE); | |||
| } | |||
| }); | |||
| Button btnAdd = new Button(applyComposite, SWT.NONE); | |||
| btnAdd.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_add_60x60.png")); | |||
| btnAdd.setToolTipText("Add"); | |||
| btnAdd.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| public void mouseUp(MouseEvent e) { | |||
| fetchEntries(ResultAction.ADD); | |||
| } | |||
| }); | |||
| Button btnSubtract = new Button(applyComposite, SWT.NONE); | |||
| btnSubtract.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_subtract_60x60.png")); | |||
| btnSubtract.setToolTipText("Subtract"); | |||
| btnSubtract.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| public void mouseUp(MouseEvent e) { | |||
| fetchEntries(ResultAction.SUBTRACT); | |||
| } | |||
| }); | |||
| Button btnIntersect = new Button(applyComposite, SWT.NONE); | |||
| btnIntersect.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_intersect_60x60.png")); | |||
| btnIntersect.setToolTipText("Intersect"); | |||
| btnIntersect.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| public void mouseUp(MouseEvent e) { | |||
| fetchEntries(ResultAction.INTERSECT); | |||
| } | |||
| }); | |||
| // init filter using config manager | |||
| source = configManager.getResultConfig().source; | |||
| SourceFilter source = configManager.getResultConfig().source; | |||
| selectFilter(source); | |||
| showFilter(filterGroup, source); | |||
| } | |||
| private void selectFilter(SourceFilter source) { | |||
| configManager.getResultConfig().source = source; | |||
| switch(source) { | |||
| default: | |||
| case BGG_USER: | |||
| @@ -175,7 +214,7 @@ public class FetchPart { | |||
| btnGeeklist.setBackground(null); | |||
| break; | |||
| case FAMILY: | |||
| btnBggUser.setFocus(); | |||
| btnFamily.setFocus(); | |||
| btnBggUser.setBackground(null); | |||
| btnFamily.setBackground(BatColors.getButtonBgColor()); | |||
| btnGeeklist.setBackground(null); | |||
| @@ -188,7 +227,7 @@ public class FetchPart { | |||
| break; | |||
| } | |||
| showFilter(filterGroup, source); | |||
| eventBroker.send(EventConstants.TOPIC_ACTION_CHANGED, source); | |||
| eventBroker.send(EventConstants.TOPIC_SOURCE_CHANGED, source); | |||
| } | |||
| @@ -221,70 +260,65 @@ public class FetchPart { | |||
| } | |||
| private void checkEntry() { | |||
| private void fetchEntries(ResultAction action) { | |||
| Object fetchId = getFetchId(); | |||
| if(fetchId == null) return; | |||
| try { | |||
| SourceFilter source = configManager.getResultConfig().source; | |||
| eventBroker.send(EventConstants.TOPIC_STATUS, "Fetching " + source.toString() + " '" + fetchId + "'..."); | |||
| ArrayList<Thing> things = bggApi.getThings(source, fetchId); | |||
| useThingsOnResult(things, action); | |||
| goToHomePart(); | |||
| } | |||
| catch(IllegalArgumentException ex) { | |||
| MessageDialog.openError(main.getShell(), "", ex.getMessage()); | |||
| } | |||
| } | |||
| private Object getFetchId() { | |||
| ResultConfig resultConfig = configManager.getResultConfig(); | |||
| SourceFilter source = configManager.getResultConfig().source; | |||
| if(source == SourceFilter.BGG_USER) { | |||
| if(source == SourceFilter.BGG_USER) { | |||
| String user = resultConfig.user; | |||
| if(user == null || user.isEmpty()) { | |||
| MessageDialog.openError(main.getShell(), "", "Please enter a user name."); | |||
| return; | |||
| } else { | |||
| eventBroker.send(EventConstants.TOPIC_STATUS, "Fetching " + source.toString() + " '" + user + "'..."); | |||
| try { | |||
| ArrayList<Thing> things = bggApi.getThingsForUser(user); | |||
| useThingsOnResult(things); | |||
| } | |||
| catch(IllegalArgumentException ex) { | |||
| MessageDialog.openError(main.getShell(), "", ex.getMessage()); | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| return user; | |||
| } else if(source == SourceFilter.GEEKLIST) { | |||
| Integer geeklistId = resultConfig.geeklistId; | |||
| if(geeklistId == null) { | |||
| MessageDialog.openError(main.getShell(), "", "Please enter a geeklist id."); | |||
| return; | |||
| } else { | |||
| eventBroker.send(EventConstants.TOPIC_STATUS, "Fetching for geeklist id '" + geeklistId + "'"); | |||
| try { | |||
| ArrayList<Thing> things = bggApi.getThingsForGeeklist(geeklistId); | |||
| useThingsOnResult(things); | |||
| } | |||
| catch(IllegalArgumentException ex) { | |||
| MessageDialog.openError(main.getShell(), "", ex.getMessage()); | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| return geeklistId; | |||
| } else if(source == SourceFilter.FAMILY) { | |||
| Integer familyId = resultConfig.familyId; | |||
| if(familyId == null) { | |||
| MessageDialog.openError(main.getShell(), "", "Please enter a family id."); | |||
| return; | |||
| } else { | |||
| eventBroker.send(EventConstants.TOPIC_STATUS, "Fetching for family id '" + familyId + "'"); | |||
| try { | |||
| ArrayList<Thing> things = bggApi.getThingsForFamily(familyId); | |||
| useThingsOnResult(things); | |||
| } | |||
| catch(IllegalArgumentException ex) { | |||
| MessageDialog.openError(main.getShell(), "", ex.getMessage()); | |||
| } | |||
| return null; | |||
| } | |||
| return familyId; | |||
| } | |||
| } | |||
| private void useThingsOnResult(ArrayList<Thing> things) { | |||
| switch(configManager.getResultConfig().action) { | |||
| case REP: | |||
| return null; | |||
| } | |||
| private void useThingsOnResult(ArrayList<Thing> things, ResultAction action) { | |||
| switch(action) { | |||
| case REPLACE: | |||
| thingProvider.replaceThings(things); | |||
| break; | |||
| case ADD: | |||
| thingProvider.addThings(things); | |||
| break; | |||
| case SUB: | |||
| case SUBTRACT: | |||
| thingProvider.subtractThings(things); | |||
| break; | |||
| case AND: | |||
| case INTERSECT: | |||
| thingProvider.intersectThings(things); | |||
| break; | |||
| case ONLY_NEW: | |||
| @@ -295,4 +329,14 @@ public class FetchPart { | |||
| eventBroker.send(EventConstants.TOPIC_STATUS, "Fetched " + Integer.toString(things.size()) + " things."); | |||
| } | |||
| private void goToHomePart() { | |||
| // TODO Auto-generated method stub | |||
| List<MPart> parts = modelService.findElements(application, "xyz.veronie.bgg.ui.part.batmain", MPart.class); | |||
| if(parts != null && parts.size() >= 1) { | |||
| MPart fetchPart = parts.get(0); | |||
| partService.showPart(fetchPart, PartState.ACTIVATE); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,312 +0,0 @@ | |||
| package xyz.veronie.bgg.ui.parts; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import javax.annotation.PostConstruct; | |||
| import javax.inject.Inject; | |||
| import org.eclipse.e4.core.services.events.IEventBroker; | |||
| import org.eclipse.e4.ui.workbench.modeling.EPartService; | |||
| import org.eclipse.jface.dialogs.MessageDialog; | |||
| import org.eclipse.jface.viewers.ArrayContentProvider; | |||
| import org.eclipse.jface.viewers.ComboViewer; | |||
| import org.eclipse.jface.viewers.ISelectionChangedListener; | |||
| import org.eclipse.jface.viewers.IStructuredSelection; | |||
| import org.eclipse.jface.viewers.SelectionChangedEvent; | |||
| import org.eclipse.jface.viewers.StructuredSelection; | |||
| 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.Control; | |||
| 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.Thing; | |||
| 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.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.YearSourceFilter; | |||
| import xyz.veronie.bgg.ui.helpers.CommonControls; | |||
| /// Has controls to download a list of thing IDs (+some meta info) from BGG. | |||
| /// There are different ways to configure which IDs to retrieve. | |||
| public class PreparePart { | |||
| @Inject | |||
| EPartService partService; | |||
| @Inject | |||
| private ResultConfigManager configManager; | |||
| @Inject | |||
| private IEventBroker eventBroker; | |||
| @Inject | |||
| private ThingProvider thingProvider; | |||
| // inject all source filter composites | |||
| @Inject private BggUserSourceFilter bggUserSourceFilter; | |||
| @Inject private GeeklistSourceFilter geeklistSourceFilter; | |||
| @Inject private FamilySourceFilter familySourceFilter; | |||
| @Inject private AgeSourceFilter ageSourceFilter; | |||
| @Inject private RankSourceFilter rankSourceFilter; | |||
| @Inject private YearSourceFilter yearSourceFilter; | |||
| @Inject private SearchSourceFilter searchSourceFilter; | |||
| @Inject private BggApi bggApi; | |||
| private Composite mainComposite; | |||
| @PostConstruct | |||
| public void createControls(Composite parent) { | |||
| mainComposite = new Composite(parent, SWT.FILL); | |||
| mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); | |||
| mainComposite.setLayout(new GridLayout(1, false)); | |||
| // // contains configuration options for download of the bgg thing ID list | |||
| // Group dlConfigGroup = new Group(main, SWT.SHADOW_ETCHED_IN); | |||
| // GridData configGrid = new GridData(SWT.FILL, SWT.FILL, true, true); | |||
| // dlConfigGroup.setText("Configure filters..."); | |||
| // dlConfigGroup.setLayoutData(configGrid); | |||
| // GridLayout layoutG = new GridLayout(2, false); | |||
| // dlConfigGroup.setLayout(layoutG); | |||
| Composite sourceSelectCompo = new Composite(mainComposite, SWT.FILL); | |||
| sourceSelectCompo.setLayout(new GridLayout(2, false)); | |||
| Label lblSource = new Label(sourceSelectCompo, SWT.LEFT); | |||
| lblSource.setText("Source: "); | |||
| lblSource.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false)); | |||
| // choose the bgg data source | |||
| ComboViewer cbSource = new ComboViewer(sourceSelectCompo, SWT.READ_ONLY); | |||
| cbSource.getCombo().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); | |||
| cbSource.setContentProvider(ArrayContentProvider.getInstance()); | |||
| List<SourceFilter> sources = new ArrayList<SourceFilter>(); | |||
| for(SourceFilter sf : SourceFilter.values()) { | |||
| sources.add(sf); | |||
| } | |||
| cbSource.setInput(sources); | |||
| // TODO: implement all the sources | |||
| cbSource.setSelection(new StructuredSelection(configManager.getResultConfig().source)); | |||
| // listener is configured further below | |||
| CommonControls.makeEmptySpace(mainComposite, 2); | |||
| // area to display filter controls | |||
| Group gFilters = new Group(mainComposite, SWT.SHADOW_ETCHED_IN); | |||
| gFilters.setText(""); | |||
| gFilters.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); | |||
| showFilter(gFilters, (IStructuredSelection)cbSource.getSelection()); // set content to initial selection | |||
| cbSource.addSelectionChangedListener(new ISelectionChangedListener() { // later, its content will be set via the dropdown | |||
| @Override | |||
| public void selectionChanged(SelectionChangedEvent event) { | |||
| IStructuredSelection selection = (IStructuredSelection) event.getSelection(); | |||
| // ASK: this is strange to me. Why is filterComposite known INSIDE a free function? | |||
| showFilter(gFilters, selection); | |||
| eventBroker.send(EventConstants.TOPIC_SOURCE_CHANGED, selection.getFirstElement()); | |||
| } | |||
| }); | |||
| // next row | |||
| Composite fetchCompo = new Composite(mainComposite, SWT.FILL); | |||
| fetchCompo.setLayout(new GridLayout(4, false)); | |||
| // choose action on result list | |||
| Button btDownload = new Button(fetchCompo, SWT.PUSH); | |||
| GridData gd = new GridData(SWT.LEFT, SWT.FILL, false, false); | |||
| btDownload.setLayoutData(gd); | |||
| btDownload.setText("Fetch"); | |||
| btDownload.addSelectionListener(new SelectionAdapter() { | |||
| @Override | |||
| public void widgetSelected(SelectionEvent e) { | |||
| ResultConfig resultConfig = configManager.getResultConfig(); | |||
| IStructuredSelection selection = (IStructuredSelection) cbSource.getSelection(); | |||
| if(selection.size() == 0) return; | |||
| if(selection.getFirstElement() == SourceFilter.BGG_USER) { | |||
| String user = resultConfig.user; | |||
| if(user == null || user.isEmpty()) { | |||
| MessageDialog.openError(mainComposite.getShell(), "", "Please enter a user name."); | |||
| return; | |||
| } else { | |||
| eventBroker.send(EventConstants.TOPIC_STATUS, "Fetching " + selection.getFirstElement().toString() + " '" + user + "'..."); | |||
| try { | |||
| ArrayList<Thing> things = bggApi.getThingsForUser(user); | |||
| useThingsOnResult(things); | |||
| } | |||
| catch(IllegalArgumentException ex) { | |||
| MessageDialog.openError(mainComposite.getShell(), "", ex.getMessage()); | |||
| } | |||
| } | |||
| } else if(selection.getFirstElement() == SourceFilter.GEEKLIST) { | |||
| Integer geeklistId = resultConfig.geeklistId; | |||
| if(geeklistId == null) { | |||
| MessageDialog.openError(mainComposite.getShell(), "", "Please enter a geeklist id."); | |||
| return; | |||
| } else { | |||
| eventBroker.send(EventConstants.TOPIC_STATUS, "Fetching for geeklist id '" + geeklistId + "'"); | |||
| try { | |||
| ArrayList<Thing> things = bggApi.getThingsForGeeklist(geeklistId); | |||
| useThingsOnResult(things); | |||
| } | |||
| catch(IllegalArgumentException ex) { | |||
| MessageDialog.openError(mainComposite.getShell(), "", ex.getMessage()); | |||
| } | |||
| } | |||
| } else if(selection.getFirstElement() == SourceFilter.FAMILY) { | |||
| Integer familyId = resultConfig.familyId; | |||
| if(familyId == null) { | |||
| MessageDialog.openError(mainComposite.getShell(), "", "Please enter a family id."); | |||
| return; | |||
| } else { | |||
| eventBroker.send(EventConstants.TOPIC_STATUS, "Fetching for family id '" + familyId + "'"); | |||
| try { | |||
| ArrayList<Thing> things = bggApi.getThingsForFamily(familyId); | |||
| useThingsOnResult(things); | |||
| } | |||
| catch(IllegalArgumentException ex) { | |||
| MessageDialog.openError(mainComposite.getShell(), "", ex.getMessage()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private void useThingsOnResult(ArrayList<Thing> things) { | |||
| switch(configManager.getResultConfig().action) { | |||
| case REP: | |||
| thingProvider.replaceThings(things); | |||
| break; | |||
| case ADD: | |||
| thingProvider.addThings(things); | |||
| break; | |||
| case SUB: | |||
| thingProvider.subtractThings(things); | |||
| break; | |||
| case AND: | |||
| thingProvider.intersectThings(things); | |||
| break; | |||
| case ONLY_NEW: | |||
| thingProvider.keepOnlyNew(things); | |||
| break; | |||
| } | |||
| eventBroker.send(EventConstants.TOPIC_RESULT_CHANGED, ""); | |||
| eventBroker.send(EventConstants.TOPIC_STATUS, "Fetched " + Integer.toString(things.size()) + " things."); | |||
| } | |||
| }); | |||
| Label lblAct = new Label(fetchCompo, SWT.LEFT); | |||
| lblAct.setText("and"); | |||
| lblAct.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, false, false)); | |||
| ComboViewer cbAct = new ComboViewer(fetchCompo, SWT.READ_ONLY); | |||
| GridData gdact = new GridData(SWT.FILL, SWT.FILL, false, false); | |||
| cbAct.getCombo().setLayoutData(gdact); | |||
| cbAct.setContentProvider(ArrayContentProvider.getInstance()); | |||
| 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(); | |||
| eventBroker.send(EventConstants.TOPIC_ACTION_CHANGED, selection.getFirstElement()); | |||
| } | |||
| }); | |||
| Label toResultLabel = new Label(fetchCompo, SWT.LEFT); | |||
| toResultLabel.setText("result"); | |||
| toResultLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); | |||
| mainComposite.pack(); | |||
| mainComposite.layout(); | |||
| } | |||
| /// show different filter controls depending on selection in cbSource ComboViewer | |||
| private void showFilter(Composite parent, IStructuredSelection selection) { | |||
| SourceFilter elem = (SourceFilter) selection.getFirstElement(); | |||
| // clean up | |||
| for(Control child : parent.getChildren()) { | |||
| child.dispose(); | |||
| } | |||
| // create a new filter area based on selection: | |||
| switch(elem) { | |||
| case BGG_USER: | |||
| System.out.println("construct " + elem); | |||
| bggUserSourceFilter.create(parent, SWT.FILL); | |||
| break; | |||
| case GEEKLIST: | |||
| System.out.println("construct " + elem); | |||
| geeklistSourceFilter.create(parent, SWT.FILL); | |||
| break; | |||
| case FAMILY: | |||
| System.out.println("construct " + elem); | |||
| familySourceFilter.create(parent, SWT.FILL); | |||
| break; | |||
| case RANK: | |||
| rankSourceFilter.create(parent, SWT.FILL); | |||
| break; | |||
| case YEAR: | |||
| yearSourceFilter.create(parent, SWT.FILL); | |||
| break; | |||
| case AGE: | |||
| ageSourceFilter.create(parent, SWT.FILL); | |||
| break; | |||
| case SEARCH: | |||
| searchSourceFilter.create(parent, SWT.FILL); | |||
| break; | |||
| default: | |||
| System.out.println("construct " + elem + " (not implemented yet, try another one)"); | |||
| } | |||
| parent.pack(); | |||
| mainComposite.pack(); | |||
| mainComposite.layout(true, true); | |||
| } | |||
| public static Display getDisplay() { | |||
| Display display = Display.getCurrent(); | |||
| // may be null if outside the UI thread | |||
| if (display == null) | |||
| display = Display.getDefault(); | |||
| return display; | |||
| } | |||
| } | |||
| @@ -12,22 +12,21 @@ public abstract class CenterImageLabelProvider extends OwnerDrawLabelProvider { | |||
| } | |||
| protected void paint(Event event, Object element) { | |||
| Image img = getImage(element); | |||
| if (img != null) { | |||
| Rectangle bounds = ((TableItem) event.item).getBounds(event.index); | |||
| Rectangle imgBounds = img.getBounds(); | |||
| bounds.width /= 2; | |||
| bounds.width -= imgBounds.width / 2; | |||
| bounds.height /= 2; | |||
| bounds.height -= imgBounds.height / 2; | |||
| int x = bounds.width > 0 ? bounds.x + bounds.width : bounds.x; | |||
| int y = bounds.height > 0 ? bounds.y + bounds.height : bounds.y; | |||
| event.gc.drawImage(img, x, y); | |||
| } | |||
| Image img = getImage(element); | |||
| if (img != null) { | |||
| Rectangle bounds = ((TableItem) event.item).getBounds(event.index); | |||
| Rectangle imgBounds = img.getBounds(); | |||
| bounds.width /= 2; | |||
| bounds.width -= imgBounds.width / 2; | |||
| bounds.height /= 2; | |||
| bounds.height -= imgBounds.height / 2; | |||
| int x = bounds.width > 0 ? bounds.x + bounds.width : bounds.x; | |||
| int y = bounds.height > 0 ? bounds.y + bounds.height : bounds.y; | |||
| event.gc.drawImage(img, x, y); | |||
| } | |||
| } | |||
| protected abstract Image getImage(Object element); | |||