Change Eclipse toolbar icon dynamically - java

I've got a toolbar item with its own icon, defined in the plugin.xml file like:
<action
class="MyActionClass"
id="MyActionID"
label="MyActionLabel"
menubarPath="MyActionMenuBarPath"
toolbarPath="MyActionToolBarPath"
icon="icon/myicon.png" <---- this one
...
</action>
How do I change this dynamically when needed? I mean changing it from code

Use org.eclipse.ui.menus extension point instead and add menuContribution with dynamic. The class of dynamic should subclass ControlContribution and implement createControl method to create a button.

You should implements IElementUpdater in your Handler class.
Please refer to : https://stackoverflow.com/a/23742598/2893073
Handler class
import java.util.Map;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.commands.IElementUpdater;
import org.eclipse.ui.menus.UIElement;
import com.packpub.e4.menu.Activator;
public class SampleHandler2 extends
AbstractHandler implements IElementUpdater{
private static ImageDescriptor image_enable =
Activator.getImageDescriptor("icons/btn_adapt_enable.png");
private static ImageDescriptor image_disable =
Activator.getImageDescriptor("icons/btn_adapt_disable.png");
/**
* The constructor.
*/
public SampleHandler2() {
}
/**
* the command has been executed, so extract extract the needed information
* from the application context.
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
//...
return null;
}
#Override
public void updateElement(UIElement element, #SuppressWarnings("rawtypes") Map map) {
boolean condition = false;
//...
if( condition ) {
element.setIcon(image_disable);
}else{
element.setIcon(image_enable);
}
}
}
invoke this Handler using ICommandService:
IWorkbenchWindow window = part.getSite().getWorkbenchWindow();
ICommandService commandService = (ICommandService) window.getService(ICommandService.class);
if (commandService != null) {
commandService.refreshElements("com.packpub.e4.menu.commands.sampleCommand", null);
}
Thanks.

Related

How does the class loader loads an instance of extended class which is declared inside a method? (java.lang.NoClassDefFoundError)

I have a class which have util functions and can be invoked on demand.
Steps to Reproduce :
TestMainWebApp (this project having Dependency of TestMainImp)
TestMainImpl ( this project implements TestMainInterface)
TestMainInterface
TestMainWebApp > TestMainServlet.java
package com.main;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.test.util.Util;
/**
* Servlet implementation class TestMainServlet
*/
#WebServlet("/TestMainServlet")
public class TestMainServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("\nCurrent ClassLoader chain: "+JavaEETrainingUtil.getCurrentClassloaderDetail());
Util prov = new Util();
// prov.test();
}
}
TestMainImpl > Util.java & TLSErrorRedirectListener.java
package com.test.util;
public class Util {
private final static String CLAZZ = Util.class.getName();
static {
System.out.println("Classloading of "+CLAZZ+" in progress..."+JavaEETrainingUtil.getCurrentClassloaderDetail());
}
public boolean checkForTLSErrorRedirection(boolean b) {
test.intf.ConfigurationListener listener = new com.listener.TLSErrorRedirectListener();
listener.valueChanged("test", "test");
return true;
}
public void test() {
System.out.println(" test util");
}
}
TLSErrorRedirectionListener.java
package com.listener;
import com.test.util.JavaEETrainingUtil;
public class TLSErrorRedirectListener implements test.intf.ConfigurationListener {
final static String CLAZZ = TLSErrorRedirectListener.class.getName();
static {
System.out.println("Classloading of "+CLAZZ+" in progress..."+JavaEETrainingUtil.getCurrentClassloaderDetail());
}
public void valueChanged(String key, String value) {
switch(key){
case "test1":
default : break;
}
}
}
TestMainInterface >ConfigurationListener.java
package test.intf;
public abstract interface ConfigurationListener
{
public abstract void valueChanged(String paramString1, String paramString2);
}
CASE :
TestMainInterface.jar will be in classpath of TestMainImpl.jar (#compiletime only)
At RunTime (i wont have TestMainInterface.jar) and I don't invoke the method "checkForTLSErrorRedirection()" . i invoke only test() method.
But Iam getting , java.lang.NoClassDefFoundError: test/intf/ConfigurationListener
when i create instance itself.
Can you please help to find out the root cause ? How does the java loads Class which is declared within a method ?
NOTE : JavaEETrainingUtil.java for debug purpose
package noclassdef.example1;
import java.util.Stack;
import java.lang.ClassLoader;
/**
* JavaEETrainingUtil
* #author Pierre-Hugues Charbonneau
*
*/
public class JavaEETrainingUtil {
/**
* getCurrentClassloaderDetail
* #return
*/
public static String getCurrentClassloaderDetail() {
StringBuffer classLoaderDetail = new StringBuffer();
Stack<ClassLoader> classLoaderStack = new Stack<ClassLoader>();
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
classLoaderDetail.append("\n-----------------------------------------------------------------\n");
// Build a Stack of the current ClassLoader chain
while (currentClassLoader != null) {
classLoaderStack.push(currentClassLoader);
currentClassLoader = currentClassLoader.getParent();
}
// Print ClassLoader parent chain
while(classLoaderStack.size() > 0) {
ClassLoader classLoader = classLoaderStack.pop();
// Print current
classLoaderDetail.append(classLoader);
if (classLoaderStack.size() > 0) {
classLoaderDetail.append("\n--- delegation ---\n"); } else {
classLoaderDetail.append(" **Current ClassLoader**");
}
}
classLoaderDetail.append("\n-----\n");
return classLoaderDetail.toString();
}
}
This is not correct. You should not add the abstract keyword to interfaces or their methods. No need for public on interface methods; they are required to be public.
This is correct:
package test.intf;
public interface ConfigurationListener {
void valueChanged(String paramString1, String paramString2);
}
Be sure that the test.intf.ConfigurationListener.class file appears in your deployment. If it doesn't, the class loader will never find it.

Intellij plugin: Intention for xml file that replace an attribute with two custom attribute with different prefix with same value

On a plugin I want to do the following action for an intention in XML file.
Intention appear when you are on an xml attribute (cursor on text)
When intention is invoked I want to add two attribute to label tag like below:
what's the code that replace text="hello" with i:text="hello" a:text="hello"
I tried the code below:
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.XmlElementFactory;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlToken;
import com.intellij.util.IncorrectOperationException;
import org.igu.plugins.nativescript.NsBundle;
import org.igu.plugins.nativescript.NsFacade;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
/**
*/
public class PlatformSpecificPropertyValue extends PsiElementBaseIntentionAction {
public PlatformSpecificPropertyValue() {
setText(NsBundle.message("intention.declare.platform.specific.property.value"));
}
#Override
public void invoke(#NotNull Project project, Editor editor, #NotNull PsiElement psiElement) throws IncorrectOperationException {
if (psiElement instanceof XmlToken) {
XmlToken xmlToken = (XmlToken) psiElement;
final PsiElement parent = xmlToken.getParent();
if (parent instanceof XmlAttribute) {
XmlAttribute xmlAttribute = (XmlAttribute) parent;
String localName = xmlAttribute.getLocalName();
String value = xmlAttribute.getValue();
final XmlTag tag = xmlAttribute.getParent();
final XmlAttribute iAttribute = XmlElementFactory.getInstance(project).createAttribute("i:"+localName, value, tag);
final XmlAttribute aAttribute = XmlElementFactory.getInstance(project).createAttribute("a:"+localName, value, tag);
if (!FileModificationService.getInstance().prepareFileForWrite(xmlAttribute.getContainingFile())) {
return;
}
new WriteCommandAction(project, tag.getContainingFile()) {
#Override
protected void run(#NotNull Result result) throws Throwable {
tag.addAfter(xmlAttribute, iAttribute);
tag.addBefore(xmlAttribute, aAttribute);
xmlAttribute.delete();
}
}.execute();
}
}
}
#Override
public boolean isAvailable(#NotNull Project project, Editor editor, #NotNull PsiElement psiElement) {
return psiElement instanceof XmlToken;
}
#Nls
#NotNull
#Override
public String getFamilyName() {
return getText();
}
}
Thanks.
You swapped the two arguments of addAfter() and addBefore():
/**
* Adds a child to this PSI element, after the specified anchor element.
*
* #param element the child element to add.
* #param anchor the anchor after which the child element is inserted (must be a child of this PSI element)
* #return the element which was actually added (either <code>element</code> or its copy).
* #throws IncorrectOperationException if the modification is not supported or not possible for some reason.
*/
PsiElement addAfter(#NotNull PsiElement element, #Nullable PsiElement anchor) throws IncorrectOperationException;
The correct code should be:
tag.addAfter(iAttribute, xmlAttribute);
tag.addBefore(aAttribute, xmlAttribute);
xmlAttribute.delete();

JavaFX CustomControl<T>: Is this possible?

I want to create a simple reusable custom control in JavaFX that is nothing more than a ComboBox with a label over its head that can have the text set.
I would like for it to be usable in JavaFX Scene Builder.
I would also like for it to be able to take a single Generic Parameter <T> to be able to as closely as possible emulate the behavior of the standard ComboBox that is available.
The problem which I am encountering is that when I attempt to set the Controls Controller to Controller<T> in SceneBuilder, I get an error telling me: Controller<T> is invalid for Controller class.
This makes sense as when you call FXMLLoader.load() (after setting the root, classLoader, and Location), there is no way (that I can find) to tell the loader "Oh, and this is a CustomControl."
This is the code I have for the Control:
public class LabeledComboBox<T> extends VBox {
private final LCBController<T> Controller;
public LabeledComboBox(){
this.Controller = this.Load();
}
private LCBController Load(){
final FXMLLoader loader = new FXMLLoader();
loader.setRoot(this);
loader.setClassLoader(this.getClass().getClassLoader());
loader.setLocation(this.getClass().getResource("LabeledComboBox.fxml"));
try{
final Object root = loader.load();
assert root == this;
} catch (IOException ex){
throw new IllegalStateException(ex);
}
final LCBController ctrlr = loader.getController();
assert ctrlr != null;
return ctrlr;
}
/*Methods*/
}
This is the Controller class:
public class LCBController<T> implements Initializable {
//<editor-fold defaultstate="collapsed" desc="Variables">
#FXML private ResourceBundle resources;
#FXML private URL location;
#FXML private Label lbl; // Value injected by FXMLLoader
#FXML private ComboBox<T> cbx; // Value injected by FXMLLoader
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Initialization">
#Override public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
this.location = fxmlFileLocation;
this.resources = resources;
//<editor-fold defaultstate="collapsed" desc="Assertions" defaultstate="collapsed">
assert lbl != null : "fx:id=\"lbl\" was not injected: check your FXML file 'LabeledComboBox.fxml'.";
assert cbx != null : "fx:id=\"cbx\" was not injected: check your FXML file 'LabeledComboBox.fxml'.";
//</editor-fold>
}
//</editor-fold>
/*Methods*/
}
Clearly there is something that I am missing here. I am really hoping this is possible without having to come up with my own implementation of the FXMLLoader Class (REALLY, REALLY, REALLY REALLY hoping).
Can someone please tell me what I am missing, or if this is even possible?
EDIT 1:
After someone pointed me to a link I may have an idea of how to do this but I'm still not one hundred percent. To me it feels like the Controller class itself can not be created with a generic parameter (I.E.: public class Controller<T>{...} = No Good)
That's kind of annoying but I guess makes sense.
Then what about applying Generic parameters to the Methods inside the custom control controller, and making the control itself (not the controller) a generic: like so?
Control:
public class LabeledComboBox<T> extends VBox {...}
Controller:
public class LCBController implements Initializable {
/*Stuff...*/
/**
* Set the ComboBox selected value.
* #param <T>
* #param Value
*/
public <T> void setValue(T Value){
this.cbx.setValue(Value);
}
/**
* Adds a single item of type T to the ComboBox.
* #param <T> ComboBox Type
* #param Item
*/
public <T> void Add(T Item){
this.cbx.getItems().add(Item);
}
/**
* Adds a list of items of type T to the ComboBox.
* #param <T> ComboBox Type
* #param Items
*/
public <T> void Add(ObservableList<T> Items){
this.cbx.getItems().addAll(Items);
}
/**
* Removes an item of type T from the ComboBox.
* #param <T> ComboBox Type
* #param Item
* #return True if successful(?)
*/
public <T> boolean Remove(T Item){
return this.cbx.getItems().remove(Item);
}
}
Would that work? Is that more along the right track? Again, my desire is nothing more than a ComboBox with a Label on it to tell users what its all about.
This worked for me, and when I imported the library into SceneBuilder it worked fine:
(Very basic) FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ComboBox?>
<fx:root xmlns:fx="http://javafx.com/fxml/1" type="VBox"
fx:controller="application.LabeledComboBoxController">
<Label fx:id="label" />
<ComboBox fx:id="comboBox" />
</fx:root>
Controller:
package application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.SingleSelectionModel;
public class LabeledComboBoxController<T> {
#FXML
private Label label ;
#FXML
private ComboBox<T> comboBox ;
public void setText(String text) {
label.setText(text);
}
public String getText() {
return label.getText();
}
public StringProperty textProperty() {
return label.textProperty();
}
public ObservableList<T> getItems() {
return comboBox.getItems();
}
public void setItems(ObservableList<T> items) {
comboBox.setItems(items);
}
public boolean isWrapText() {
return label.isWrapText();
}
public void setWrapText(boolean wrapText) {
label.setWrapText(wrapText);
}
public BooleanProperty wrapTextProperty() {
return label.wrapTextProperty();
}
public SingleSelectionModel<T> getSelectionModel() {
return comboBox.getSelectionModel();
}
}
Control:
package application;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.SingleSelectionModel;
import javafx.scene.layout.VBox;
public class LabeledComboBox<T> extends VBox {
private final LabeledComboBoxController<T> controller ;
public LabeledComboBox(ObservableList<T> items, String text) {
controller = load();
if (controller != null) {
setText(text);
setItems(items);
}
}
public LabeledComboBox(ObservableList<T> items) {
this(items, "");
}
public LabeledComboBox(String text) {
this(FXCollections.observableArrayList(), text);
}
public LabeledComboBox() {
this("");
}
private LabeledComboBoxController<T> load() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource(
"LabeledComboBox.fxml"));
loader.setRoot(this);
loader.load();
return loader.getController() ;
} catch (Exception exc) {
Logger.getLogger("LabeledComboBox").log(Level.SEVERE,
"Exception occurred instantiating LabeledComboBox", exc);
return null ;
}
}
// Expose properties, but just delegate to controller to manage them
// (by delegating in turn to the underlying controls):
public void setText(String text) {
controller.setText(text);
}
public String getText() {
return controller.getText();
}
public StringProperty textProperty() {
return controller.textProperty();
}
public boolean isWrapText() {
return controller.isWrapText();
}
public void setWrapText(boolean wrapText) {
controller.setWrapText(wrapText);
}
public BooleanProperty wrapTextProperty() {
return controller.wrapTextProperty();
}
public ObservableList<T> getItems() {
return controller.getItems();
}
public void setItems(ObservableList<T> items) {
controller.setItems(items);
}
public SingleSelectionModel<T> getSelectionModel() {
return controller.getSelectionModel();
}
}
Test code:
package application;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root,400,400);
LabeledComboBox<String> comboBox = new LabeledComboBox<String>(
FXCollections.observableArrayList("One", "Two", "Three"), "Test");
root.setTop(comboBox);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
I'm sure that this construction is not possible as FXML is evaluated at runtime. And generics are already deleted at runtime.
But what's possible to do is to assign a generic to the controller.
FXML implements the Model-View-Controller (MVC) design which is subject to the following topic:
What is MVC (Model View Controller)?
Your question ist also an issue in the following topic:
Setting TableView Generic Type from FXML

Is it possible to write your own objects that give out ActionEvents?

I've looked at the java tutorials online and they all seem concerned with catching ActionEvents given out by other components that are already written. Is it possible to write your own objects that have there own set of criteria that trigger actionEvents that can then be caught by other classes that have registered as listeners?
So for example: If I wanted an object that was counting sheep to send out an actionEvent when 100 sheep had been counted to all the sleeper objects that had registered as listeners.
Is there a way to do this are there any tutorials online?
Any help is greatly appreciated.
Yes, it's pretty straightforward, once someone shows you how to create your own listeners.
First, you create your own EventObject. Here's an example from one of my projects.
import gov.bop.rabid.datahandler.bean.InmateDataBean;
import java.util.EventObject;
public class InmatePhotoEventObject extends EventObject {
private static final long serialVersionUID = 1L;
protected InmateDataBean inmate;
public InmatePhotoEventObject(Object source) {
super(source);
}
public InmateDataBean getInmate() {
return inmate;
}
public void setInmate(InmateDataBean inmate) {
this.inmate = inmate;
}
}
There's nothing special about this class, other than it extends EventObject. Your constructor is defined by EventObject, but you can create any methods you want.
Second, you define an EventListener interface.
public interface EventListener {
public void handleEvent(InmatePhotoEventObject eo);
}
You would use the EventObject you created. You can use any method name or names that you want. This is the interface for the code that will be written as a response to the listener.
Third, you write a ListenerHandler. Here's mine from the same project.
import gov.bop.rabid.datahandler.bean.InmateDataBean;
import gov.bop.rabid.datahandler.main.EventListener;
import gov.bop.rabid.datahandler.main.InmatePhotoEventListener;
import gov.bop.rabid.datahandler.main.InmatePhotoEventObject;
import java.util.ArrayList;
import java.util.List;
public class InmatePhotoListenerHandler {
protected List<EventListener> listeners;
public InmatePhotoListenerHandler() {
listeners = new ArrayList<EventListener>();
}
public void addListener(EventListener listener) {
listeners.add(listener);
}
public void removeListener(EventListener listener) {
for (int i = listeners.size() - 1; i >= 0; i--) {
EventListener instance = listeners.get(i);
if (instance.equals(listener)) {
listeners.remove(i);
}
}
}
public void fireEvent(final InmatePhotoEventObject eo,
final InmateDataBean inmate) {
for (int i = 0; i < listeners.size(); i++) {
final EventListener instance = listeners.get(i);
Runnable runnable = new Runnable() {
public void run() {
eo.setInmate(inmate);
instance.handleEvent(eo);
}
};
new Thread(runnable).start();
}
}
public static void main(String[] args) {
System.out.println("This line goes in your DataHandlerMain class "
+ "constructor.");
InmatePhotoListenerHandler handler = new InmatePhotoListenerHandler();
System.out.println("I need you to put the commented method in "
+ "DataHandlerMain so I can use the handler instance.");
// public InmatePhotoListenerHandler getInmatePhotoListenerHandler() {
// return handler;
// }
System.out.println("This line goes in the GUI code.");
handler.addListener(new InmatePhotoEventListener());
System.out.println("Later, when you've received the response from "
+ "the web service...");
InmateDataBean inmate = new InmateDataBean();
inmate.setIntKey(23);
handler.fireEvent(new InmatePhotoEventObject(handler), inmate);
}
}
The main method in this class shows you how you use a ListenerHandler. The rest of the methods in the class are standard. You would use your own EventObject and EventListener.
Yes.
I suggest you look at the java API documentation for ActionEvent and EventListenerList.
I also suggest that you read about the Listener (also called Observer) pattern.

J2ME key event handling

I have created a textfield that takes all characters from the user.. but i want to disable the space so that user cant enter space ...help??
pin = new TextField("Pin#","",4,TextField.PASSWORD);
If it's a PIN number then maybe you should replace the constraints parameter with TextField.NUMERIC | TextField.PASSWORD.
Implement the ItemStateListener interface. Then call this.setItemStateListener(this) in the Form constructor.
Implement the itemStateChanged method so that if the Item is the one you are interested in then get its content and test it if it contains spaces.
In my case I create a MIDlet and a Form which contains a TextField. And it works. I do not know why did you say that the solution I gave you did not work to you ! Here is a very simple example I give ( I created it and tested it ! ) :
package hello;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class HelloMIDlet extends MIDlet {
public Display display;
public HelloMIDlet() {
display = Display.getDisplay(this);
}
public void startApp() {
Form f = new F(display);
display.setCurrent(f);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
package hello;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.lcdui.TextField;
public class F extends Form implements ItemStateListener {
private TextField pin = new TextField("PIN :","",4,TextField.PASSWORD);
private Alert alert;
private Display disp;
public F(Display d)
{
super("");
disp = d;
this.setItemStateListener(this);
this.append(pin);
}
public void itemStateChanged(Item item) {
if (item == pin)
{
for (int i=0; i<pin.getString().length(); i++)
{
if (String.valueOf(pin.getString().charAt(i)).equals(new String(" ")))
displayAlert();
}
}
}
private void displayAlert()
{
alert = new Alert("Info","No space please !",null, AlertType.ERROR);
disp.setCurrent(alert, this);
}
}

Categories

Resources