Eclipse GEF - Snap to Grid not working - eclipse-rcp

I am trying to use the "Snap to Grid" function for a GEF viewer. I am following the tutorial at this site. The tutorial essentially talks about installing necessary edit policies and overriding the getAdapter method like below:
#Override
public Object getAdapter(Class key) {
System.out.println("snapping..." + key);
if (key == SnapToHelper.class) {
List<SnapToHelper> helpers = new ArrayList<SnapToHelper>();
if (Boolean.TRUE.equals(getViewer().getProperty(
SnapToGeometry.PROPERTY_SNAP_ENABLED))) {
helpers.add(new SnapToGeometry(this));
}
if (Boolean.TRUE.equals(getViewer().getProperty(
SnapToGrid.PROPERTY_GRID_ENABLED))) {
helpers.add(new SnapToGrid(this));
}
if (helpers.size() == 0) {
return null;
} else {
return new CompoundSnapToHelper(
helpers.toArray(new SnapToHelper[0]));
}
}
return super.getAdapter(key);
}
However during runtime, the getAdapter method is never called with a SnapToHelper instance which I confirmed by putting a println method.
am I missing something?

After some research, I learnt that I had made a trivial mistake which took me several days to figure out. The code snippet of createFigure method for a typical TopEditPart is as follows:
protected IFigure createFigure() {
Figure f = new FreeformLayer();
f.setLayoutManager(new FreeformLayout());
f.setBorder(new MarginBorder(1));
// Create a layout for the graphical screen
f.setOpaque(true);
helpers = new ArrayList<SnapToHelper>();
helpers.add(new SnapToGrid(this));
CompoundSnapToHelper h = new CompoundSnapToHelper(
helpers.toArray(new SnapToHelper[0]));
return f;
}
In the above method, using f.setOpaque(true); had hidden the grid all this while and had cost me several days to figure out. I have now changed it to f.setOpaque(false); and now I am able to see the grid. Hope many could save time because of this answer.

Related

Proper way to implement custom Css attribute with Itext and html2Pdf

I'm using Itext 7 and their html2Pdf lib.
Is there a way to implement for example cmyk colors.
.wootWorkingCMYK-color{
color: cmyk( 1 , 0.69 , 0.08 , 0.54);
}
I know the itext core part pretty good, looking for away to use the html2Pdf side. I'm aware of the CssApplierFactory but this seems to be to far up the chain.
Well, of course there is a way of processing custom CSS properties like cmyk colors, but unfortunately the code would be quite bulky and you will need to write quite some code for different cases. I will show how to apply custom color for font, but e.g. for backgrounds, borders or other cases you will need to write separate code in a similar way. Reason behind it is that iText layout structure, although designed with HTML/CSS in mind, is not 100% similar and has some differences you have to code around.
Having that said, if you can fork, build and use your custom version from sources, this is the way I would advice to go. Although it has drawbacks like having to rebase to get updates, the solution would be simpler and more generic. To do that, search for usages of CssUtils.parseRgbaColor in pdfHTML module, and you will find that it is used in BackgroundApplierUtil, BorderStyleApplierUtil, FontStyleApplierUtil, OutlineApplierUtil. There you will find code like
if (!CssConstants.TRANSPARENT.equals(cssColorPropValue)) {
float[] rgbaColor = CssUtils.parseRgbaColor(cssColorPropValue);
Color color = new DeviceRgb(rgbaColor[0], rgbaColor[1], rgbaColor[2]);
float opacity = rgbaColor[3];
transparentColor = new TransparentColor(color, opacity);
} else {
transparentColor = new TransparentColor(ColorConstants.BLACK, 0f);
}
Which I belive you can tweak to process cmyk as well, knowing that you know core part pretty well.
Now, the solution without custom pdfHTML version is to indeed start with implementing ICssApplierFactory, or subclassing default implementation DefaultCssApplierFactory. We are mostly interested in customizing implementation of SpanTagCssApplier and BlockCssApplier, but you can consult with DefaultTagCssApplierMapping to get the full list of appliers and cases they are used in, so that you can decide which of them you want to process in your code.
I will show you how to add support for custom color space for font color in the two main applier classes I mentioned and you can work from there.
private static class CustomCssApplierFactory implements ICssApplierFactory {
private static final ICssApplierFactory DEFAULT_FACTORY = new DefaultCssApplierFactory();
#Override
public ICssApplier getCssApplier(IElementNode tag) {
ICssApplier defaultApplier = DEFAULT_FACTORY.getCssApplier(tag);
if (defaultApplier instanceof SpanTagCssApplier) {
return new CustomSpanTagCssApplier();
} else if (defaultApplier instanceof BlockCssApplier) {
return new CustomBlockCssApplier();
} else {
return defaultApplier;
}
}
}
private static class CustomSpanTagCssApplier extends SpanTagCssApplier {
#Override
protected void applyChildElementStyles(IPropertyContainer element, Map<String, String> css, ProcessorContext context, IStylesContainer stylesContainer) {
super.applyChildElementStyles(element, css, context, stylesContainer);
String color = css.get("color2");
if (color != null) {
color = color.trim();
if (color.startsWith("cmyk")) {
element.setProperty(Property.FONT_COLOR, new TransparentColor(parseCmykColor(color)));
}
}
}
}
private static class CustomBlockCssApplier extends BlockCssApplier {
#Override
public void apply(ProcessorContext context, IStylesContainer stylesContainer, ITagWorker tagWorker) {
super.apply(context, stylesContainer, tagWorker);
IPropertyContainer container = tagWorker.getElementResult();
if (container != null) {
String color = stylesContainer.getStyles().get("color2");
if (color != null) {
color = color.trim();
if (color.startsWith("cmyk")) {
container.setProperty(Property.FONT_COLOR, new TransparentColor(parseCmykColor(color)));
}
}
}
}
}
// You might want a safer implementation with better handling of corner cases
private static DeviceCmyk parseCmykColor(String color) {
final String delim = "cmyk(), \t\r\n\f";
StringTokenizer tok = new StringTokenizer(color, delim);
float[] res = new float[]{0, 0, 0, 0};
for (int k = 0; k < 3; ++k) {
if (tok.hasMoreTokens()) {
res[k] = Float.parseFloat(tok.nextToken());
}
}
return new DeviceCmyk(res[0], res[1], res[2], res[3]);
}
Having that custom code, you should configure the ConverterProperties accordingly and pass it to HtmlConverter:
ConverterProperties properties = new ConverterProperties();
properties.setCssApplierFactory(new CustomCssApplierFactory());
HtmlConverter.convertToPdf(..., properties);
You might have noticed that I used color2 instead of color, and this is for a reason. pdfHTML has a mechanism of CSS property validation (as browsers do as well), to discard invalid CSS properties when calculating effective properties for an element. Unfortunately, there is no mechanism of customizing this validation logic currently and of course it treats cmyk colors as invalid declarations at the moment. Thus, if you really want to have custom color property, you will have to preprocess your HTML and replace declarations like color: cmyk... to color2: cmyk.. or whatever the property name you might want to use.
As I mentioned at the start of the answer, my recommendation is to build your own custom version :)

Preloader in Wicket Application

In a wicket application on search event it takes few secons and sometimes minutes to show the result as its a long data . I want to show a preloader while the data is fetched from the database to let the user know something is going on when they click search . I am very new to wicket application , dont understands the things very deeply but I find AjaxLazyPreloader but as I said I want to show the preloader when the search method is called ...I am sharing the SearchSubmit method ...
private void processSearchSubmit(AjaxRequestTarget ajaxRequestTarget) {
ajaxRequestTarget.add(tableHolder);
ajaxRequestTarget.add(productTableHolder);
if (zipcode == null) {
ajaxRequestTarget
.appendJavaScript("$().toastmessage('showWarningToast','Please enter a zipcode')");
} else if (!ZipCodeValidator.isValid(zipcode)) {
useZones = true;
currentZone = zipcode;
ajaxRequestTarget.add(tableHolder);
if (searchProduct != null) {
ajaxRequestTarget.add(productTableHolder);
if (lstProduct.getList().size() == 0) {
ajaxRequestTarget
.appendJavaScript("$().toastmessage('showErrorToast','Sorry! This product is not avialable .')");
}
}
} else if (lstMerchants.getList().size() == 0) {
ajaxRequestTarget
.appendJavaScript("$().toastmessage('showWarningToast','Sorry! There are currently no services')");
}
if (ZipCodeValidator.isValid(zipcode)) {
ajaxRequestTarget.add(tableHolder);
if (searchProduct != null && !searchProduct.equals("")) {
ajaxRequestTarget.add(productTableHolder);
if (lstProduct.getList().size() == 0) {
ajaxRequestTarget
.appendJavaScript("$().toastmessage('showErrorToast','Sorry! This product is not avialable in this zip code or zone.')");
}
}
}
}
I want when this method is called till the times it fetch the result data , it should show a preloader or spinner . Can anybody suggest how to do that .??
If you need to call long execution method by clicking button check this answer.
You can also use AjaxLazyLoadPanel, check this demo (it's Java part and html part)
Either use an AjaxLazyLoadPanel or an IndicatingAjaxLink/-Button. Both will work fine in either normal or Ajax calls.
To use an AjaxLazyLoadPanel: create a subclass of AjaxLazyLoadPanel which loads the panel you want to display and add it to the AjaxRequest.
IndicatingAjaxLinks just display a spinner while the request is being processed and can be used straightforward in your current application. Use this instead of the button/link you use for formsubmits now.

How can I predict which Wicket components will have their tags rendered in the final page?

For some Wicket components, if I call setOutputMarkupId(true) they warn when they are rendered.
Markup id set on a component that is usually not rendered into markup.
I'd like to output an id for every component that will actually end up in the HTML in order that I can find them with XPath for testing. How can I predict from class or properties of a Component whether it is sensible to setOutputMarkupId(true)?
More detail - in my Application I'm overriding
protected void init() {
super.init();
addComponentInstantiationListener(new IComponentInstantiationListener() {
public void onInstantiation(Component component) {
if (!(component instanceof WebMarkupContainer)) return;
if (component instanceof WebMarkupContainerWithAssociatedMarkup) return;
if (component instanceof Border.BorderBodyContainer) return;
WebMarkupContainer container = (WebMarkupContainer) component;
if (container.isTransparentResolver()) return;
component.setOutputMarkupId(true);
}});
For a sample of pages, this arbitrary gubbins does the trick, but it does seem pretty arbitrary!
Repeater components like DataView and ListView don't have their own markup, but repeat the markup with Items. You can check if the component is instanceof RepeatingView.
This problem is easily shown by the following, wrong, example:
ListView<Person> people = new ListView<Person>("people", list) {
protected void onPopulateItem(ListItem<Person> item) {
add(new Label("name", item.getModelObject().getName()));
}
}
Here we don't add the label to the list item, but rather the listview. And that fails. The code should've been:
ListView<Person> people = new ListView<Person>("people", list) {
protected void onPopulateItem(ListItem<Person> item) {
item.add(new Label("name", item.getModelObject().getName()));
}
}
Also ignore auto-components (Component.isAuto()).
Such components are for example: <wicket:container>, <wicket:enclosure>, etc.
This is just an idea. I didn't try this ans can't right now...
You could find the components, that will propably be rendered by checking if the are tied to a WicketTag (which are not rendered or at least which are the ones causing this message).
This can be done like this:
boolean isGoingToBeRendered (Component component) {
MarkupStream stream = new MarkupStream(component.getMarkup());
ComponentTag tag = stream.getTag();
return (!tag instanceof WicketTag);
}
Again: This is no tried solution, just some lines of code hacked into this editor. It's indended as a pointer not as a ready to use piece of code.

HierarchicalDataBoundControl.PerformDataBinding not being called on postback

I am binding to a SiteMapDataSource (hierarchical).
I am overriding PerformDataBinding to grab the data from the datasource.
Everything works great on page load. But when I perform a postback anywhere on the page, the PerformDataBinding method does not get called, and in effect, not rendering any menu items (PerformDataBinding wasn't called).
No clue why this is happening, but I have a fix for it. Amazingly, every example of a HierarchicalDataBoundControl I could find (even from msdn) was doing this. However, here is a workaround.
private bool dataBound = false;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (this.Page.IsPostBack)
{
this.DataBound += delegate { dataBound = true; };
this.Page.Load += delegate { if (!dataBound) DataBind(); };
}
}

Using the Selection service on something that is *not* a JFace view

I am building an image Editor as an Eclipse plugin.
I would like to use the Properties view to view & edit properties of the model underneath the image. Accordingly I am calling ..
getSite().setSelectionProvider( this );
.. within createPartControl, and implementing the ISelectionProvider interface in my EditorPart implementation, so that the model is returned as the selection (which must therefore implement the ISelection interface).
The next step is for the Editor to implement IAdaptable to supply an adapter for the selected object.
My problem however is that getAdapter is never called with IPropertySource.class, and therefore the Properties View never gets what it needs to make sense of the image model.
Your help is much appreciated.
M.
The answer in the end broke down into a few pieces ...
1.) When your selection does change (if a user has zoomed into the image, for example) be sure to tell Eclipse this. It won't happen otherwise.
2.) When sending your SelectionChangedEvent, wrap up your IAdaptable in a StructuredSelection object - otherwise the Properties view will ignore it.
This boiled down to the following method
public void fireSelectionChanged()
{
final SelectionChangedEvent event = new SelectionChangedEvent( this, new StructuredSelection( this ) );
Object[] listeners = selectionChangedListeners.getListeners();
for (int i = 0; i < listeners.length; ++i)
{
final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
SafeRunnable.run(new SafeRunnable() {
public void run() {
l.selectionChanged( event );
}
});
}
}
... on an class that implemented ISelectionProvider & IAdaptable.
M.