I'm using a MenuContribution to feed a menu entry, implementing a feature like the "switch workspace" in E3.
In a dynamic menu contribution, i'm building a 3 item list of most recent opened projects followed by the "Other.." entry.
graphically, i'm done, the 3 list, separator and "other.." menu elements are showing up.
But in the case of most recent project, i have to dynamically pass the project name/Path to the handler which consume the selection event.
below is a code similar to what i have in the menu contribution that creates one of the 3 recent project item :
#AboutToShow
public void aboutToShow(List<MMenuElement> items, MApplication application) {
MHandledMenuItem dynamicItem = modelService.createModelElement(MHandledMenuItem.class);
dynamicItem.setLabel(projectName);
dynamicItem.setContributorURI("platform:/plugin/com.acme");
MCommand command = modelService.createModelElement(MCommand.class);
command.setElementId(LOAD_PROJECT_COMMAND_ID);
MCommandParameter commandParam = modelService.createModelElement(MCommandParameter.class);
commandParam.setElementId(PROJECT_NAME_PARAMETER_ID);
commandParam.setName(PROJECT_NAME_PARAMETER_ID);
command.getParameters().add(commandParam);
// one of the 3 last used projects
String projectName = "foo";
dynamicItem.setCommand(command);
items.add(dynamicItem);
}
where LOAD_PROJECT_COMMAND_ID and PROJECT_NAME_PARAMETER_ID are e4xmi command and command parameter id.
I wonder how i can put projectName in the command to be able to get it back in the associated handler, which contains something like :
#Execute
public void execute(ParameterizedCommand command) {
[...]
}
Note : I read Lars tutorial about menus but did not found solution in there
--- EDIT : full contribution code ---
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.eclipse.e4.core.commands.ECommandService;
import org.eclipse.e4.ui.di.AboutToShow;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.commands.MCommand;
import org.eclipse.e4.ui.model.application.commands.MParameter;
import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import com.acme.model.platypus.extractionresult.CampaignResultProvider;
#SuppressWarnings("restriction")
public class SwitchProjectMenuContribution {
private static final String NEW_PROJECT = "Other...";
private static final String LOAD_PROJECT_COMMAND_ID = "gui.rcp4.command.loadProjectCommand";
private static final String PROJECT_NAME_PARAMETER_ID = "gui.rcp4.command.loadProjectCommand.projectName";
#Inject
CampaignResultProvider campaignResultProvider;
#Inject
private EModelService modelService;
#Inject
ECommandService commandService;
private MDirectMenuItem otherProjectItem;
private MMenuSeparator separatorItem;
private MCommand loadProjectCommand;
#SuppressWarnings("unchecked")
#PostConstruct
public void initialize(MApplication application) {
loadProjectCommand = (MCommand) modelService
.findElements(application, LOAD_PROJECT_COMMAND_ID, MCommand.class, Collections.EMPTY_LIST).get(0);
otherProjectItem = modelService.createModelElement(MDirectMenuItem.class);
otherProjectItem.setLabel(NEW_PROJECT);
otherProjectItem.setContributorURI("platform:/plugin/com.acme.gui.rcp4");
otherProjectItem.setContributionURI(
"bundleclass://com.acme.gui.rcp4/com.acme.gui.rcp4.handlers.OtherProjecthandler");
separatorItem = modelService.createModelElement(MMenuSeparator.class);
}
#AboutToShow
public void aboutToShow(List<MMenuElement> items, MApplication application) {
String[] lastProject = campaignResultProvider.getLastUsed();
MMenuElement newEntry;
for (String projectName : lastProject) {
newEntry = createExistingProjectEntry(projectName);
items.add(newEntry);
}
if (lastProject.length > 0) {
items.add(separatorItem);
}
items.add(otherProjectItem);
}
private MHandledMenuItem createExistingProjectEntry(String projectPath) {
MHandledMenuItem dynamicItem = modelService.createModelElement(MHandledMenuItem.class);
dynamicItem.setLabel(projectPath);
dynamicItem.setContributorURI("platform:/plugin/com.acme.gui.rcp4");
MParameter commandParam = modelService.createModelElement(MParameter.class);
commandParam.setName("projectName");
commandParam.setElementId(PROJECT_NAME_PARAMETER_ID);
commandParam.setValue(projectPath);
dynamicItem.getParameters().add(commandParam);
dynamicItem.setCommand(loadProjectCommand);
return dynamicItem;
}
}
You add the parameter value to the MHandledMenuItem not the command.
Use a MParameter and call the setName and setValue methods to set the name (must match the parameter name in the command) and value (the project name in your case).
Add the MParameter to the MHandledMenuItem.getParameters() list.
Note: You should only define the command and command parameter once, not every time aboutToShow is called (so that should probably be in the e4xmi file).
Related
I issue I am trying to get rid off is the following:
I intend to setup a costum event handling chain as a workaround for JavaFX's lack of actioncommands.
The issue in particular is, that a menuitem upon clicking it, still fires an ActionEvent instead of the self-written MilvaLabActionEvent.
The code:
Event class
package jpt.gui.items;
import javafx.event.ActionEvent;
public class MilvaLabActionEvent extends ActionEvent {
private static final long serialVersionUID = 6757067652205246280L;
private String actionCommand ="";
public MilvaLabActionEvent(String actionCommand2) {
setActionCommand(actionCommand2);
}
public MilvaLabActionEvent() {}
public String getActionCommand() {
return actionCommand;
}
public void setActionCommand(String actioncommand) {
this.actionCommand = actioncommand;
}
}
My EventHandler:
package jpt.gui.items;
import javafx.event.EventHandler;
import jpt.MilvaLabGlobal;
import jpt.MilvaLabKonst;
import jpt.handle.MilvaLabDateiHandle;
import jpt.handle.MilvaLabEinHandle;
import jpt.handle.MilvaLabHilfeHandle;
import jpt.handle.MilvaLabMilvaHandle;
import jpt.handle.MilvaLabRvAnwendungHandle;
import jpt.handle.MilvaLabrvTextHandle;
import jpt.log4j.MilvaLabLogger;
public class MilvaLabEventHandler implements EventHandler<MilvaLabActionEvent>{
#Override
public void handle(MilvaLabActionEvent event) {
// the command string of the menu item
final String sCmd = event.getActionCommand();
if (sCmd.charAt(0) == 'M')
{//doing something here
}
}
The costum MenuItem-Class I figured out I gotta write.
package jpt.gui.items;
import javafx.event.Event;
import javafx.scene.control.MenuItem;
public class MilvaLabMenuItem extends MenuItem {
private String actionCommand;
public MilvaLabMenuItem(String sText) {
this.setText(sText);
}
#Override
public void fire() {
Event.fireEvent(this, new MilvaLabActionEvent(getActionCommand()));
}
public String getActionCommand() {
return actionCommand;
}
public void setActionCommand(String actionCommand) {
this.actionCommand = actionCommand;
}
}
And the initialization of the costum MenuItem:
final MilvaLabMenuItem jmi = new MilvaLabMenuItem("I am a menuItem");
jmi.addEventHandler(evtype, new MilvaLabEventHandler());
jmi.setOnAction((event) -> {
System.out.print("I have fired an ActionEvent!");
});
Well, as of now, I got "I have fired an ActionEvent" when I click on the MilvaLabMenuItem, nothing else happens. (Looked into that thing already using the debugger).
What I want to happen is that, obviously, the MilvaLabEventHandler is called.
I figured it out again.
I declared two EventTypes, though, only one was necessary.
This helped me finding the solution, though, they use Nodes instead of MenuItems.
How to emit and handle custom events?
I want to have some helper functions for manipulating UI.
I don't want to pass to them any parameters except what is necessary by my domain model (i don't want to pass EModelService, EPartService etc.)
Question: The problem is i am getting exception application does not have active window.
I found where the problem is.
It happend because i am manipulating parts via EPartService accessed from the application context IWorkbench.getApplication().getContext().get(EPartService.class).
THIS IS IMPORTANT: Currently i am getting that exception when i am trying to modify my UI AFTER i read inputs from dialog. Pleas note that the error does not happened when i am trying to modify the UI just BEFORE i
opened the dialog. Look at the code, i added some comments.
NewFromDirectoryDialog.java
package cz.vutbr.fit.xhriba01.bc.handlers;
import javax.inject.Named;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;
import cz.vutbr.fit.xhriba01.bc.BcModel;
import cz.vutbr.fit.xhriba01.bc.resolvers.filesystem.FileSystemResolver;
import cz.vutbr.fit.xhriba01.bc.ui.dialogs.NewFromDirectoryDialog;
import cz.vutbr.fit.xhriba01.bc.ui.UI;
public class NewFromDirectoryHandler {
#Execute
public void execute(MApplication application, EPartService partService, #Named(IServiceConstants.ACTIVE_SHELL) Shell shell) {
FileSystemResolver fsr = new FileSystemResolver("/home/jara/git/cz.vutbr.fit.xhriba01.bc/bc/src",
"/home/jara/git/cz.vutbr.fit.xhriba01.bc/bc/bin");
BcModel.setResolver(fsr);
// THIS CALL IS OK AND EVERYTHING WORKS
UI.changeExplorerView("bc.partdescriptor.filesystemview", fsr);
NewFromDirectoryDialog dialog = new NewFromDirectoryDialog(shell);
dialog.create();
if (dialog.open() == Window.OK) {
String sourceDir = dialog.getSourceDir();
String classDir = dialog.getClassDir();
FileSystemResolver fsr = new FileSystemResolver(classDir, sourceDir);
//THIS CALL LEADS TO EXCEPTION: application does not have active window
UI.changeExplorerView("bc.partdescriptor.filesystemview", fsr);
}
}
}
That EPartService from application context is based on org.eclipse.e4.ui.internal.workbench.ApplicationPartServiceImpl
and not on org.eclipse.e4.ui.internal.workbench.PartServiceImpl
as EPartService instance you get when injected to #PostConstruct annotated method on Part's view.
org.eclipse.e4.ui.internal.workbench.ApplicationPartServiceImpl (not entire source code)
You can see that the error probably happened because at the time ApplicationPartServiceImpl.createPart is called in my UI.changeExplorerView, the Eclipse runtime does not know what window
is currently active.
package org.eclipse.e4.ui.internal.workbench;
import java.util.Collection;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MInputPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.IPartListener;
public class ApplicationPartServiceImpl implements EPartService {
private MApplication application;
#Inject
ApplicationPartServiceImpl(MApplication application) {
this.application = application;
}
private EPartService getActiveWindowService() {
IEclipseContext activeWindowContext = application.getContext().getActiveChild();
if (activeWindowContext == null) {
throw new IllegalStateException("Application does not have an active window"); //$NON-NLS-1$
}
EPartService activeWindowPartService = activeWindowContext.get(EPartService.class);
if (activeWindowPartService == null) {
throw new IllegalStateException("Active window context is invalid"); //$NON-NLS-1$
}
if (activeWindowPartService == this) {
throw new IllegalStateException("Application does not have an active window"); //$NON-NLS-1$
}
return activeWindowPartService;
}
#Override
public MPart createPart(String id) {
return getActiveWindowService().createPart(id);
}
}
LifeCycleManager.java (how i initialize the UI helper class)
You can see i am injecting IWorkbench to my UI class.
IWorkbench allows me to access MApplication, so that is all i should
need to modify app UI.
package cz.vutbr.fit.xhriba01.bc;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.di.UIEventTopic;
import org.eclipse.e4.ui.workbench.IWorkbench;
import org.eclipse.e4.ui.workbench.UIEvents;
import cz.vutbr.fit.xhriba01.bc.ui.UI;
public class LifeCycleManager {
#Inject
#Optional
private void appCompleted(#UIEventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) Object event, IWorkbench workbench) {
ContextInjectionFactory.inject(UI.getDefault(), workbench.getApplication().getContext());
}
}
UI.java
package cz.vutbr.fit.xhriba01.bc.ui;
import javax.inject.Inject;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.workbench.IWorkbench;
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.text.IDocument;
import cz.vutbr.fit.xhriba01.bc.BcModel;
import cz.vutbr.fit.xhriba01.bc.resolvers.ISourceAndClassResolver;
public class UI {
public static final String PART_EXPLORER_ID = "bc.part.inspector";
public static final String PART_EXPLORER_CONTAINER_ID = "bc.partstack.explorer_stack";
public static final String PART_JAVA_SOURCE_VIEWER_ID = "bc.part.javasourceview";
private static UI fInstance = new UI();
#Inject
private IWorkbench fWorkbench;
private UI() {
}
public static void changeExplorerView(String partDescriptorId, ISourceAndClassResolver resolver) {
EModelService modelService = fInstance.fWorkbench.getApplication().getContext().get(EModelService.class);
EPartService partService = fInstance.fWorkbench.getApplication().getContext().get(EPartService.class);
MApplication application = fInstance.fWorkbench.getApplication();
MPart part = partService.createPart(partDescriptorId);
MPart oldPart = partService.findPart(UI.PART_EXPLORER_ID);
MPartStack partStack = (MPartStack) modelService.find(UI.PART_EXPLORER_CONTAINER_ID, application);
partStack.setVisible(true);
if (oldPart != null) {
partService.hidePart(oldPart);
}
part.setElementId(UI.PART_EXPLORER_ID);
partStack.getChildren().add(part);
BcModel.setResolver(resolver);
partService.showPart(part, PartState.VISIBLE);
}
public static UI getDefault() {
return fInstance;
}
public static void setJavaSourceLabel(String label, EPartService partService) {
MPart part = partService.findPart(UI.PART_JAVA_SOURCE_VIEWER_ID);
if (part != null) {
part.setLabel(label);
}
}
public static void setJavaSourceText(String source) {
IDocument document = BcModel.getJavaDocument();
if (document != null) {
document.set(source);
}
}
}
I think the problem is when i open the dialog, the activeChild changes somehow to that new opened dialog and when i close it and try immediately change my UI, it does not work because the activeChild is still not properly setup back. Otherweise i don't know why it works fine just before i opened the dialog and doesn't work just after the dialog is closed.
Does anyone know if it is bug?
I am developing in Visual Studio 2012 web interface. When I remove a parent node it removes correctly, but when I try to remove a child node the node stays and does not seem to get removed. Both methods shows the same result.
Tree1.Nodes.Remove(e.Node);
This is a postback method removing the node with e as FineUI.TreeCommandEventArgs.
Tree1.Nodes.Remove(Tree1.SelectedNode);
This is another method to remove the node. There is no update or refresh method to refresh the tree. Both of which cannot delete a child node.
Another question would be that I want to update the database based on the SelectedNode, the SelectedNodeID contains a string with the ID value, but it exist in a form like fnode1 where I only want the integer value at the end. I want to know how to get just the integer value so I can delete the selected node from the database.
what u need to do is you need to take DefaultNode from Tree and then u have to Remove it. see this.
DefaultMutableTreeNode defaultMutableTreeNode = new DefaultMutableTreeNode(node_vervesystems);
model.removeNodeFromParent(defaultMutableTreeNode);
that will Work.
Here the Example for the same.
import javax.swing.JFrame;
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author kishan
*/
public class JTreeRemoveNode extends JFrame{
public JTreeRemoveNode() throws HeadlessException {
initializeUI();
}
private void initializeUI() {
setSize(200, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Address Book");
String[] names = new String[] {"Alice", "Bob", "Carol", "Mallory"};
for (String name : names) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(name);
root.add(node);
}
final JTree tree = new JTree(root);
JScrollPane pane = new JScrollPane(tree);
pane.setPreferredSize(new Dimension(200, 400));
JButton removeButton = new JButton("Remove");
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
TreePath[] paths = tree.getSelectionPaths();
for (TreePath path : paths) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
if (node.getParent() != null) {
model.removeNodeFromParent(node);
}
}
}
});
getContentPane().setLayout(new BorderLayout());
getContentPane().add(tree, BorderLayout.CENTER);
getContentPane().add(removeButton, BorderLayout.SOUTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JTreeRemoveNode().setVisible(true);
}
});
}
}
hope that will help.
After building a perspective in application.e4xmi file, I am unable to reset perspective by calling IWorkbenchPage.resetPerspective().
I thought this may save others some time, as well as document it for myself.
The trick to being able to reset an e4 perspective is as follows (assumes a basic application.e4xmi with PerspectiveStack element):
In your application.e4xmi file, locate your PerspectiveStack under your Application/TrimmedWindow node. Record/set its ID.
In Eclipse 4 Model Editor, drag your Perspective(s) from underneath your PerspectiveStack to Application/Snippets. (This will cause your perspective IDs to register with IPerspectiveRegistry, and provide a pristine state).
Create new CopyPerspectiveSnippetProcessor. This will copy the perspectives in your snippets to your PerspectiveStack on startup. This makes it so you don't have to maintain two copies of each perspective element in your e4xmi file.
package com.example.application.processors;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
/**
* Copies all snippet perspectives to perspective stack called "MainPerspectiveStack" In order to register/reset perspective and not have to sync two copies in
* e4xmi.
*
*/
public class CopyPerspectiveSnippetProcessor {
private static final String MAIN_PERSPECTIVE_STACK_ID = "MainPerspectiveStack";
#Execute
public void execute(EModelService modelService, MApplication application) {
MPerspectiveStack perspectiveStack = (MPerspectiveStack) modelService.find(MAIN_PERSPECTIVE_STACK_ID, application);
// Only do this when no other children, or the restored workspace state will be overwritten.
if (!perspectiveStack.getChildren().isEmpty())
return;
// clone each snippet that is a perspective and add the cloned perspective into the main PerspectiveStack
boolean isFirst = true;
for (MUIElement snippet : application.getSnippets()) {
if (snippet instanceof MPerspective) {
MPerspective perspectiveClone = (MPerspective) modelService.cloneSnippet(application, snippet.getElementId(), null);
perspectiveStack.getChildren().add(perspectiveClone);
if (isFirst) {
perspectiveStack.setSelectedElement(perspectiveClone);
isFirst = false;
}
}
}
}
}
Register your CopyPerspectiveSnippetProcess into your plugin.xml file.
<extension id="MainAppModel" point="org.eclipse.e4.workbench.model">
<processor beforefragment="false" class="com.example.application.processors.CopyPerspectiveSnippetProcessor"/>
</extension>
Reset the perspective as normal. You will also want to set the perspective stack and the current perspective to visible, as these can sometimes be set to invisible. A sample handler might look like:
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.ui.PlatformUI;
public class ResetPerspectiveHandler {
private static final String MAIN_PERSPECTIVE_STACK_ID = "MainPerspectiveStack";
#Execute
public void execute(EModelService modelService, MApplication application) {
MPerspectiveStack perspectiveStack = (MPerspectiveStack) modelService.find(MAIN_PERSPECTIVE_STACK_ID, application);
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().resetPerspective();
perspectiveStack.getSelectedElement().setVisible(true);
perspectiveStack.setVisible(true);
}
}
Reset perspective (when you lunch e4 application without clearing work space, when you switch other perspective to your perceptive).
Step 1: Add a add-on in your model fragment at application level.
Step 2: Create Add-on class and implement EventHandler
Step 3: add following code in the class.
public class ResetPrespectiveAddOn implements EventHandler {
private static final String MY_PERSPECTIVE_ID = "myPrespectiveId";
#Inject
private IEventBroker broker;
#PostConstruct
public void loadPrespective() {
broker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT, this);
}
#SuppressWarnings("restriction")
#Override
public void handleEvent(Event event) {
//UIEvents.EventTags.ELEMENT is trigger for all UI activity
Object property = event.getProperty(UIEvents.EventTags.ELEMENT);
if (!(property instanceof PerspectiveStackImpl)) {
return;
}
// Reset perspective logic .
IEclipseContext serviceContext = E4Workbench.getServiceContext();
final IEclipseContext appContext = (IEclipseContext) serviceContext.getActiveChild();
EModelService modelService = appContext.get(EModelService.class);
MApplication application = serviceContext.get(MApplication.class);
MWindow mWindow = application.getChildren().get(0);
PerspectiveStackImpl perspectiveStack = (PerspectiveStackImpl) property;
List<MPerspective> children = perspectiveStack.getChildren();
for (MPerspective myPerspective : children) {
if (myPerspective.getElementId().equals(MY_PERSPECTIVE_ID)) {
//find active perspective
MPerspective activePerspective = modelService.getActivePerspective(mWindow);
if(activePerspective.getElementId().equals(MY_PERSPECTIVE_ID))
//Reseting perspective e3 way
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().resetPerspective();
// till now there is no direct e4 way to reset perspective
// but u can Add and remove e4 perspective with this code code
EPartService partService = serviceContext.get(EPartService.class);
MPerspectiveStack perspectiveStack = (MPerspectiveStack) (MElementContainer<?>) activePerspective.getParent();
int indexOf = perspectiveStack.getChildren().indexOf(activePerspective);
perspectiveStack.getChildren().remove(indexOf);
perspectiveStack.getChildren().add(myPerspective);
partService.switchPerspective(myPerspective);
}
}
}}
I am having trouble getting images to display when using ImageBundle. I have followed the GWT tutorial as a guide however my images don't display.
I can view the images (from within Eclipse) in my browser fine - so they are definitely there. I am clearly doing something wrong when using the ImageBundle but I'm at a loss to understand what it is I am doing wrong.
The logo.jpg image should simply display itself.
The ajaxLoader.gif should display itself first (in order to cover the RPC which gets the facebook user profile data) and then it would be replaced by the image at the pic_square url.
When I look at the GWT generated html, I find that where the logo.jpg image should be, there is a gif image [http://sandpit1965.appspot.com/sandpit/clear.cache.gif] but I don't understand where this is coming from.
Any help would be appreciated - source code below.
Darren
Image Package Structure
org.redboffin.sandpit.client.icons
|___ SandpitImageBundle.java
|___ ajaxLoader.gif
|___ logo.jpeg
Relevent Classes
package org.redboffin.sandpit.client.facebook;
import org.redboffin.sandpit.client.icons.SandpitImageBundle;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ErrorEvent;
import com.google.gwt.event.dom.client.ErrorHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.XMLParser;
public class ProfileWidget extends Composite implements RBWidget {
// Data
private String firstName = null;
private String lastName = null;
private String picSquareUrl = null;
// Elements
private Image picSquare = new Image();
private Image logo = new Image();
private Button logoutButton = new Button("Logout");
private DockPanel panel = new DockPanel();
private HTML html = new HTML("Welcome to Sandpit.");
/**
* Create a remote service proxy to talk to the server-side User Data
* service.
*/
private final UserDataServiceAsync userDataService = GWT.create(UserDataService.class);
public ProfileWidget() {
this.rpcWidget = new RPCWidget(this);
this.initProfileImage();
this.initLogoImage();
panel.add(picSquare, DockPanel.WEST);
panel.add(html, DockPanel.CENTER);
VerticalPanel verticalPanel = new VerticalPanel();
verticalPanel.add(logo);
verticalPanel.add(logoutButton);
panel.add(verticalPanel, DockPanel.EAST);
panel.add(rpcWidget, DockPanel.SOUTH);
initWidget(panel);
}
private void initProfileImage() {
// Display ajaxLoader.gif
SandpitImageBundle sib = GWT.create(SandpitImageBundle.class);
AbstractImagePrototype aip = sib.ajaxLoader();
sib.applyTo(this.picSquare);
}
private void initLogoImage() {
// Display logo.jpg
SandpitImageBundle sib = GWT.create(SandpitImageBundle.class);
AbstractImagePrototype aip = sib.logo();
aip.applyTo(this.logo);
}
// Other methods omitted...
}
package org.redboffin.sandpit.client.icons;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.ImageBundle;
public interface SandpitImageBundle extends ImageBundle {
/**
* Would match the file 'logo.jpg', 'logo.gif', or 'logo.png' located in the
* same package as this type.
*/
public AbstractImagePrototype logo();
/**
* Would match the file 'ajaxLoader.jpg', 'ajaxLoader.gif', or 'ajaxLoader.png' located in the
* same package as this type.
*/
public AbstractImagePrototype ajaxLoader();
}
I don't understand why but this now works and I haven't changed anything.
The image won't be displayed until you "compile" your project and place your generated "war" in your servers public folder. You were simply making a request to a non existing file.