Javafx: Can't import custom control into Scene Builder - eclipse

I tried to import my gui control (jar file) into the scene builder but without success. The file was created using eclipse export -> jar. When it was selected in scene builder "import JAR/FXML File", there was nothing inside the Import Dialog.
My control is a TextField with TextFormatter:
import java.text.NumberFormat;
import java.text.ParseException;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.util.StringConverter;
public class CustomTextField extends TextField {
public CustomTextField() {
setText("Custom");
NumberTextFormatter formatter = new NumberTextFormatter(new StringConverter<Number>() {
#Override
public String toString(Number object) {
return object.toString();
}
#Override
public Number fromString(String string) {
try {
return NumberFormat.getInstance().parse(string);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
});
setTextFormatter(formatter);
}
public static class NumberTextFormatter extends TextFormatter<Number> {
public NumberTextFormatter(StringConverter<Number> valueConverter) {
super(valueConverter);
}
}
}
I am sure that the culprit is the usage of TextFormatter. Because the control will works (appear in Import Dialog) if I removed the TextFormatter from the codes.
Whats wrong?
Update: Even if I simplified my constructor to exclude setTextFormatter(), as long as it still have a line of TextFormatter declaration the problem still persist. Such as:
public CustomTextField() {
setText("Custom");
TextFormatter<Integer> formatter = new TextFormatter<Integer>(new IntegerStringConverter());
}

Found the solution. The oracle scene builder 2.0 is too old/ too dumb to work with TextFormatter. Need to upgrade to Gluon scene builder 8.5.0.

Related

Costum Event Handling

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?

Eclipse Plug-in Development: DefaultInformationControl Does'nt work as expected

I am writing eclipse plugin that using the texthover and override it for my own text.
I need to add an action to the hover window so I used the following function:
public IInformationControlCreator getHoverControlCreator()
This is my code:
#Override
public IInformationControlCreator getHoverControlCreator() {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
Shell s=new Shell(parent,SWT.V_SCROLL | SWT.H_SCROLL);
ToolBarManager tbm = new ToolBarManager(SWT.FLAT);
NoFocusDic dic = new NoFocusDic(parent, tbm);
dic.setBackgroundColor(new Color(null,123,234,12));
ButtonAction ba=new ButtonAction();
tbm.add(ba);
tbm.update(true);
dic.setSize(300,100);
dic.setLocation(new Point(500,500));
// dic.setInformation("abc");
dic.setVisible(true);
return dic;
}
};
}
When I run this code with the setInformation line I get this window:
And when I run it without the setInformation line I get this window:
So The window I want to always get is the second one, but with text inside.
I read in eclipse site that the setVisible won't work if I try to catch the focus, but I don't think that setInformation is catching focus.
Any Ideas what to do?
package TextHoverPackage;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IInformationControlExtension2;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Shell;
public class NoFocusDic extends DefaultInformationControl implements IInformationControlExtension2 {
public NoFocusDic(Shell parent, ToolBarManager toolBarManager) {
super(parent, toolBarManager);
}
public NoFocusDic(Shell parent, ToolBarManager toolBarManager, IInformationPresenter a){
super(parent, toolBarManager,a);
}
#Override
public void setInput(Object arg0) {
super.setInformation(arg0.toString());
}
}
DefaultInformationControl.setInformation adjusts the size of the window to fix the text that you give it. However it only does this if an IInformationPresenter has been defined.
So one option is to specify null for the IInformationPresenter in your constructor:
public NoFocusDic(Shell parent, ToolBarManager toolBarManager) {
super(parent, toolBarManager, null);
}

Getting user data in NewProjectCreationPage in Eclipse Plugin

I have been successful in making a plugin. However now i need that on project creation page i add some more textboxes to get the user information. Also i need to use this information to add into the auto generated .php files made in project directory.
I want to know how can i override the WizardNewProjectCreationPage to add some more textboxes to the already given layout. I am pretty new to plugin development. Here is the code for my custom wizard.
import java.net.URI;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
import rudraxplugin.pages.MyPageOne;
import rudraxplugin.projects.RudraxSupport;
public class CustomProjectNewWizard extends Wizard implements INewWizard, IExecutableExtension {
private WizardNewProjectCreationPage _pageOne;
protected MyPageOne one;
private IConfigurationElement _configurationElement;
public CustomProjectNewWizard() {
// TODO Auto-generated constructor stub
setWindowTitle("RudraX");
}
#Override
public void init(IWorkbench workbench, IStructuredSelection selection) {
// TODO Auto-generated method stub
}
#Override
public void addPages() {
super.addPages();
_pageOne = new WizardNewProjectCreationPage("From Scratch Project Wizard");
_pageOne.setTitle("From Scratch Project");
_pageOne.setDescription("Create something from scratch.");
addPage(one);
addPage(_pageOne);
}
#Override
public boolean performFinish() {
String name = _pageOne.getProjectName();
URI location = null;
if (!_pageOne.useDefaults()) {
location = _pageOne.getLocationURI();
System.err.println("location: " + location.toString()); //$NON-NLS-1$
} // else location == null
RudraxSupport.createProject(name, location);
// Add this
BasicNewProjectResourceWizard.updatePerspective(_configurationElement);
return true;
}
#Override
public void setInitializationData(IConfigurationElement config,
String propertyName, Object data) throws CoreException {
_configurationElement = config;
// TODO Auto-generated method stub
}
}
Ask for any other code required. Any help is appreciated. Thank You.
Instead of using WizardNewProjectCreationPage directly create a new class extending WizardNewProjectCreationPage and override the createControl method to create new controls:
class MyNewProjectCreationPage extends WizardNewProjectCreationPage
{
#Override
public void createControl(Composite parent)
{
super.createControl(parent);
Composite body = (Composite)getControl();
... create new controls here
}
}

Eclipse 4 RCP - application does not have active window

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?

Jenkins Plugin. RootAction. index.jelly in seperate window

i am writing a simple plugin and am forced to create a RootAction which displays a page (the index.jelly) and needs some additional values to confirm and then execute the methode.
My problem is, that the index.jelly file gets always displayed on a blank window.
But i do need it to be included inside of the Jenkinstemplate in the main table, as usual.
Can't seem to figure out why this is happening.
Any ideas?
RestartJksLink.java
package org.jenkinsci.plugins.tomcat_app_restart;
import hudson.Extension;
import hudson.model.ManagementLink;
/**
*
*
* #author [...]
*/
#Extension
public class RestartJksLink extends ManagementLink {
#Override
public String getIconFileName() {
return "/plugin/tomcat-app-restart/images/restart.png";
}
#Override
public String getUrlName() {
return "jksrestart";
}
#Override
public String getDescription() {
return "Restart your Jenkins-Application on Tomcat";
}
public String getDisplayName() {
return "Restart Jenkins-App on Tomcat";
}
}
RestartJksRootAction.java
package org.jenkinsci.plugins.tomcat_app_restart;
import java.io.IOException;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import jenkins.model.Jenkins;
import hudson.Extension;
import hudson.model.RootAction;
import hudson.util.FormValidation;
#Extension
public class RestartJksRootAction implements RootAction {
public String getDisplayName() {
return "Restart Jenkins on Tomcat";
}
public String getIconFileName() {
if (!Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER)) {
return null;
}
if (!Jenkins.getInstance().getLifecycle().canRestart()) {
return null;
}
return "/plugin/tomcat-app-restart/images/restart.png";
}
public String getUrlName() {
return "jksrestart";
}
public FormValidation doJksRestart() {
Authenticator.setDefault (new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("admin", "admin".toCharArray());
}
});
URL url;
try {
url = new URL("http://localhost:8888/manager/text/start?path=/jenkins");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
System.out.println("" + connection.getResponseMessage());
return FormValidation.ok("Success");
} catch (IOException e) {
return FormValidation.error("Client error: " + e.getMessage());
}
}
}
index.jelly inside: resources.org.jenkinsci.plugins.tomcat_app_restart.RestartJksRootAction
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
<f:validateButton
title="${%Restart Jenkins}" progress="${%Restarting...}"
method="JksRestart" with="" />
</j:jelly>
Thank you guys!
I am new to jenkins plugin development, this would help me a lot to understand.
Kind regards.
this demo (rootaction-example-plugin) helped a lot.You can read it.
https://github.com/gustavohenrique/jenkins-plugins/tree/master/rootaction-example-plugin
Add the <l:main-panel> tag and the the <l:layout norefresh="true">tag to the index.jelly file.
And include the side panel:
Pass the the build to Action (through a parameter of the constructor)
The build can be retrieved out of the parameters of the perform method which is inherited from the BuildStepCompatibilityLayer class (by Extending Publisher).
Create a getBuild() method in the Action class
Add the <st:include it="${it.build}" page="sidepanel.jelly" /> tag with the build
Jelly Example (index.jelly):
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
<l:layout norefresh="true">
<st:include it="${it.build}" page="sidepanel.jelly" />
<l:main-panel>
<f:validateButton title="${%Restart Jenkins}" progress="${%Restarting...}" method="JksRestart" with="" />
</l:main-panel>
</l:layout>
</j:jelly>
Java Action class example:
package tryPublisher.tryPublisher;
import hudson.model.Action;
import hudson.model.AbstractBuild;
public class ExampleAction implements Action {
AbstractBuild<?,?> build;
public ExampleAction(AbstractBuild<?,?> build) {
this.build = build;
}
#Override
public String getIconFileName() {
return "/plugin/action.png";
}
#Override
public String getDisplayName() {
return "ExampleAction";
}
#Override
public String getUrlName() {
return "ExampleActionUrl";
}
public AbstractBuild<?,?> getBuild() {
return this.build;
}
}
Java Publisher class example:
package tryPublisher.tryPublisher;
import java.io.IOException;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
public class ExamplePublisher extends Publisher {
#Override
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
}
#Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException, IOException {
build.getActions().add(new ExampleAction(build));
return true;
}
}
The .jelly file has to be in the right resources map of the plugin project. In a map with the same name as the name of the Java class implementing Action. The name of the .jelly is important also.