plugin development in eclipse - java

i have this problem with my project these days. i'm developing a plugin in eclipse,
i need to write a text on the active window(coding area) when i click a button.
i use the following code in my button.java class
public class Button implements IWorkbenchWindowActionDelegate {
private IWorkbenchWindow window;
/**
* The constructor.
*/
public Button() {
}
/**
* The action has been activated. The argument of the
* method represents the 'real' action sitting
* in the workbench UI.
* #see IWorkbenchWindowActionDelegate#run
*/
public void run(IAction action) {
MessageDialog.openInformation(
window.getShell(),
"Button",
"Code of the Button goes here");
}
how can i do it inside the run method? here I'm displaying a message, instead of showing a message i want to display some text in the text editor pane. please help me to achieve this.
if you guys can please give me some links to understand about eclipse plug-in developments? any blog posts that are easy to understand will be much better?

You should do something like this. It is completely untested and you will need to add lots of null checks and try-catch blocks, but the code below gets the currently active editor and replaces the current selection with whatever is passed in as an argument:
void method (String text) {
IEditorPart part = Workbench.getInstance().getWorkbenchWindows()[0].getActivePage().getActiveEditor();
IEditorInput editorInput = part.getEditorInput();
if (part instanceof ITextEditor) {
ITextEditor textEditor = (ITextEditor) part;
IDocument doc = textEditor.getDocumentProvider().getDocument(editorInput);
ITextSelection sel = textEditor.getSelectionProvider().getSelection();
doc.replace(sel.getOffset(), sel.getLength(), text);
}
}
It is messy and complicated, but that's the Eclipse framework for you.
This might be a good place for you to look at Eclipse plugin development:
http://www.ibm.com/developerworks/views/opensource/libraryview.jsp?search_by=Create+commercial-quality+eclipse+ide
Developer Works in general has a lot of good content on Eclipse, so if this series is not exactly what you need, you can explore Developer Works for other things.

I'd recommend this one. It is a very good introductory tutorial

Related

Java JOptionPane Visual Artifact from Window Interaction

I am trying to create a simple menu for a small project using a JSpinner and JOptionPane. I created my desired output, but when I interact with the window or even hover over the buttons in the box, it creates visual artifacts over and over again (see images below):
JOptionPane before mouse hover
JOptionPane after mouse hover
I did some researching and thought it might be due to JOptionPane not being thread safe, but could not get anything to work.
Overall, my specific question is how do I prevent Java from repainting these visual artifacts over my JOptionPane window?
For reference, please see the method I am using to show this menu:
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SpinnerNumberModel;
import javax.swing.JSpinner;
public class Battleship
{
public static void main(String[] args)
{
SpinnerNumberModel battleshipRange = new SpinnerNumberModel(1, 1, 5, 1);
JSpinner rangeSpinner = new JSpinner(battleshipRange);
JOptionPane.showMessageDialog(null, rangeSpinner, "Battleship Number", JOptionPane.QUESTION_MESSAGE);
}
}
I am running this code on BlueJ and am using Windows 10 Pro.
Thank you in advance and apologies if this is a beginner question. I am still fairly new to programming.
EDIT: Updated code to give complete source of problem, but it disappeared. I will keep an eye on it to see where the source of the error first occurred.
After completing my project, I finally found why visual artifacts would pop up in all buttons/radio buttons/etc. in my game.
In the GridWorld source code, under the "GridPanel.java" script, the original programmers created a method called "setToolTipsEnabled(boolean flag)". Its function is to pop up a message box next to the cursor when it is hovering over the grid when the game stops running.
When extending GridWorld to create my project, the method reaches past the grid structure and attempts to create a tool tip underneath anything the cursor hovers over. Thus, creating visual artifacts on buttons/radio buttons/etc.
To fix this, I made sure this method was always set to false as I did not need tool tips for my game anyway. This method was implemented in the "GridPanel.java" and "GUIController.java" scripts (in the GridWorld code). I changed following methods to fix this problem:
GridPanel.java
/**
* Construct a new GridPanel object with no grid. The view will be
* empty.
*/
public GridPanel(DisplayMap map, ResourceBundle res)
{
displayMap = map;
resources = res;
// Phillip Sturtevant: Commented out to prevent visual artifacts
//setToolTipsEnabled(true);
}
GUIController.java
/**
* Stops any existing timer currently carrying out steps.
* Phillip Sturtevant Note: keep tool tips hidden to prevent visual artifacts
*/
public void stop()
{
display.setToolTipsEnabled(false); // hide tool tips while stopped
timer.stop();
running = false;
}
Alternatively, the method calls could be omitted entirely, but I commented them out in case I needed them in the future.
For reference, the method below sets the tool tips visibility in GridWorld (located in "GridPanel.java"):
/**
* Enables/disables showing of tooltip giving information about the
* occupant beneath the mouse.
* #param flag true/false to enable/disable tool tips
*/
public void setToolTipsEnabled(boolean flag)
{
if ("hide".equals(System.getProperty("gridworld.gui.tooltips")))
flag = false;
if (flag)
ToolTipManager.sharedInstance().registerComponent(this);
else
ToolTipManager.sharedInstance().unregisterComponent(this);
toolTipsEnabled = flag;
}

Eclipse RCP view will not update when editor data is modified

I'm attempting to do something that seems like it should be quite common, so I'm surprised I'm having a hard time finding a solution.
I have a simple Eclipse RCP application. It consists of a view, containing a treeViewer that displays elements of an xml file hierarchically. The other side is an editor, which contains various fields such as textboxes, etc, for displaying and also modifying the xml values. The treeviewer displays icons alongside the element name, and what I'm trying to do is change the icon to a "modified" version of the icon whenever a change is made in the editor - signifying that a value of that element has been changed. This is very similar to how Eclipse, when integrated with subversion, shows that a file has been modified from the base revision in the Package Explorer.
I'll try to just show the parts of the code relevant to this specific issue and hope I don't leave anything out. This is the editor class:
public class XmlEditor extends EditorPart
{
protected boolean dirty = false;
public void setDirty(boolean value)
{
dirty = value;
firePropertyChange(PROP_DIRTY);
}
}
and this is the view with the tree:
public class TreeView extends ViewPart implements IPropertyChangeListener {
public void createPartControl(Composite parent) {
treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL);
getSite().setSelectionProvider(treeViewer);
treeViewer.setLabelProvider(new TreeObjLabelProvider());
treeViewer.setContentProvider(new TreeObjContentProvider());
PlatformUI.getWorkbench().getWorkingSetManager().addPropertyChangeListener(this);
}
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(IWorkbenchPartConstants.PROP_DIRTY)) {
treeViewer.refresh();
}
}
}
In this scenario, TreeView::propertyChange() is not getting called, even though firePropertyChange() is getting fired. Any ideas why? I'm also open to any other ideas that don't involve PropertyChangeListener, it just seemed like this would be the easiest way at the time. Thank you.
Here's how I ended up solving the problem:
Changed TreeView to implement IPropertyListener instead of IPropertyChangeListener
Implemented the propertyChanged() method to perform a treeViewer.refresh()
In the XmlEditor::createPartControl() method I got a reference to the Treeview part and then added it to the property listeners like so:
TreeView treeView = (TreeView) getSite().getPage().findView(TreeView.ID);
addPropertyListener(treeView);
Now, TreeView::propertyChanged() gets called after firePropertyChanged(), just like I needed. It took quite a bit of experimentation to learn the difference between IPropertyListener and IPropertyChangeListener, addPropertyListener() and addPartPropertyListener().
Thanks to nitind for giving me a new perspective, and for showing me about Decorators, which is definitely the right way to go as opposed to changing the tree icon to a modified version.
You fired a property change in the editor part, which is unrelated to the working set manager. Nothing you've done connects the view to the editor. If you want the two to talk to each other, write them to talk to each other, or at least create and react to events from making the modifications you describe.
I'm also pretty certain that's not how SVN shows that a file has been modified.
SVN is probably supplying a Decorator: http://eclipse.org/articles/Article-Decorators/decorators.html
Add this bunch of code in your create part control this will may be help you
ResourcesPlugin.getWorkspace().addResourceChangeListener(new IResourceChangeListener() {
#Override
public void resourceChanged(IResourceChangeEvent event) {
treeViewer.refresh();
}
});

Eclipse RCP: Custom console

I am trying to create a console that would work as a shell for a custom programming language. It would be very similar to the pydev interactive console.
Currently, my RCP uses the basic TextConsole and is connected to the shell via pipes so it just displays whatever the shell displays and if the user enters anything in the RCP console, the same is written in the shell.
I want to be able to do a bit more such as move the caret position, add events for up and down arrow keys etc. I believe to do that I need to add a StyledText widget to the console which is done via the ConsoleViewer.
So my question is, that is there any way for me to either override the TextConsole's ConsoleViewer or if I were to extend TextConsole and create my own, then how do I link it with the launch configuration (the one that connects the shell via pipes)?
Also, to get the current default console I use DebugUITools.getConsole(process).
I'm sorry if I haven't put all the information needed; it is a bit difficult to explain. I am happy to add more information.
An idea...
From what I understand I can create a TextConsolePage from the TextConsole using createPage(ConsoleView). Once I have the page I can set the viewer via setViewer(viewer). Here I thought if I create my own viewer (which will have the appropriate stylewidget) then that could be a lead. The only problem is that the viewer needs a Composite and I can't seem to figure out where to get that from.
Why don't you just follow what PyDev does (if you're able to cope with the EPL license)?
The relevant code may be found at:
https://github.com/aptana/Pydev/tree/ad4fd3512c899b73264e4ee981be0c4b69ed5b27/plugins/org.python.pydev/src_dltk_console
https://github.com/aptana/Pydev/tree/ad4fd3512c899b73264e4ee981be0c4b69ed5b27/plugins/org.python.pydev.debug/src_console
So I thought I would answer this myself as I was finally able to accomplish the console. It still is a working prototype but I guess as you keep adding things, you can clean up the code more and more. For my current purposes this is how it worked.
If you want the short version, then I basically mimicked the ProcessConsole provided by Eclipse as that is what I needed: a console in which I can connect a process but since the ProcessConsole is internal, I like to avoid extending those classes.
Following is an outline of the classes I used to achieve interaction with my console. I am not going to give the pretext as to where MyConsole was created. Basically, instead of using DebugUITools.getConsole(myProcess), I used my own myProcess.getConsole() method. MyProcess extends RuntimeProcess.
class MyConsole extends IOConsole {
private IOConsoleInputStream fInput;
private IOConsoleOutputStream fOutput;
private IStreamsProxy fStreamsProxy;
private ConsoleHistory history;
//This is to remember the caret position after the prompt
private int caretAtPrompt;
/* in the console so when you need to replace the command on up and down
* arrow keys you have the position.
* I just did a caretAtPrompt += String.Length wherever string was
* appended to the console. Mainly in the streamlistener and
* InputJob unless you specifically output something to the output
* stream.
*/
//In the constructor you assign all the above fields. Below are some
//to point out.
//fInput = getInputStream();
// fStreamsProxy = process.getStreamsProxy();
// fOutput = newOutputStream();
//We must override the following method to get access to the caret
#Override
public IPageBookViewPage createPage(IConsoleView view) {
return new MyConsolePage(this, view);
}
//After this I followed the ProcessConsole and added the
//InputJob and StreamListener
//defined in there.
}
class MyConsolePage extends TextConsolePage {
//Not much in this class, just override the createViewer
// to return MyConsoleViewer
}
class MyConsoleViewer extends TextConsoleViewer {
//This is the most important class and most of the work is done here
//Again I basically copied everything from IOConsoleViewer and then
//updated whatever I needed
//I added a VerifyKeyListener for the up and down arrow
//keys for the console history
MyConsoleViewer (Composite parent, MyConsole console) {
//I have omitted a lot of code as it was too much to put up,
//just highlighted a few
getTextWidget().addVerifyKeyListener(new MyKeyChecker());
}
class MyKeyChecker implements VerifyKeyListener {...}
}
This is the code for ProcessConsole.
This is the code for IOConsoleViewer.
The ConsoleHistory class I created just had a doubly linked string list to save all the commands the user entered. Quite a simple class to create.
Once you look at the Eclipse classes (ProcessConsole and IOConsoleViewer) it is actually all quite self explanatory. I haven't put in much code here because there is quite a bit. But hopefully this gives some direction as I was completely lost when I started.
I am happy to answer questions though and add more specific code if anyone asks.

Adding figures using contextual menu - Eclipse GEF

All,
I am creating a palette less eclipse plugin where am adding figures to the custom editor through the contextual menu, but am not finding a way to do it. Can anyone please guide me as to how to go about adding figures to editor dynamically through context menu i.e. adding actions/commands.
Since Eclipse GEF plugin development finds so less examples to look at, I am adding my solution so others find it useful. This code helps to render a node to the editor.
Source code for Action class to render figures to the editor:
public class AddNodeAction extends EditorPartAction
{
public static final String ADD_NODE = "ADDNODE";
public AddNodeAction(IEditorPart editor) {
super(editor);
setText("Add a Node");
setId(ADD_NODE); // Important to set ID
}
public void run()
{
<ParentModelClass> parent= (<ParentModelClass>)getEditorPart().getAdapter(<ParentModelClass>.class);
if (parent== null)
return;
CommandStack command = (CommandStack)getEditorPart().getAdapter(CommandStack.class);
if (command != null)
{
CompoundCommand totalCmd = new CompoundCommand();
<ChildModelToRenderFigureCommand>cmd = new <ChildModelToRenderFigureCommand>(parent);
cmd.setParent(parent);
<ChildModelClass> newNode = new <ChildModelClass>();
cmd.setNode(newNode);
cmd.setLocation(getLocation()); // Any location you wish to set to
totalCmd.add(cmd);
command.execute(totalCmd);
}
}
#Override
protected boolean calculateEnabled()
{
return true;
}
}
I think you need multiple different things here. Please remember that GEF would like you to have proper MVC pattern, where you have your own model, Figures as View and EditParts as controllers.
From the top of my head I would say that you need at least these things:
CreateCommand
contains all model level modifications that you need to
perform to add your new data to your
data model (undoable and transactional)
CreateAction
makes that CreateCommand instance, initializes it with current selection and executes that command in editdomain
ContextMenuProvider
Provides that CreateAction to context menu
If you happen to be using GMF the canonical mechanism will generate the editparts for you automatically when you make the model modifications inside a command, but if you are not using GMF, you must make sure that your own models and editparts are handling and refreshing the new item adding properly.
EDIT:
Ok, here is some code suggestion with playing around with requests.
public void run() {
// Fetch viewer from editor part (might not work, if not, try some other way)
EditPartViewer viewer = (EditPartViewer) part.getAdapter(EditPartViewer.class);
// get Target EditPart that is under the mouse
EditPart targetEditPart = viewer.findObjectAt(getLocation());
// If nothing under mouse, set root item as target (just playing safe)
if(targetEditPart == null)
targetEditPart = viewer.getContents();
// Make and initialize create request with proper information
CreateRequest createReq = new CreateRequest();
createReq.setLocation(getLocation());
createReq.setFactory(new OwnFactoryImplementation());
// Ask from target editpart command for this request
Command command = targetEditPart.getCommand(createReq);
// If command is ok, and it can be executed, go and execute it on commandstack
if(command != null && command.canExecute()) {
viewer.getEditDomain().getCommandStack().execute(command);
}
}
Now what happens is that editpart will be requested for creation, so the action itself doesn't know how the command works, what makes it objective agaist the command.
So to make things work, you need to install new EditPolicy to your EditPart. EditPolicies can be installed on EditParts createDefaultEditPolicies() function. This EditPolicy must react and return command when there is CreateRequest. This way any child can provide own kind of command for creating children for itself.
Here is a good image how it works (controller is EditPart):
Please ask if I can help you some more. I know that this looks bit more complex, but this makes your own life much more easier, and after you have done that, you actually understand Command-Request Pattern quite well, and it can be reused in many different places.

Wrapping/decorating GWT FileUpload

GWT FileUpload comes as a widget that produces so that one can upload a file during form submit (at least it's how I understand it :) ) What I want to do is to make it a better-looking and get rid of standard "Browse..." button.
Since I don't have good GWT experience (and no JavaScript), I looked for existing solutions and found quite a good project - gwtupload. It's good, but I realized I'd love to have my own miniature version (and also, I was curious about how it works). So I browsed through code and tried to extract the magic part. I realized that GWT FileInput is used, but it's not shown, and Button clicks are delegated to this FileInput. The code I tried to extract (only the part that delegates the click) after reviewing sources of gwtupload contains this tricky elem.click() JSNI:
class MyUpload extends Composite {
private static native void clickOnInputFile(Element elem) /*-{
elem.click();
}-*/;
public MyUpload() {
final FileUpload upload = new FileUpload();
AbsolutePanel container = new AbsolutePanel();
// container.add(upload);
Button btn = new Button("My Browse..");
btn.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
clickOnInputFile(upload.getElement());
}
});
container.add(btn);
initWidget(container);
}
}
But this seems not to work: clicking on 'My Browse..' results in no effect (just in case I also tried running with un-commented container.add(upload) line) . Could you please help me in understanding what's wrong/missing in this code sample?
Thank you in advance.
P.S. I know that I have to place it on the FormPanel, and I know the rest about how to perform the actual submit/handling in Servlet; the only thing I want to do is this kind of decoration.
Since I have not received any answers, I had to have more investigation of this issue, so I performed a deeper code analysis of gwtupload project in order to understand how GWT FileUpload (which gets transformed into ) can be decorated.
It turned out that element.click() will only work in browsers which support #click() method (IE, Chrome, Safari). Actually, Manuel Carrasco MoƱino - project author - mentions it within comments. There's second approach (for Firefox & Opera) that uses hack when FileInput is placed on transparent panel, which however is placed over some decorated button (using absolute positioning); comment by Manuel:
When the user puts his mouse over the button and clicks on it, what really happens is that the user clicks on the transparent file input showing the choose file dialog.
After that, the main work is correctly applying style attributes to elements.
Thus, there are two implementations of custom file upload component, and GWT deferred binding is used to instantiate them depending on Browser.
As for example I mention in my question, there're few fixes ("upload" has to be added to to the container, and it can be set to #setVisible(false)):
class MyUpload extends Composite {
private static native void clickOnInputFile(Element elem) /*-{
elem.click();
}-*/;
public MyUpload() {
final FileUploadWithMouseEvents upload = new FileUploadWithMouseEvents();
AbsolutePanel container = new AbsolutePanel();
container.add(upload);
upload.setVisible(false);
Button btn = new Button("My Browse..");
btn.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
clickOnInputFile(upload.getElement());
}
});
container.add(btn);
initWidget(container);
}
}
This example works fine in IE8.
P.S. Thanks to Manuel for his great library :)

Categories

Resources