@@ -13,5 +13,6 @@ | |||||
<attribute name="maven.pomderived" value="true"/> | <attribute name="maven.pomderived" value="true"/> | ||||
</attributes> | </attributes> | ||||
</classpathentry> | </classpathentry> | ||||
<classpathentry kind="lib" path="swing2swt.jar"/> | |||||
<classpathentry kind="output" path="target/classes"/> | <classpathentry kind="output" path="target/classes"/> | ||||
</classpath> | </classpath> |
@@ -1,30 +1,10 @@ | |||||
<?xml version="1.0" encoding="ASCII"?> | <?xml version="1.0" encoding="ASCII"?> | ||||
<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_Lw_ZsEqSEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.application"> | <application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_Lw_ZsEqSEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.application"> | ||||
<children xsi:type="basic:TrimmedWindow" xmi:id="_QDxdgEqSEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.trimmedwindow.main" label="BGG Tool Another" width="1600" height="900"> | |||||
<children xsi:type="basic:PartSashContainer" xmi:id="_B_h_UEqVEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.partsashcontainer.0"> | |||||
<children xsi:type="basic:PartSashContainer" xmi:id="_tbnr0EqTEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.partsashcontainer.main" horizontal="true"> | |||||
<children xsi:type="basic:PartSashContainer" xmi:id="_4NsHQEqTEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.partsashcontainer.left"> | |||||
<children xsi:type="basic:PartStack" xmi:id="_7KNiwEqTEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.partstack.leftupper" containerData="800"> | |||||
<children xsi:type="basic:Part" xmi:id="_9ocfwEqTEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.part.resultconfig" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.parts.PreparePart" label="Prepare"/> | |||||
</children> | |||||
<children xsi:type="basic:PartStack" xmi:id="_0MbRQEqTEeqT5sxfmvJ5Tg" elementId="de.wt.bgg.ui.partstack.rightupper" containerData="800"> | |||||
<children xsi:type="basic:Part" xmi:id="_-Mdy0EqTEeqT5sxfmvJ5Tg" elementId="de.wt.bgg.ui.part.gamesconfig" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.parts.DownloadThingDetailsPart" label="Download details"/> | |||||
</children> | |||||
</children> | |||||
<children xsi:type="basic:PartSashContainer" xmi:id="_AF1vQEqUEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.partsashcontainer.right"> | |||||
<children xsi:type="basic:PartStack" xmi:id="_0OB_gJ2wEeqjssfAjxHZ-w" elementId="xyz.veronie.bgg.ui.partstack.leftlower" containerData="800"> | |||||
<children xsi:type="basic:Part" xmi:id="_97XbwEqTEeqT5sxfmvJ5Tg" elementId="xyz.veronie.bgg.ui.part.resulttable" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.parts.BggResultPart" label="BGG Result"> | |||||
<toolbar xmi:id="_ZZOF8J3AEeqjssfAjxHZ-w" elementId="xyz.veronie.bgg.ui.toolbar.0"> | |||||
<children xsi:type="menu:DirectToolItem" xmi:id="_c42V4J29EeqjssfAjxHZ-w" elementId="xyz.veronie.bgg.ui.directtoolitem.saveResult" label="save result" iconURI="platform:/plugin/xyz.veronie.bgg.ui/icons/save-button.png" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.handlers.HandleSaveGamelist"/> | |||||
<children xsi:type="menu:DirectToolItem" xmi:id="_VeUlQFZdEeu8-NdCRpPGXA" elementId="xyz.veronie.bgg.ui.directtoolitem.openlist" label="open list" iconURI="platform:/plugin/xyz.veronie.bgg.ui/icons/folder-symbol.png"/> | |||||
</toolbar> | |||||
</children> | |||||
</children> | |||||
<children xsi:type="basic:PartStack" xmi:id="_2M6HAJ2wEeqjssfAjxHZ-w" elementId="xyz.veronie.bgg.ui.rightlower" containerData="200"> | |||||
<children xsi:type="basic:Part" xmi:id="_Ckm3wEqUEeqT5sxfmvJ5Tg" elementId="de.wt.bgg.ui.part.gamestable" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.parts.ThingListPart" label="Games list"/> | |||||
</children> | |||||
</children> | |||||
</children> | |||||
<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> | </children> | ||||
<mainMenu xmi:id="_wtXeQEs0EeqGDvPDavxXPQ" elementId="org.eclipse.ui.main.menu"/> | <mainMenu xmi:id="_wtXeQEs0EeqGDvPDavxXPQ" elementId="org.eclipse.ui.main.menu"/> | ||||
<trimBars xmi:id="_I6MLEFv-EeqNgfoocONcgg" elementId="xyz.veronie.bgg.ui.trimbar.bottom" side="Bottom"> | <trimBars xmi:id="_I6MLEFv-EeqNgfoocONcgg" elementId="xyz.veronie.bgg.ui.trimbar.bottom" side="Bottom"> | ||||
@@ -34,6 +14,7 @@ | |||||
<children xsi:type="menu:ToolBar" xmi:id="_AX9yMIucEeqEpr8WQZMuMQ" elementId="xyz.veronie.bgg.ui.toolbar.testbar"/> | <children xsi:type="menu:ToolBar" xmi:id="_AX9yMIucEeqEpr8WQZMuMQ" elementId="xyz.veronie.bgg.ui.toolbar.testbar"/> | ||||
</trimBars> | </trimBars> | ||||
</children> | </children> | ||||
<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_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"/> | <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"/> | ||||
<addons xmi:id="_Lw_Zs0qSEeqT5sxfmvJ5Tg" elementId="org.eclipse.e4.ui.bindings.service" contributionURI="bundleclass://org.eclipse.e4.ui.bindings/org.eclipse.e4.ui.bindings.BindingServiceAddon"/> | <addons xmi:id="_Lw_Zs0qSEeqT5sxfmvJ5Tg" elementId="org.eclipse.e4.ui.bindings.service" contributionURI="bundleclass://org.eclipse.e4.ui.bindings/org.eclipse.e4.ui.bindings.BindingServiceAddon"/> | ||||
@@ -3,6 +3,8 @@ Bundle-ManifestVersion: 2 | |||||
Bundle-Name: Secondtry | Bundle-Name: Secondtry | ||||
Bundle-SymbolicName: xyz.veronie.bgg.ui;singleton:=true | Bundle-SymbolicName: xyz.veronie.bgg.ui;singleton:=true | ||||
Bundle-Version: 1.0.0.qualifier | Bundle-Version: 1.0.0.qualifier | ||||
Bundle-ClassPath: lib/sqlite-jdbc-3.34.0.jar, | |||||
swing2swt.jar | |||||
Require-Bundle: org.eclipse.core.runtime, | Require-Bundle: org.eclipse.core.runtime, | ||||
org.eclipse.swt, | org.eclipse.swt, | ||||
org.eclipse.e4.core.di, | org.eclipse.e4.core.di, | ||||
@@ -15,9 +17,9 @@ Require-Bundle: org.eclipse.core.runtime, | |||||
org.eclipse.osgi.services, | org.eclipse.osgi.services, | ||||
javax.inject, | javax.inject, | ||||
org.eclipse.e4.ui.model.workbench | org.eclipse.e4.ui.model.workbench | ||||
Automatic-Module-Name: de.wt.secondtry | |||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | ||||
Import-Package: javax.inject;version="1.0.0", | |||||
Import-Package: javax.annotation;version="1.0.0";resolution:=optional, | |||||
javax.inject;version="1.0.0", | |||||
org.eclipse.e4.ui.model.application.descriptor.basic, | org.eclipse.e4.ui.model.application.descriptor.basic, | ||||
org.eclipse.e4.ui.model.application.ui.basic | org.eclipse.e4.ui.model.application.ui.basic | ||||
Bundle-ClassPath: lib/sqlite-jdbc-3.34.0.jar | |||||
Automatic-Module-Name: de.wt.secondtry |
@@ -0,0 +1,438 @@ | |||||
/******************************************************************************* | |||||
* Copyright (c) 2011 Google, Inc. and others | |||||
* All rights reserved. This program and the accompanying materials | |||||
* are made available under the terms of the Eclipse Public License v1.0 | |||||
* which accompanies this distribution, and is available at | |||||
* http://www.eclipse.org/legal/epl-v10.html | |||||
* | |||||
* Contributors: | |||||
* Google, Inc. - initial API and implementation | |||||
* Wim Jongman - 1.8 and higher compliance | |||||
*******************************************************************************/ | |||||
package org.eclipse.wb.swt; | |||||
import java.io.File; | |||||
import java.io.InputStream; | |||||
import java.lang.reflect.Constructor; | |||||
import java.lang.reflect.Method; | |||||
import java.net.MalformedURLException; | |||||
import java.net.URL; | |||||
import java.util.HashMap; | |||||
import java.util.Iterator; | |||||
import java.util.Map; | |||||
import org.eclipse.core.runtime.Platform; | |||||
import org.eclipse.jface.resource.CompositeImageDescriptor; | |||||
import org.eclipse.jface.resource.ImageDescriptor; | |||||
import org.eclipse.swt.graphics.Image; | |||||
import org.eclipse.swt.graphics.ImageData; | |||||
import org.eclipse.swt.graphics.ImageDataProvider; | |||||
import org.eclipse.swt.graphics.Point; | |||||
import org.eclipse.swt.graphics.Rectangle; | |||||
import org.osgi.framework.Bundle; | |||||
/** | |||||
* Utility class for managing OS resources associated with SWT/JFace controls | |||||
* such as colors, fonts, images, etc. | |||||
* | |||||
* This class is created automatically when you fiddle around with images and | |||||
* colors in WB. You might want to prevent your application from using this | |||||
* class and provide your own more effective means of resource caching. | |||||
* | |||||
* Even though this class can be used to manage these resources, if they are | |||||
* here for the duration of the application and not used then you still have an | |||||
* effective resource leak. | |||||
* | |||||
* Application code must explicitly invoke the <code>dispose()</code> method to | |||||
* release the operating system resources managed by cached objects when those | |||||
* objects and OS resources are no longer needed. | |||||
* | |||||
* This class may be freely distributed as part of any application or plugin. | |||||
* <p> | |||||
* | |||||
* @author scheglov_ke | |||||
* @author Dan Rubel | |||||
* @author Wim Jongman | |||||
*/ | |||||
public class ResourceManager extends SWTResourceManager { | |||||
/** | |||||
* The map where we store our images. | |||||
*/ | |||||
private static Map<ImageDescriptor, Image> m_descriptorImageMap = new HashMap<ImageDescriptor, Image>(); | |||||
/** | |||||
* Returns an {@link ImageDescriptor} stored in the file at the specified path | |||||
* relative to the specified class. | |||||
* | |||||
* @param clazz the {@link Class} relative to which to find the image | |||||
* descriptor. | |||||
* @param path the path to the image file. | |||||
* @return the {@link ImageDescriptor} stored in the file at the specified path. | |||||
*/ | |||||
public static ImageDescriptor getImageDescriptor(Class<?> clazz, String path) { | |||||
return ImageDescriptor.createFromFile(clazz, path); | |||||
} | |||||
/** | |||||
* Returns an {@link ImageDescriptor} stored in the file at the specified path. | |||||
* | |||||
* @param path the path to the image file. | |||||
* @return the {@link ImageDescriptor} stored in the file at the specified path. | |||||
*/ | |||||
public static ImageDescriptor getImageDescriptor(String path) { | |||||
try { | |||||
return ImageDescriptor.createFromURL(new File(path).toURI().toURL()); | |||||
} catch (MalformedURLException e) { | |||||
return null; | |||||
} | |||||
} | |||||
/** | |||||
* Returns an {@link Image} based on the specified {@link ImageDescriptor}. | |||||
* | |||||
* @param descriptor the {@link ImageDescriptor} for the {@link Image}. | |||||
* @return the {@link Image} based on the specified {@link ImageDescriptor}. | |||||
*/ | |||||
public static Image getImage(ImageDescriptor descriptor) { | |||||
if (descriptor == null) { | |||||
return null; | |||||
} | |||||
Image image = m_descriptorImageMap.get(descriptor); | |||||
if (image == null) { | |||||
image = descriptor.createImage(); | |||||
m_descriptorImageMap.put(descriptor, image); | |||||
} | |||||
return image; | |||||
} | |||||
/** | |||||
* Maps images to decorated images. | |||||
*/ | |||||
@SuppressWarnings("unchecked") | |||||
private static Map<Image, Map<Image, Image>>[] m_decoratedImageMap = new Map[LAST_CORNER_KEY]; | |||||
/** | |||||
* Returns an {@link Image} composed of a base image decorated by another image. | |||||
* | |||||
* @param baseImage the base {@link Image} that should be decorated. | |||||
* @param decorator the {@link Image} to decorate the base image. | |||||
* @return {@link Image} The resulting decorated image. | |||||
*/ | |||||
public static Image decorateImage(Image baseImage, Image decorator) { | |||||
return decorateImage(baseImage, decorator, BOTTOM_RIGHT); | |||||
} | |||||
/** | |||||
* Returns an {@link Image} composed of a base image decorated by another image. | |||||
* | |||||
* @param baseImage | |||||
* the base {@link Image} that should be decorated. | |||||
* @param decorator | |||||
* the {@link Image} to decorate the base image. | |||||
* @param corner | |||||
* the corner to place decorator image. | |||||
* @return the resulting decorated {@link Image}. | |||||
*/ | |||||
public static Image decorateImage(final Image baseImage, final Image decorator, final int corner) { | |||||
if (corner <= 0 || corner >= LAST_CORNER_KEY) { | |||||
throw new IllegalArgumentException("Wrong decorate corner"); | |||||
} | |||||
Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[corner]; | |||||
if (cornerDecoratedImageMap == null) { | |||||
cornerDecoratedImageMap = new HashMap<Image, Map<Image, Image>>(); | |||||
m_decoratedImageMap[corner] = cornerDecoratedImageMap; | |||||
} | |||||
Map<Image, Image> decoratedMap = cornerDecoratedImageMap.get(baseImage); | |||||
if (decoratedMap == null) { | |||||
decoratedMap = new HashMap<Image, Image>(); | |||||
cornerDecoratedImageMap.put(baseImage, decoratedMap); | |||||
} | |||||
// | |||||
Image result = decoratedMap.get(decorator); | |||||
if (result == null) { | |||||
final Rectangle bib = baseImage.getBounds(); | |||||
final Rectangle dib = decorator.getBounds(); | |||||
final Point baseImageSize = new Point(bib.width, bib.height); | |||||
CompositeImageDescriptor compositImageDesc = new CompositeImageDescriptor() { | |||||
@Override | |||||
protected void drawCompositeImage(int width, int height) { | |||||
drawImage(createCachedImageDataProvider(baseImage), 0, 0); | |||||
if (corner == TOP_LEFT) { | |||||
drawImage(getUnzoomedImageDataProvider(decorator.getImageData()) , 0, 0); | |||||
} else if (corner == TOP_RIGHT) { | |||||
drawImage(getUnzoomedImageDataProvider(decorator.getImageData()), bib.width - dib.width, 0); | |||||
} else if (corner == BOTTOM_LEFT) { | |||||
drawImage(getUnzoomedImageDataProvider(decorator.getImageData()), 0, bib.height - dib.height); | |||||
} else if (corner == BOTTOM_RIGHT) { | |||||
drawImage(getUnzoomedImageDataProvider(decorator.getImageData()), bib.width - dib.width, bib.height - dib.height); | |||||
} | |||||
} | |||||
@Override | |||||
protected Point getSize() { | |||||
return baseImageSize; | |||||
} | |||||
}; | |||||
// | |||||
result = compositImageDesc.createImage(); | |||||
decoratedMap.put(decorator, result); | |||||
} | |||||
return result; | |||||
} | |||||
private static ImageDataProvider getUnzoomedImageDataProvider(ImageData imageData) { | |||||
return zoom -> zoom == 100 ? imageData : null; | |||||
} | |||||
/** | |||||
* Dispose all of the cached images. | |||||
*/ | |||||
public static void disposeImages() { | |||||
SWTResourceManager.disposeImages(); | |||||
// dispose ImageDescriptor images | |||||
{ | |||||
for (Iterator<Image> I = m_descriptorImageMap.values().iterator(); I.hasNext();) { | |||||
I.next().dispose(); | |||||
} | |||||
m_descriptorImageMap.clear(); | |||||
} | |||||
// dispose decorated images | |||||
for (int i = 0; i < m_decoratedImageMap.length; i++) { | |||||
Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[i]; | |||||
if (cornerDecoratedImageMap != null) { | |||||
for (Map<Image, Image> decoratedMap : cornerDecoratedImageMap.values()) { | |||||
for (Image image : decoratedMap.values()) { | |||||
image.dispose(); | |||||
} | |||||
decoratedMap.clear(); | |||||
} | |||||
cornerDecoratedImageMap.clear(); | |||||
} | |||||
} | |||||
// dispose plugin images | |||||
{ | |||||
for (Iterator<Image> I = m_URLImageMap.values().iterator(); I.hasNext();) { | |||||
I.next().dispose(); | |||||
} | |||||
m_URLImageMap.clear(); | |||||
} | |||||
} | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
// | |||||
// Plugin images support | |||||
// | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
/** | |||||
* Maps URL to images. | |||||
*/ | |||||
private static Map<String, Image> m_URLImageMap = new HashMap<String, Image>(); | |||||
/** | |||||
* Provider for plugin resources, used by WindowBuilder at design time. | |||||
*/ | |||||
public interface PluginResourceProvider { | |||||
URL getEntry(String symbolicName, String path); | |||||
} | |||||
/** | |||||
* Instance of {@link PluginResourceProvider}, used by WindowBuilder at design | |||||
* time. | |||||
*/ | |||||
private static PluginResourceProvider m_designTimePluginResourceProvider = null; | |||||
/** | |||||
* Returns an {@link Image} based on a plugin and file path. | |||||
* | |||||
* @param plugin the plugin {@link Object} containing the image | |||||
* @param name the path to the image within the plugin | |||||
* @return the {@link Image} stored in the file at the specified path | |||||
* | |||||
* @deprecated Use {@link #getPluginImage(String, String)} instead. | |||||
*/ | |||||
@Deprecated | |||||
public static Image getPluginImage(Object plugin, String name) { | |||||
try { | |||||
URL url = getPluginImageURL(plugin, name); | |||||
if (url != null) { | |||||
return getPluginImageFromUrl(url); | |||||
} | |||||
} catch (Throwable e) { | |||||
// Ignore any exceptions | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Returns an {@link Image} based on a {@link Bundle} and resource entry path. | |||||
* | |||||
* @param symbolicName the symbolic name of the {@link Bundle}. | |||||
* @param path the path of the resource entry. | |||||
* @return the {@link Image} stored in the file at the specified path. | |||||
*/ | |||||
public static Image getPluginImage(String symbolicName, String path) { | |||||
try { | |||||
URL url = getPluginImageURL(symbolicName, path); | |||||
if (url != null) { | |||||
return getPluginImageFromUrl(url); | |||||
} | |||||
} catch (Throwable e) { | |||||
// Ignore any exceptions | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Returns an {@link Image} based on given {@link URL}. | |||||
*/ | |||||
private static Image getPluginImageFromUrl(URL url) { | |||||
try { | |||||
try { | |||||
String key = url.toExternalForm(); | |||||
Image image = m_URLImageMap.get(key); | |||||
if (image == null) { | |||||
InputStream stream = url.openStream(); | |||||
try { | |||||
image = getImage(stream); | |||||
m_URLImageMap.put(key, image); | |||||
} finally { | |||||
stream.close(); | |||||
} | |||||
} | |||||
return image; | |||||
} catch (Throwable e) { | |||||
// Ignore any exceptions | |||||
} | |||||
} catch (Throwable e) { | |||||
// Ignore any exceptions | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Returns an {@link ImageDescriptor} based on a plugin and file path. | |||||
* | |||||
* @param plugin the plugin {@link Object} containing the image. | |||||
* @param name the path to th eimage within the plugin. | |||||
* @return the {@link ImageDescriptor} stored in the file at the specified path. | |||||
* | |||||
* @deprecated Use {@link #getPluginImageDescriptor(String, String)} instead. | |||||
*/ | |||||
@Deprecated | |||||
public static ImageDescriptor getPluginImageDescriptor(Object plugin, String name) { | |||||
try { | |||||
try { | |||||
URL url = getPluginImageURL(plugin, name); | |||||
return ImageDescriptor.createFromURL(url); | |||||
} catch (Throwable e) { | |||||
// Ignore any exceptions | |||||
} | |||||
} catch (Throwable e) { | |||||
// Ignore any exceptions | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Returns an {@link ImageDescriptor} based on a {@link Bundle} and resource | |||||
* entry path. | |||||
* | |||||
* @param symbolicName the symbolic name of the {@link Bundle}. | |||||
* @param path the path of the resource entry. | |||||
* @return the {@link ImageDescriptor} based on a {@link Bundle} and resource | |||||
* entry path. | |||||
*/ | |||||
public static ImageDescriptor getPluginImageDescriptor(String symbolicName, String path) { | |||||
try { | |||||
URL url = getPluginImageURL(symbolicName, path); | |||||
if (url != null) { | |||||
return ImageDescriptor.createFromURL(url); | |||||
} | |||||
} catch (Throwable e) { | |||||
// Ignore any exceptions | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Returns an {@link URL} based on a {@link Bundle} and resource entry path. | |||||
*/ | |||||
private static URL getPluginImageURL(String symbolicName, String path) { | |||||
// try runtime plugins | |||||
{ | |||||
Bundle bundle = Platform.getBundle(symbolicName); | |||||
if (bundle != null) { | |||||
return bundle.getEntry(path); | |||||
} | |||||
} | |||||
// try design time provider | |||||
if (m_designTimePluginResourceProvider != null) { | |||||
return m_designTimePluginResourceProvider.getEntry(symbolicName, path); | |||||
} | |||||
// no such resource | |||||
return null; | |||||
} | |||||
/** | |||||
* Returns an {@link URL} based on a plugin and file path. | |||||
* | |||||
* @param plugin the plugin {@link Object} containing the file path. | |||||
* @param name the file path. | |||||
* @return the {@link URL} representing the file at the specified path. | |||||
* @throws Exception | |||||
*/ | |||||
private static URL getPluginImageURL(Object plugin, String name) throws Exception { | |||||
// try to work with 'plugin' as with OSGI BundleContext | |||||
try { | |||||
Class<?> BundleClass = Class.forName("org.osgi.framework.Bundle"); //$NON-NLS-1$ | |||||
Class<?> BundleContextClass = Class.forName("org.osgi.framework.BundleContext"); //$NON-NLS-1$ | |||||
if (BundleContextClass.isAssignableFrom(plugin.getClass())) { | |||||
Method getBundleMethod = BundleContextClass.getMethod("getBundle", new Class[0]); //$NON-NLS-1$ | |||||
Object bundle = getBundleMethod.invoke(plugin, new Object[0]); | |||||
// | |||||
Class<?> PathClass = Class.forName("org.eclipse.core.runtime.Path"); //$NON-NLS-1$ | |||||
Constructor<?> pathConstructor = PathClass.getConstructor(new Class[] { String.class }); | |||||
Object path = pathConstructor.newInstance(new Object[] { name }); | |||||
// | |||||
Class<?> IPathClass = Class.forName("org.eclipse.core.runtime.IPath"); //$NON-NLS-1$ | |||||
Class<?> PlatformClass = Class.forName("org.eclipse.core.runtime.Platform"); //$NON-NLS-1$ | |||||
Method findMethod = PlatformClass.getMethod("find", new Class[] { BundleClass, IPathClass }); //$NON-NLS-1$ | |||||
return (URL) findMethod.invoke(null, new Object[] { bundle, path }); | |||||
} | |||||
} catch (Throwable e) { | |||||
// Ignore any exceptions | |||||
} | |||||
// else work with 'plugin' as with usual Eclipse plugin | |||||
{ | |||||
Class<?> PluginClass = Class.forName("org.eclipse.core.runtime.Plugin"); //$NON-NLS-1$ | |||||
if (PluginClass.isAssignableFrom(plugin.getClass())) { | |||||
// | |||||
Class<?> PathClass = Class.forName("org.eclipse.core.runtime.Path"); //$NON-NLS-1$ | |||||
Constructor<?> pathConstructor = PathClass.getConstructor(new Class[] { String.class }); | |||||
Object path = pathConstructor.newInstance(new Object[] { name }); | |||||
// | |||||
Class<?> IPathClass = Class.forName("org.eclipse.core.runtime.IPath"); //$NON-NLS-1$ | |||||
Method findMethod = PluginClass.getMethod("find", new Class[] { IPathClass }); //$NON-NLS-1$ | |||||
return (URL) findMethod.invoke(plugin, new Object[] { path }); | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
// | |||||
// General | |||||
// | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
/** | |||||
* Dispose of cached objects and their underlying OS resources. This should only | |||||
* be called when the cached objects are no longer needed (e.g. on application | |||||
* shutdown). | |||||
*/ | |||||
public static void dispose() { | |||||
disposeColors(); | |||||
disposeFonts(); | |||||
disposeImages(); | |||||
} | |||||
} |
@@ -0,0 +1,447 @@ | |||||
/******************************************************************************* | |||||
* Copyright (c) 2011 Google, Inc. | |||||
* All rights reserved. This program and the accompanying materials | |||||
* are made available under the terms of the Eclipse Public License v1.0 | |||||
* which accompanies this distribution, and is available at | |||||
* http://www.eclipse.org/legal/epl-v10.html | |||||
* | |||||
* Contributors: | |||||
* Google, Inc. - initial API and implementation | |||||
*******************************************************************************/ | |||||
package org.eclipse.wb.swt; | |||||
import java.io.FileInputStream; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import org.eclipse.swt.SWT; | |||||
import org.eclipse.swt.graphics.Color; | |||||
import org.eclipse.swt.graphics.Cursor; | |||||
import org.eclipse.swt.graphics.Font; | |||||
import org.eclipse.swt.graphics.FontData; | |||||
import org.eclipse.swt.graphics.GC; | |||||
import org.eclipse.swt.graphics.Image; | |||||
import org.eclipse.swt.graphics.ImageData; | |||||
import org.eclipse.swt.graphics.RGB; | |||||
import org.eclipse.swt.graphics.Rectangle; | |||||
import org.eclipse.swt.widgets.Display; | |||||
/** | |||||
* Utility class for managing OS resources associated with SWT controls such as colors, fonts, images, etc. | |||||
* <p> | |||||
* !!! IMPORTANT !!! Application code must explicitly invoke the <code>dispose()</code> method to release the | |||||
* operating system resources managed by cached objects when those objects and OS resources are no longer | |||||
* needed (e.g. on application shutdown) | |||||
* <p> | |||||
* This class may be freely distributed as part of any application or plugin. | |||||
* <p> | |||||
* @author scheglov_ke | |||||
* @author Dan Rubel | |||||
*/ | |||||
public class SWTResourceManager { | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
// | |||||
// Color | |||||
// | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
private static Map<RGB, Color> m_colorMap = new HashMap<RGB, Color>(); | |||||
/** | |||||
* Returns the system {@link Color} matching the specific ID. | |||||
* | |||||
* @param systemColorID | |||||
* the ID value for the color | |||||
* @return the system {@link Color} matching the specific ID | |||||
*/ | |||||
public static Color getColor(int systemColorID) { | |||||
Display display = Display.getCurrent(); | |||||
return display.getSystemColor(systemColorID); | |||||
} | |||||
/** | |||||
* Returns a {@link Color} given its red, green and blue component values. | |||||
* | |||||
* @param r | |||||
* the red component of the color | |||||
* @param g | |||||
* the green component of the color | |||||
* @param b | |||||
* the blue component of the color | |||||
* @return the {@link Color} matching the given red, green and blue component values | |||||
*/ | |||||
public static Color getColor(int r, int g, int b) { | |||||
return getColor(new RGB(r, g, b)); | |||||
} | |||||
/** | |||||
* Returns a {@link Color} given its RGB value. | |||||
* | |||||
* @param rgb | |||||
* the {@link RGB} value of the color | |||||
* @return the {@link Color} matching the RGB value | |||||
*/ | |||||
public static Color getColor(RGB rgb) { | |||||
Color color = m_colorMap.get(rgb); | |||||
if (color == null) { | |||||
Display display = Display.getCurrent(); | |||||
color = new Color(display, rgb); | |||||
m_colorMap.put(rgb, color); | |||||
} | |||||
return color; | |||||
} | |||||
/** | |||||
* Dispose of all the cached {@link Color}'s. | |||||
*/ | |||||
public static void disposeColors() { | |||||
for (Color color : m_colorMap.values()) { | |||||
color.dispose(); | |||||
} | |||||
m_colorMap.clear(); | |||||
} | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
// | |||||
// Image | |||||
// | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
/** | |||||
* Maps image paths to images. | |||||
*/ | |||||
private static Map<String, Image> m_imageMap = new HashMap<String, Image>(); | |||||
/** | |||||
* Returns an {@link Image} encoded by the specified {@link InputStream}. | |||||
* | |||||
* @param stream | |||||
* the {@link InputStream} encoding the image data | |||||
* @return the {@link Image} encoded by the specified input stream | |||||
*/ | |||||
protected static Image getImage(InputStream stream) throws IOException { | |||||
try { | |||||
Display display = Display.getCurrent(); | |||||
ImageData data = new ImageData(stream); | |||||
if (data.transparentPixel > 0) { | |||||
return new Image(display, data, data.getTransparencyMask()); | |||||
} | |||||
return new Image(display, data); | |||||
} finally { | |||||
stream.close(); | |||||
} | |||||
} | |||||
/** | |||||
* Returns an {@link Image} stored in the file at the specified path. | |||||
* | |||||
* @param path | |||||
* the path to the image file | |||||
* @return the {@link Image} stored in the file at the specified path | |||||
*/ | |||||
public static Image getImage(String path) { | |||||
Image image = m_imageMap.get(path); | |||||
if (image == null) { | |||||
try { | |||||
image = getImage(new FileInputStream(path)); | |||||
m_imageMap.put(path, image); | |||||
} catch (Exception e) { | |||||
image = getMissingImage(); | |||||
m_imageMap.put(path, image); | |||||
} | |||||
} | |||||
return image; | |||||
} | |||||
/** | |||||
* Returns an {@link Image} stored in the file at the specified path relative to the specified class. | |||||
* | |||||
* @param clazz | |||||
* the {@link Class} relative to which to find the image | |||||
* @param path | |||||
* the path to the image file, if starts with <code>'/'</code> | |||||
* @return the {@link Image} stored in the file at the specified path | |||||
*/ | |||||
public static Image getImage(Class<?> clazz, String path) { | |||||
String key = clazz.getName() + '|' + path; | |||||
Image image = m_imageMap.get(key); | |||||
if (image == null) { | |||||
try { | |||||
image = getImage(clazz.getResourceAsStream(path)); | |||||
m_imageMap.put(key, image); | |||||
} catch (Exception e) { | |||||
image = getMissingImage(); | |||||
m_imageMap.put(key, image); | |||||
} | |||||
} | |||||
return image; | |||||
} | |||||
private static final int MISSING_IMAGE_SIZE = 10; | |||||
/** | |||||
* @return the small {@link Image} that can be used as placeholder for missing image. | |||||
*/ | |||||
private static Image getMissingImage() { | |||||
Image image = new Image(Display.getCurrent(), MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE); | |||||
// | |||||
GC gc = new GC(image); | |||||
gc.setBackground(getColor(SWT.COLOR_RED)); | |||||
gc.fillRectangle(0, 0, MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE); | |||||
gc.dispose(); | |||||
// | |||||
return image; | |||||
} | |||||
/** | |||||
* Style constant for placing decorator image in top left corner of base image. | |||||
*/ | |||||
public static final int TOP_LEFT = 1; | |||||
/** | |||||
* Style constant for placing decorator image in top right corner of base image. | |||||
*/ | |||||
public static final int TOP_RIGHT = 2; | |||||
/** | |||||
* Style constant for placing decorator image in bottom left corner of base image. | |||||
*/ | |||||
public static final int BOTTOM_LEFT = 3; | |||||
/** | |||||
* Style constant for placing decorator image in bottom right corner of base image. | |||||
*/ | |||||
public static final int BOTTOM_RIGHT = 4; | |||||
/** | |||||
* Internal value. | |||||
*/ | |||||
protected static final int LAST_CORNER_KEY = 5; | |||||
/** | |||||
* Maps images to decorated images. | |||||
*/ | |||||
@SuppressWarnings("unchecked") | |||||
private static Map<Image, Map<Image, Image>>[] m_decoratedImageMap = new Map[LAST_CORNER_KEY]; | |||||
/** | |||||
* Returns an {@link Image} composed of a base image decorated by another image. | |||||
* | |||||
* @param baseImage | |||||
* the base {@link Image} that should be decorated | |||||
* @param decorator | |||||
* the {@link Image} to decorate the base image | |||||
* @return {@link Image} The resulting decorated image | |||||
*/ | |||||
public static Image decorateImage(Image baseImage, Image decorator) { | |||||
return decorateImage(baseImage, decorator, BOTTOM_RIGHT); | |||||
} | |||||
/** | |||||
* Returns an {@link Image} composed of a base image decorated by another image. | |||||
* | |||||
* @param baseImage | |||||
* the base {@link Image} that should be decorated | |||||
* @param decorator | |||||
* the {@link Image} to decorate the base image | |||||
* @param corner | |||||
* the corner to place decorator image | |||||
* @return the resulting decorated {@link Image} | |||||
*/ | |||||
public static Image decorateImage(final Image baseImage, final Image decorator, final int corner) { | |||||
if (corner <= 0 || corner >= LAST_CORNER_KEY) { | |||||
throw new IllegalArgumentException("Wrong decorate corner"); | |||||
} | |||||
Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[corner]; | |||||
if (cornerDecoratedImageMap == null) { | |||||
cornerDecoratedImageMap = new HashMap<Image, Map<Image, Image>>(); | |||||
m_decoratedImageMap[corner] = cornerDecoratedImageMap; | |||||
} | |||||
Map<Image, Image> decoratedMap = cornerDecoratedImageMap.get(baseImage); | |||||
if (decoratedMap == null) { | |||||
decoratedMap = new HashMap<Image, Image>(); | |||||
cornerDecoratedImageMap.put(baseImage, decoratedMap); | |||||
} | |||||
// | |||||
Image result = decoratedMap.get(decorator); | |||||
if (result == null) { | |||||
Rectangle bib = baseImage.getBounds(); | |||||
Rectangle dib = decorator.getBounds(); | |||||
// | |||||
result = new Image(Display.getCurrent(), bib.width, bib.height); | |||||
// | |||||
GC gc = new GC(result); | |||||
gc.drawImage(baseImage, 0, 0); | |||||
if (corner == TOP_LEFT) { | |||||
gc.drawImage(decorator, 0, 0); | |||||
} else if (corner == TOP_RIGHT) { | |||||
gc.drawImage(decorator, bib.width - dib.width, 0); | |||||
} else if (corner == BOTTOM_LEFT) { | |||||
gc.drawImage(decorator, 0, bib.height - dib.height); | |||||
} else if (corner == BOTTOM_RIGHT) { | |||||
gc.drawImage(decorator, bib.width - dib.width, bib.height - dib.height); | |||||
} | |||||
gc.dispose(); | |||||
// | |||||
decoratedMap.put(decorator, result); | |||||
} | |||||
return result; | |||||
} | |||||
/** | |||||
* Dispose all of the cached {@link Image}'s. | |||||
*/ | |||||
public static void disposeImages() { | |||||
// dispose loaded images | |||||
{ | |||||
for (Image image : m_imageMap.values()) { | |||||
image.dispose(); | |||||
} | |||||
m_imageMap.clear(); | |||||
} | |||||
// dispose decorated images | |||||
for (int i = 0; i < m_decoratedImageMap.length; i++) { | |||||
Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[i]; | |||||
if (cornerDecoratedImageMap != null) { | |||||
for (Map<Image, Image> decoratedMap : cornerDecoratedImageMap.values()) { | |||||
for (Image image : decoratedMap.values()) { | |||||
image.dispose(); | |||||
} | |||||
decoratedMap.clear(); | |||||
} | |||||
cornerDecoratedImageMap.clear(); | |||||
} | |||||
} | |||||
} | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
// | |||||
// Font | |||||
// | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
/** | |||||
* Maps font names to fonts. | |||||
*/ | |||||
private static Map<String, Font> m_fontMap = new HashMap<String, Font>(); | |||||
/** | |||||
* Maps fonts to their bold versions. | |||||
*/ | |||||
private static Map<Font, Font> m_fontToBoldFontMap = new HashMap<Font, Font>(); | |||||
/** | |||||
* Returns a {@link Font} based on its name, height and style. | |||||
* | |||||
* @param name | |||||
* the name of the font | |||||
* @param height | |||||
* the height of the font | |||||
* @param style | |||||
* the style of the font | |||||
* @return {@link Font} The font matching the name, height and style | |||||
*/ | |||||
public static Font getFont(String name, int height, int style) { | |||||
return getFont(name, height, style, false, false); | |||||
} | |||||
/** | |||||
* Returns a {@link Font} based on its name, height and style. Windows-specific strikeout and underline | |||||
* flags are also supported. | |||||
* | |||||
* @param name | |||||
* the name of the font | |||||
* @param size | |||||
* the size of the font | |||||
* @param style | |||||
* the style of the font | |||||
* @param strikeout | |||||
* the strikeout flag (warning: Windows only) | |||||
* @param underline | |||||
* the underline flag (warning: Windows only) | |||||
* @return {@link Font} The font matching the name, height, style, strikeout and underline | |||||
*/ | |||||
public static Font getFont(String name, int size, int style, boolean strikeout, boolean underline) { | |||||
String fontName = name + '|' + size + '|' + style + '|' + strikeout + '|' + underline; | |||||
Font font = m_fontMap.get(fontName); | |||||
if (font == null) { | |||||
FontData fontData = new FontData(name, size, style); | |||||
if (strikeout || underline) { | |||||
try { | |||||
Class<?> logFontClass = Class.forName("org.eclipse.swt.internal.win32.LOGFONT"); //$NON-NLS-1$ | |||||
Object logFont = FontData.class.getField("data").get(fontData); //$NON-NLS-1$ | |||||
if (logFont != null && logFontClass != null) { | |||||
if (strikeout) { | |||||
logFontClass.getField("lfStrikeOut").set(logFont, Byte.valueOf((byte) 1)); //$NON-NLS-1$ | |||||
} | |||||
if (underline) { | |||||
logFontClass.getField("lfUnderline").set(logFont, Byte.valueOf((byte) 1)); //$NON-NLS-1$ | |||||
} | |||||
} | |||||
} catch (Throwable e) { | |||||
System.err.println("Unable to set underline or strikeout" + " (probably on a non-Windows platform). " + e); //$NON-NLS-1$ //$NON-NLS-2$ | |||||
} | |||||
} | |||||
font = new Font(Display.getCurrent(), fontData); | |||||
m_fontMap.put(fontName, font); | |||||
} | |||||
return font; | |||||
} | |||||
/** | |||||
* Returns a bold version of the given {@link Font}. | |||||
* | |||||
* @param baseFont | |||||
* the {@link Font} for which a bold version is desired | |||||
* @return the bold version of the given {@link Font} | |||||
*/ | |||||
public static Font getBoldFont(Font baseFont) { | |||||
Font font = m_fontToBoldFontMap.get(baseFont); | |||||
if (font == null) { | |||||
FontData fontDatas[] = baseFont.getFontData(); | |||||
FontData data = fontDatas[0]; | |||||
font = new Font(Display.getCurrent(), data.getName(), data.getHeight(), SWT.BOLD); | |||||
m_fontToBoldFontMap.put(baseFont, font); | |||||
} | |||||
return font; | |||||
} | |||||
/** | |||||
* Dispose all of the cached {@link Font}'s. | |||||
*/ | |||||
public static void disposeFonts() { | |||||
// clear fonts | |||||
for (Font font : m_fontMap.values()) { | |||||
font.dispose(); | |||||
} | |||||
m_fontMap.clear(); | |||||
// clear bold fonts | |||||
for (Font font : m_fontToBoldFontMap.values()) { | |||||
font.dispose(); | |||||
} | |||||
m_fontToBoldFontMap.clear(); | |||||
} | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
// | |||||
// Cursor | |||||
// | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
/** | |||||
* Maps IDs to cursors. | |||||
*/ | |||||
private static Map<Integer, Cursor> m_idToCursorMap = new HashMap<Integer, Cursor>(); | |||||
/** | |||||
* Returns the system cursor matching the specific ID. | |||||
* | |||||
* @param id | |||||
* int The ID value for the cursor | |||||
* @return Cursor The system cursor matching the specific ID | |||||
*/ | |||||
public static Cursor getCursor(int id) { | |||||
Integer key = Integer.valueOf(id); | |||||
Cursor cursor = m_idToCursorMap.get(key); | |||||
if (cursor == null) { | |||||
cursor = new Cursor(Display.getDefault(), id); | |||||
m_idToCursorMap.put(key, cursor); | |||||
} | |||||
return cursor; | |||||
} | |||||
/** | |||||
* Dispose all of the cached cursors. | |||||
*/ | |||||
public static void disposeCursors() { | |||||
for (Cursor cursor : m_idToCursorMap.values()) { | |||||
cursor.dispose(); | |||||
} | |||||
m_idToCursorMap.clear(); | |||||
} | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
// | |||||
// General | |||||
// | |||||
//////////////////////////////////////////////////////////////////////////// | |||||
/** | |||||
* Dispose of cached objects and their underlying OS resources. This should only be called when the cached | |||||
* objects are no longer needed (e.g. on application shutdown). | |||||
*/ | |||||
public static void dispose() { | |||||
disposeColors(); | |||||
disposeImages(); | |||||
disposeFonts(); | |||||
disposeCursors(); | |||||
} | |||||
} |
@@ -1,70 +1,93 @@ | |||||
package xyz.veronie.bgg.ui.dialogs; | package xyz.veronie.bgg.ui.dialogs; | ||||
import static org.eclipse.jface.widgets.WidgetFactory.text; | |||||
import org.eclipse.jface.dialogs.Dialog; | import org.eclipse.jface.dialogs.Dialog; | ||||
import org.eclipse.jface.dialogs.IDialogConstants; | |||||
import org.eclipse.swt.SWT; | import org.eclipse.swt.SWT; | ||||
import org.eclipse.swt.events.FocusEvent; | |||||
import org.eclipse.swt.events.FocusListener; | |||||
import org.eclipse.swt.events.ModifyEvent; | |||||
import org.eclipse.swt.events.ModifyListener; | |||||
import org.eclipse.swt.graphics.Point; | import org.eclipse.swt.graphics.Point; | ||||
import org.eclipse.swt.layout.GridData; | import org.eclipse.swt.layout.GridData; | ||||
import org.eclipse.swt.layout.GridLayout; | import org.eclipse.swt.layout.GridLayout; | ||||
import org.eclipse.swt.widgets.Composite; | import org.eclipse.swt.widgets.Composite; | ||||
import org.eclipse.swt.widgets.Control; | import org.eclipse.swt.widgets.Control; | ||||
import org.eclipse.swt.widgets.Label; | |||||
import org.eclipse.swt.widgets.Shell; | import org.eclipse.swt.widgets.Shell; | ||||
import org.eclipse.swt.widgets.Text; | import org.eclipse.swt.widgets.Text; | ||||
import org.eclipse.wb.swt.SWTResourceManager; | |||||
import xyz.veronie.bgg.ui.helpers.BatColors; | |||||
public class SaveGameListDialog extends Dialog { | public class SaveGameListDialog extends Dialog { | ||||
private Text textField; | |||||
private String entryString; | private String entryString; | ||||
/** | |||||
* Create the dialog. | |||||
* @param parentShell | |||||
*/ | |||||
public SaveGameListDialog(Shell parentShell) { | public SaveGameListDialog(Shell parentShell) { | ||||
super(parentShell); | |||||
} | |||||
@Override | |||||
protected Control createDialogArea(Composite parent) { | |||||
Composite container = (Composite) super.createDialogArea(parent); | |||||
GridLayout layout = new GridLayout(1, false); | |||||
layout.marginLeft = 16; | |||||
layout.marginTop = 16; | |||||
layout.marginRight = 16; | |||||
layout.marginBottom = 16; | |||||
container.setLayout(layout); | |||||
super(parentShell); | |||||
setShellStyle(SWT.APPLICATION_MODAL); | |||||
} | |||||
Text text = text(SWT.BORDER).message("Enter game list name") | |||||
.limitTo(255) | |||||
.layoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false)) | |||||
.create(container); | |||||
/** | |||||
* Create contents of the dialog. | |||||
* @param parent | |||||
*/ | |||||
@Override | |||||
protected Control createDialogArea(Composite parent) { | |||||
parent.setBackground(BatColors.getBackgroundColor()); | |||||
Composite container = (Composite) super.createDialogArea(parent); | |||||
container.setFont(SWTResourceManager.getFont("Segoe UI", 11, SWT.NORMAL)); | |||||
container.setBackground(BatColors.getBackgroundColor()); | |||||
GridLayout gl_container = new GridLayout(1, false); | |||||
gl_container.verticalSpacing = 24; | |||||
gl_container.marginWidth = 24; | |||||
gl_container.marginTop = 24; | |||||
gl_container.marginRight = 24; | |||||
gl_container.marginLeft = 24; | |||||
gl_container.marginHeight = 24; | |||||
gl_container.marginBottom = 24; | |||||
gl_container.horizontalSpacing = 24; | |||||
container.setLayout(gl_container); | |||||
Label lblEnterAName = new Label(container, SWT.NONE); | |||||
lblEnterAName.setFont(SWTResourceManager.getFont("Segoe UI", 11, SWT.NORMAL)); | |||||
lblEnterAName.setText("Enter a name for the game list:"); | |||||
textField = new Text(container, SWT.BORDER); | |||||
textField.addModifyListener(new ModifyListener() { | |||||
public void modifyText(ModifyEvent e) { | |||||
Text t = (Text) e.widget; | |||||
entryString = t.getText(); | |||||
} | |||||
}); | |||||
textField.setFont(SWTResourceManager.getFont("Segoe UI", 11, SWT.NORMAL)); | |||||
textField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); | |||||
return container; | |||||
} | |||||
FocusListener focusListener = new FocusListener() { | |||||
public void focusGained(FocusEvent e) { | |||||
} | |||||
/** | |||||
* Create contents of the button bar. | |||||
* @param parent | |||||
*/ | |||||
@Override | |||||
protected void createButtonsForButtonBar(Composite parent) { | |||||
parent.setBackground(BatColors.getBackgroundColor()); | |||||
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); | |||||
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); | |||||
} | |||||
public void focusLost(FocusEvent e) { | |||||
Text t = (Text) e.widget; | |||||
entryString = t.getText(); | |||||
} | |||||
}; | |||||
text.addFocusListener(focusListener); | |||||
return container; | |||||
} | |||||
// overriding this methods allows you to set the | |||||
// title of the custom dialog | |||||
@Override | |||||
protected void configureShell(Shell newShell) { | |||||
super.configureShell(newShell); | |||||
newShell.setText("Enter game list name"); | |||||
} | |||||
/** | |||||
* Return the initial size of the dialog. | |||||
*/ | |||||
@Override | |||||
protected Point getInitialSize() { | |||||
return new Point(450, 300); | |||||
} | |||||
@Override | |||||
protected Point getInitialSize() { | |||||
return new Point(450, 300); | |||||
} | |||||
public String getEntryText() { | public String getEntryText() { | ||||
return entryString; | return entryString; | ||||
@@ -1,8 +1,6 @@ | |||||
package xyz.veronie.bgg.ui.handlers; | 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.CanExecute; | ||||
import org.eclipse.e4.core.di.annotations.Execute; | import org.eclipse.e4.core.di.annotations.Execute; | ||||
import org.eclipse.jface.dialogs.Dialog; | import org.eclipse.jface.dialogs.Dialog; | ||||
@@ -15,9 +13,14 @@ import xyz.veronie.bgg.ui.dialogs.SaveGameListDialog; | |||||
public class HandleSaveGamelist { | public class HandleSaveGamelist { | ||||
@Inject | |||||
// @Inject | |||||
ThingProvider thingProvider; | ThingProvider thingProvider; | ||||
public HandleSaveGamelist(ThingProvider thingProvider) { | |||||
this.thingProvider = thingProvider; | |||||
} | |||||
@Execute | @Execute | ||||
public void execute(Shell shell) { | public void execute(Shell shell) { | ||||
@@ -0,0 +1,16 @@ | |||||
package xyz.veronie.bgg.ui.helpers; | |||||
import org.eclipse.swt.graphics.Color; | |||||
import org.eclipse.wb.swt.SWTResourceManager; | |||||
public class BatColors { | |||||
public static Color getBackgroundColor() { | |||||
return SWTResourceManager.getColor(155,142,237); | |||||
} | |||||
public static Color getButtonBgColor() { | |||||
return SWTResourceManager.getColor(255,81,0); | |||||
} | |||||
} |
@@ -0,0 +1,18 @@ | |||||
package xyz.veronie.bgg.ui.helpers; | |||||
import org.eclipse.swt.layout.GridLayout; | |||||
public class BatLayouts { | |||||
public static void applyStandardSpacing(GridLayout gl) { | |||||
gl.horizontalSpacing = 8; | |||||
gl.verticalSpacing = 24; | |||||
gl.marginWidth = 8; | |||||
gl.marginTop = 8; | |||||
gl.marginRight = 8; | |||||
gl.marginLeft = 8; | |||||
gl.marginHeight = 8; | |||||
gl.marginBottom = 8; | |||||
} | |||||
} |
@@ -0,0 +1,274 @@ | |||||
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.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.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.SelectionChangedEvent; | |||||
import org.eclipse.jface.viewers.TableViewer; | |||||
import org.eclipse.jface.viewers.TableViewerColumn; | |||||
import org.eclipse.swt.SWT; | |||||
import org.eclipse.swt.events.MouseAdapter; | |||||
import org.eclipse.swt.events.MouseEvent; | |||||
import org.eclipse.swt.graphics.Color; | |||||
import org.eclipse.swt.graphics.Image; | |||||
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.Label; | |||||
import org.eclipse.swt.widgets.Table; | |||||
import org.eclipse.swt.widgets.TableColumn; | |||||
import org.eclipse.wb.swt.ResourceManager; | |||||
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; | |||||
public class BatMain { | |||||
private Table tableGameList; | |||||
private TableViewer tableViewer; | |||||
@Inject | |||||
private ThingProvider thingProvider; | |||||
@Inject | |||||
private IEventBroker eventBroker; | |||||
@Inject | |||||
public BatMain() { | |||||
} | |||||
@PostConstruct | |||||
public void postConstruct(Composite parent, MApplication application, EPartService partService, EModelService modelService) { | |||||
Color bgColor = BatColors.getBackgroundColor(); | |||||
parent.setBackground(bgColor); | |||||
GridLayout gl_parent = new GridLayout(1, false); | |||||
gl_parent.horizontalSpacing = 0; | |||||
gl_parent.verticalSpacing = 0; | |||||
gl_parent.marginWidth = 0; | |||||
gl_parent.marginHeight = 0; | |||||
parent.setLayout(gl_parent); | |||||
Composite main = new Composite(parent, SWT.NONE); | |||||
GridData gd_main = new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1); | |||||
gd_main.minimumHeight = 192; | |||||
gd_main.minimumWidth = 348; | |||||
main.setLayoutData(gd_main); | |||||
main.setBackground(bgColor); | |||||
GridLayout gl_main = new GridLayout(1, false); | |||||
gl_main.verticalSpacing = 24; | |||||
BatLayouts.applyStandardSpacing(gl_main); | |||||
main.setLayout(gl_main); | |||||
Composite buttonRow = new Composite(main, SWT.NONE); | |||||
buttonRow.setBackground(bgColor); | |||||
GridLayout gl_buttonRow = new GridLayout(5, false); | |||||
gl_buttonRow.verticalSpacing = 8; | |||||
gl_buttonRow.marginWidth = 0; | |||||
gl_buttonRow.marginHeight = 8; | |||||
gl_buttonRow.horizontalSpacing = 8; | |||||
BatLayouts.applyStandardSpacing(gl_buttonRow); | |||||
buttonRow.setLayout(gl_buttonRow); | |||||
buttonRow.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false, 1, 1)); | |||||
Button btnFetch = new Button(buttonRow, SWT.NONE); | |||||
btnFetch.addMouseListener(new MouseAdapter() { | |||||
@Override | |||||
public void mouseUp(MouseEvent e) { | |||||
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.ACTIVATE); | |||||
} | |||||
} | |||||
}); | |||||
btnFetch.setToolTipText("Fetch games from BGG"); | |||||
btnFetch.setForeground(SWTResourceManager.getColor(SWT.COLOR_TRANSPARENT)); | |||||
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.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()); | |||||
} | |||||
} | |||||
}); | |||||
btnSave.setToolTipText("Save list of games"); | |||||
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")); | |||||
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.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)); | |||||
Button 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"); | |||||
tableViewer = new TableViewer(main, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI); | |||||
tableGameList = tableViewer.getTable(); | |||||
tableGameList.setLinesVisible(true); | |||||
tableGameList.setHeaderVisible(true); | |||||
GridData gd_tableGameList = new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1); | |||||
gd_tableGameList.heightHint = 466; | |||||
tableGameList.setLayoutData(gd_tableGameList); | |||||
createColumns(tableViewer); | |||||
tableViewer.setContentProvider(new ArrayContentProvider()); | |||||
// Get the content for the viewer, setInput will call getElements in the | |||||
// contentProvider | |||||
tableViewer.setInput(thingProvider.getThings()); | |||||
// make the selection available to other views | |||||
// TODO: getSite().setSelectionProvider(viewer); | |||||
// Set the sorter for the table | |||||
tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { | |||||
@Override | |||||
public void selectionChanged(SelectionChangedEvent event) { | |||||
IStructuredSelection selection = tableViewer.getStructuredSelection(); | |||||
Thing thing = (Thing)selection.getFirstElement(); | |||||
eventBroker.send(EventConstants.TOPIC_THING_SELECTION, thing); | |||||
} | |||||
}); | |||||
Composite statusRow = new Composite(main, SWT.NONE); | |||||
statusRow.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false, 1, 1)); | |||||
GridLayout gl_statusRow = new GridLayout(1, false); | |||||
gl_statusRow.verticalSpacing = 8; | |||||
gl_statusRow.marginWidth = 8; | |||||
gl_statusRow.marginHeight = 8; | |||||
gl_statusRow.horizontalSpacing = 8; | |||||
BatLayouts.applyStandardSpacing(gl_statusRow); | |||||
statusRow.setLayout(gl_statusRow); | |||||
Label lblResultStatus = new Label(statusRow, SWT.NONE); | |||||
lblResultStatus.setText("0 items"); | |||||
} | |||||
public TableViewer getViewer() { | |||||
return tableViewer; | |||||
} | |||||
// 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() { | |||||
@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(tableViewer, | |||||
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() { | |||||
tableViewer.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(); | |||||
tableViewer.setInput(things); | |||||
tableViewer.refresh(true); | |||||
// if(things != null) { | |||||
// statsLabel.setText(Integer.toString(things.size()) + " items"); | |||||
// statsLabel.redraw(); | |||||
// } | |||||
} | |||||
} |
@@ -33,33 +33,6 @@ import xyz.veronie.bgg.result.Thing; | |||||
import xyz.veronie.bgg.result.ThingProvider; | import xyz.veronie.bgg.result.ThingProvider; | ||||
import xyz.veronie.bgg.types.EventConstants; | import xyz.veronie.bgg.types.EventConstants; | ||||
abstract class CenterImageLabelProvider extends OwnerDrawLabelProvider { | |||||
protected void measure(Event event, Object element) { | |||||
} | |||||
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); | |||||
} | |||||
} | |||||
protected abstract Image getImage(Object element); | |||||
}; | |||||
public class BggResultPart { | public class BggResultPart { | ||||
private TableViewer viewer; | private TableViewer viewer; | ||||
@@ -72,7 +45,7 @@ public class BggResultPart { | |||||
private IEventBroker eventBroker; | private IEventBroker eventBroker; | ||||
@PostConstruct | @PostConstruct | ||||
public void createControls(Composite parent) { | |||||
public void createContents(Composite parent) { | |||||
Composite main = new Composite(parent, SWT.FILL); | Composite main = new Composite(parent, SWT.FILL); | ||||
main.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); | main.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); | ||||
@@ -0,0 +1,298 @@ | |||||
package xyz.veronie.bgg.ui.parts; | |||||
import java.util.ArrayList; | |||||
import javax.annotation.PostConstruct; | |||||
import javax.inject.Inject; | |||||
import org.eclipse.e4.core.services.events.IEventBroker; | |||||
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; | |||||
import org.eclipse.swt.widgets.Composite; | |||||
import org.eclipse.swt.widgets.Control; | |||||
import org.eclipse.swt.widgets.Group; | |||||
import org.eclipse.wb.swt.ResourceManager; | |||||
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.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 { | |||||
@Inject | |||||
private ResultConfigManager configManager; | |||||
// inject all source filter composites | |||||
@Inject private BggUserSourceFilter bggUserSourceFilter; | |||||
@Inject private GeeklistSourceFilter geeklistSourceFilter; | |||||
@Inject private FamilySourceFilter familySourceFilter; | |||||
@Inject | |||||
private IEventBroker eventBroker; | |||||
@Inject | |||||
private ThingProvider thingProvider; | |||||
@Inject | |||||
private BggApi bggApi; | |||||
private Button btnBggUser; | |||||
private Button btnFamily; | |||||
private Button btnGeeklist; | |||||
private SourceFilter source; | |||||
private Composite main; | |||||
private Group filterGroup; | |||||
@Inject | |||||
public FetchPart() { | |||||
} | |||||
@PostConstruct | |||||
public void postConstruct(Composite parent) { | |||||
parent.setBackground(BatColors.getBackgroundColor()); | |||||
parent.setLayout(new GridLayout(1, false)); | |||||
main = new Composite(parent, SWT.NONE); | |||||
GridLayout gl_main = new GridLayout(1, false); | |||||
BatLayouts.applyStandardSpacing(gl_main); | |||||
main.setLayout(gl_main); | |||||
main.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1)); | |||||
Composite buttonRow = new Composite(main, SWT.NONE); | |||||
buttonRow.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); | |||||
GridLayout gl_buttonRow = new GridLayout(3, false); | |||||
BatLayouts.applyStandardSpacing(gl_main); | |||||
buttonRow.setLayout(gl_buttonRow); | |||||
btnBggUser = new Button(buttonRow, SWT.NONE); | |||||
btnBggUser.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_Meeple_60x60.png")); | |||||
btnFamily = new Button(buttonRow, SWT.NONE); | |||||
btnFamily.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_Family_60x60.png")); | |||||
btnGeeklist = new Button(buttonRow, SWT.NONE); | |||||
btnGeeklist.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_List_60x60.png")); | |||||
btnBggUser.addMouseListener(new MouseAdapter() { | |||||
@Override | |||||
public void mouseUp(MouseEvent e) { | |||||
selectFilter(SourceFilter.BGG_USER); | |||||
} | |||||
}); | |||||
btnFamily.addMouseListener(new MouseAdapter() { | |||||
@Override | |||||
public void mouseUp(MouseEvent e) { | |||||
selectFilter(SourceFilter.FAMILY); | |||||
} | |||||
}); | |||||
btnGeeklist.addMouseListener(new MouseAdapter() { | |||||
@Override | |||||
public void mouseUp(MouseEvent e) { | |||||
selectFilter(SourceFilter.GEEKLIST); | |||||
} | |||||
}); | |||||
Composite centerComposite = new Composite(main, SWT.NONE); | |||||
centerComposite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1)); | |||||
GridLayout gl_centerComposite = new GridLayout(1, false); | |||||
BatLayouts.applyStandardSpacing(gl_centerComposite); | |||||
centerComposite.setLayout(gl_centerComposite); | |||||
filterGroup = new Group(centerComposite, SWT.NONE); | |||||
filterGroup.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true, 1, 1)); | |||||
filterGroup.setLayout(new GridLayout(1, false)); | |||||
Composite applyComposite = new Composite(main, SWT.NONE); | |||||
applyComposite.setLayout(new GridLayout(5, false)); | |||||
applyComposite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false, 1, 1)); | |||||
Button btnOnlyNew = new Button(applyComposite, SWT.NONE); | |||||
btnOnlyNew.addMouseListener(new MouseAdapter() { | |||||
@Override | |||||
public void mouseUp(MouseEvent e) { | |||||
} | |||||
}); | |||||
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"); | |||||
Button btnAdd = new Button(applyComposite, SWT.NONE); | |||||
btnAdd.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_add_60x60.png")); | |||||
btnAdd.setToolTipText("Add"); | |||||
Button btnSubtract = new Button(applyComposite, SWT.NONE); | |||||
btnSubtract.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_subtract_60x60.png")); | |||||
btnSubtract.setToolTipText("Subtract"); | |||||
Button btnIntersect = new Button(applyComposite, SWT.NONE); | |||||
btnIntersect.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_intersect_60x60.png")); | |||||
btnIntersect.setToolTipText("Intersect"); | |||||
// init filter using config manager | |||||
source = configManager.getResultConfig().source; | |||||
selectFilter(source); | |||||
showFilter(filterGroup, source); | |||||
} | |||||
private void selectFilter(SourceFilter source) { | |||||
switch(source) { | |||||
default: | |||||
case BGG_USER: | |||||
btnBggUser.setFocus(); | |||||
btnBggUser.setBackground(BatColors.getButtonBgColor()); | |||||
btnFamily.setBackground(null); | |||||
btnGeeklist.setBackground(null); | |||||
break; | |||||
case FAMILY: | |||||
btnBggUser.setFocus(); | |||||
btnBggUser.setBackground(null); | |||||
btnFamily.setBackground(BatColors.getButtonBgColor()); | |||||
btnGeeklist.setBackground(null); | |||||
break; | |||||
case GEEKLIST: | |||||
btnGeeklist.setFocus(); | |||||
btnBggUser.setBackground(null); | |||||
btnFamily.setBackground(null); | |||||
btnGeeklist.setBackground(BatColors.getButtonBgColor()); | |||||
break; | |||||
} | |||||
showFilter(filterGroup, source); | |||||
eventBroker.send(EventConstants.TOPIC_ACTION_CHANGED, source); | |||||
} | |||||
/// show different filter controls depending on selection in cbSource ComboViewer | |||||
private void showFilter(Composite parent, SourceFilter source) { | |||||
// clean up | |||||
for(Control child : parent.getChildren()) { | |||||
child.dispose(); | |||||
} | |||||
// create a new filter area based on selection: | |||||
switch(source) { | |||||
default: | |||||
case BGG_USER: | |||||
System.out.println("construct " + source); | |||||
bggUserSourceFilter.create(parent, SWT.FILL); | |||||
break; | |||||
case GEEKLIST: | |||||
System.out.println("construct " + source); | |||||
geeklistSourceFilter.create(parent, SWT.FILL); | |||||
break; | |||||
case FAMILY: | |||||
System.out.println("construct " + source); | |||||
familySourceFilter.create(parent, SWT.FILL); | |||||
break; | |||||
} | |||||
main.layout(true, true); | |||||
} | |||||
private void checkEntry() { | |||||
ResultConfig resultConfig = configManager.getResultConfig(); | |||||
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()); | |||||
} | |||||
} | |||||
} 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()); | |||||
} | |||||
} | |||||
} 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()); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
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."); | |||||
} | |||||
} |
@@ -0,0 +1,35 @@ | |||||
package xyz.veronie.bgg.ui.parts.internal; | |||||
import org.eclipse.jface.viewers.OwnerDrawLabelProvider; | |||||
import org.eclipse.swt.graphics.Image; | |||||
import org.eclipse.swt.graphics.Rectangle; | |||||
import org.eclipse.swt.widgets.Event; | |||||
import org.eclipse.swt.widgets.TableItem; | |||||
public abstract class CenterImageLabelProvider extends OwnerDrawLabelProvider { | |||||
protected void measure(Event event, Object element) { | |||||
} | |||||
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); | |||||
} | |||||
} | |||||
protected abstract Image getImage(Object element); | |||||
}; |