I understand that Vaadin 8.1.0 will include a new LocalDateRenderer to work with Java 8's new date LocalDate but in the meantime I'm trying to setup my own custom LocalDateRenderer. I've got it mostly working in that it's all hooked up but based on the documentation I need to setup an AbstractRendererConnector but there's no such class...
The following code is all in my main UI class (for testing purposes):
private void setupGrid(Grid<Dog> grid)
{
grid.addColumn(dog -> dog.getBirthday(), new LocalDateRenderer()).setCaption("Birthday");
}
class LocalDateRenderer extends AbstractRenderer<Object, LocalDate>
{
public LocalDateRenderer()
{
super(LocalDate.class, "");
}
#Override
public JsonValue encode(LocalDate localDate)
{
return encode(DateTimeFormatter.ofPattern("MMM dd, YYYY").format(localDate), String.class);
}
}
I have confirmed that the LocalDateRenderer is called by adding logging statements, however on the grid no values are displayed. If I use the same code but instead of LocalDate I do it for a Long but instead of extends AbstractRenderer I extend NumberRenderer with my own code then it works.
This lead me to the documentation where I need to setup the Renderer with a AbstractRendererConnector but whenever I try to do this I get the compiler error saying that AbstractRendererConnector cannot be resolved to a type. And then of course I have a number of compiler errors (in the code below). My code for this (still in the main UI class) is:
#Connect(LocalDateRenderer.class)
class LocalDateRendererConnector extends AbstractRendererConnector<LocalDate>
{
#Override
public LocalDateRenderer getRenderer()
{
return (LocalDateRenderer) super.getRenderer();
}
}
Any assistance with how to get it linked up so that it displays my actual dates would be greatly appreciated. Thank you.
Also in the documentation it's not clear which class is which when they refer to TextRenderer since they use the same name to to be different things...
If your compiler can't resolve AbstractRendererConnector<T> to a type, you must be missing a dependency. If you are using Maven, you can add the following dependency, assuming that you have the vaadin-bom in your <dependencyManagement> section.
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-client</artifactId>
</dependency>
This artifact is not included by default in most of the Vaadin archtetypes.
Also be careful: there are two Renderer interfaces, one in com.vaadin.client.renderers and one in com.vaadin.ui.renderers. Your covariant return in LocalDateRendererConnector.getRenderer() won't work because AbstractRendererConnector<T> implements a different Renderer interface.
Related
I am working with AspectJ at the moment.
I seperated AspectJ code in a dependency.
Within that dependency everything works as intended.
But as soon as I import it in another project only some functionality does not work anymore.
When using the defaultImpl of #DeclareParents, the interface is shown within the compiled code but not the default Implementation.
Here is my code to show what I mean (every code snippet is its own File):
AspectJ code:
public interface IAspect
{
String hello();
}
public class IAspectDefaultImpl implements IAspect
{
#Override
public String hello()
{
return "hello";
}
}
#Aspect
public class AspectJ
{
#DeclareParents(value = "#SomeAnnotation*", defaultImpl = IAspectDefaultImpl.class)
private IAspect implementedInterface;
}
Target Class in a different project:
#SomeAnnotation
public class MyClass
{
private final int myValue;
public MyClass(final int wert)
{
this.myValue = wert;
}
public int getMyValue()
{
return myValue;
}
}
Maven throws me:
The type MyClass must implement the inherited abstract method IAspect.hello()
Which implies that it works partially.
When looking at the decompiled .class files the targeted Class does in fact implement IAspect.
The method defined in IAspectDefaultImpl is still missing tho.
My pom is set up like in this example.
I am not sure where I should start to look for errors.
Any help is apreciated.
Thanks for the MCVE. But hey, you don't use Git in order to commit 7z or ZIP archives, you ought to commit source code. I forked your project and fixed that, restructured and simplified your POMs and also fixed the main problem.
See my pull request and the commits in it for further details.
Concerning your problem, I can confirm that it occurs if you use #DeclareParents the way you do in an aspect library.
Actually, according to AspectJ maintainer Andy Clement there are certain problems with #DeclareParents when using it to provide parent interfaces + implementations in annotation style. The native AspectJ syntax via declare parents is not affected by that, but for annotation-style syntax Andy provided an alternative called #DeclareMixin, see the AspectJ manual. There he mentions that he is even considering to deprecate the defaultImpl argument of #DeclareParents in favour of #DeclareMixin.
So my bugfix (or workaround) for your problems is to actually replace
#DeclareParents(value = "#de.example.aspect.SomeAnnotation *", defaultImpl = IAspectDefaultImpl.class)
private IAspect implementedInterface;
by
#DeclareMixin("#de.example.aspect.SomeAnnotation *")
public static IAspect createIAspectImplementation() {
return new IAspectDefaultImpl();
}
This works with aspect libraries.
I will discuss with Andy about whether it makes sense to file a bug ticket for your problem or if he won't fix it anyway because there is a viable and recommended alternative.
I've come into a little problem with some legacy code from the 2016 control system. I'm trying to control the adis16448 board with this library
which compiled fine in the 2016 wpilibj, but doesn't compile in the 2017 version. Now, I'd like to get this up and running quickly without having to wait for the dev to update, and there are actually only two errors.
Relevant code here:
private static class InterruptSource extends DigitalSource {
public InterruptSource(int channel) {
initDigitalPort(channel, true);
}
}
First is that the InterruptSource class has some unimplemented methods from the parent class. I just added empty definitions for these and that error obviously went away. Next is that the method initDigitalPort is not defined from the parent class. This is the part that I get stuck on.
Upon examination of the API Javadoc, the Source Code on github, and the context of this code, I still can't seem to figure out what this does or how to fix it. I'm guessing this has been depreciated in the 2017 wpilibj library.
My question is, what is the replacement method for initDigitalPort?
Forgive me for anything simple I've overlooked, we are a new FRC team so we have 0 experience with using wpilibj.
Also, it might help if I understood what the DigitalSource class actually does, it seems to involve encoders but that can't be right since this board has none. Could someone explain this to me?
Thanks, help is greatly apreciated!
The library in question has now been updated as of this commit. The new class is called DigitalInput and the initDigitalPort method is called in the constructor of this class which is given the parameter for the port.
Ex:
public InterruptSource(int channel) {
initDigitalPort(channel, true);
}
can be subsituted with
DigitalInput m_interrupt = new DigitalInput(10)
and will provide nearly the same functionality including class structure and methods.
private static class InterruptSource extends DigitalInput {
public InterruptSource(int channel) {
super(channel);
}
}
I have cloned a maven project on a new machine but I am having some problems with some of the dependencies as they don't seem to have been loaded.
One such case, is fj.Effect of Functional java. I am not sure if I am (manually) adding the right library.
In the code, I have:
private Effect<EventDBEvent> downloadEvent = new Effect<EventDBEvent>() {
#Override
public void e(EventDBEvent eventDBEvent) {
...
}
};
I have tried adding org.org.functionaljava:functionaljava-java8:4.32 and org.functionaljava:functionaljava:4.3 IntelliJ recognizes Effect but highlights the first line as error and says:
I have a similar issue in another line:
final ... = new ...(new Effect<Option<Integer>>() {
#Override
public void e(Option<Integer> integerOption) {
}
}, ...);
Type fj.Effect does not have type parameters.
Am I importing the wrong packages?
More generally, is there a way of knowing which packages I should use, based on an existing code?
The Effect class changed so that the arity is in the class name, e.g. Effect0, Effect1, etc., where the arity indicates the number of parameters to the method. You want to use the Effect1 class.
I am building an Android app. Now, I have a source code for API #1, I should get it adapted for API #2. Then I will publish the both versions for API #1 and API #2 in different packages. I can't use something like values-en, because both versions can be used worldwide. Also, the user may not have choice.
As the new version will use same UI and DB logic, (and because now the code is erroneous,) I don't want to separate the code. If i were coding in c or c++, I must use #ifdef and Makefile. However, I'm in Java. It's possible to run the API-dependent code by determining the package name in runtime, but it's somewhat weird.
I think I can use annotations. What I expect is:
package foo.app;
public class API {
public boolean prepare() { ... }
#TargetPlatform(1)
public void open() { ... }
#TargetPlatform(2)
public void open() { ... }
}
and use only one of them. Also, this is good:
package foo.app;
public class R {
#TargetPlatform(1) com.example.foo.app.R R;
#TargetPlatform(2) net.example.foo.app.R R;
}
Just defining an annotation is simple. What I don't know is, how can I exclude unused duplicates from build or execution, or so on? If the work can be done in this way, I can do anything.
You cannot use annotations for that.
It would be better to hide the implementation specific classes behind an interface.
public interface Api {
boolean prepare();
void open();
}
To create a Api instance use a factory class:
public class ApiFactory {
public static Api createApi() {
if(isTargetPlatform1())
return new com.example.foo.app.Api();
else
return new net.example.foo.app.Api();
}
private boolean isTargetPlatform1() {
// determine the current platform, e.g. by reading a configuration file
}
}
In all other places you only refer to the Api interface and ApiFactory class.
Use it like that:
Api api = ApiFactory.createApi();
api.open();
// ...
A more advanced solution would be to use dependency injection.
I am developing an Eclipse plug-in that shows custom multi-line markers in Eclipse's own AbstractTextEditor.
Here is what I have so far:
a custom marker with the super type "org.eclipse.core.resources.textmarker"
an annotationType (org.eclipse.ui.editors.annotationTypes)
a markerAnnotationSpecification (org.eclipse.ui.editors.markerAnnotationSpecification)
This is all working well, my markers show up in the editor. But I need to customize the way they are drawn on the VerticalRuler, so they do not only show up as an icon, but as a vertical line spanning the affected source lines.
I know, that this can be done with Annotations by implementing IAnnotationPresentation and overwriting paint().
But how can I do this for markers?
Edit: Here is a screenshot of what I am trying to achieve:
I solved this by contributing a RulerColumn (extension point org.eclipse.ui.workbench.texteditor.rulerColumns) and configuring markerAnnotationSpecification to not include verticalRulerPreferenceKey and verticalRulerPreferenceValue (so it will not be shown on the default AnnotationRulerColumn).
In case someone also finds the documentation on how to best implement IContributedRulerColumn a bit sparse: it seems the way to go is to subclass AbstractContributedRulerColumn and have the methods delegate to a subclass of AbstractRulerColumn.
For example:
public class MyRulerColumn extends AbstractContributedRulerColumn {
private IVerticalRulerColumn delegate = new AbstractRulerColumn() { … }
public void setModel(IAnnotationModel model) {
delegate.setModel(model);
}
…
}
Customizing the appearance is then as easy as overwriting one of the paint… methods in the delegate.