In my prefuse visualization I want to add label to edges. I followed some examples proposed here on SO, but I can't bring it to work:
I use this Renderer for my edges:
private class CustomEdgeRenderer extends LabelRenderer {
private EdgeRenderer edgeRenderer = new EdgeRenderer();
#Override
public String getText(VisualItem item) {
System.out.println("edgerenderer");
return "test";
}
#Override
public void render(Graphics2D g, VisualItem item) {
edgeRenderer.render(g, item);
item.setTextColor(BLACK);
}
}
The problem now is, that the text isn't displayed, but the edges are drawn in a weird form. That is they aren't correctly drawn. If I don't overwrite render, then the text is drawn, but no edges. How can i make this work?
Following the architecture of prefuse you would create a separate group of visual items for the labels, so called DecoratorItem.
An example can be found in the TreeMap demo:
https://github.com/prefuse/Prefuse/blob/master/demos/prefuse/demos/TreeMap.java
Another more ad-hoc solution:
Extend EdgeRenderer.
Take care of drawing the label in the render method.
Call super.render to let prefuse draw the edge.
You could check this question:
Displaying edges labels in prefuse (java) graphs
Google send me here and the previous questions, and looking for some code, I recently found the following version and runs ok.
http://netgrok.googlecode.com/svn-history/r2/trunk/src/test/AggregateDecoratorDemo.java
Regards.
Related
I want to add a route fence within the jxmap is it possible? like the picture above, with the feature of directly drawing a polyline in the map
Current version of JxMaps doesn't implement drawing tools.(https://developers.google.com/maps/documentation/javascript/examples/drawing-tools). This functionality will be included to one of next JxMaps releases.
But you can implement own logic using map events and polylines. For example you can add mouse click handler to the Map instance:
LatLng[] path = new LatLng[count];
map.addEventListener("click", new MapMouseEvent() {
#Override
public void onEvent(MouseEvent mouseEvent) {
path[current] = mouseEvent.latLng();
}
});
Using this handler you can collect positions and then write polyline with them:
Polyline polyline = new Polyline(map);
polyline.setPath(path);
We have been able to add a PdfFormField at a specific location on the page using the following Scala code snippet.
val form = PdfAcroForm.getAcroForm(document.getPdfDocument(), true)
val nameField = PdfFormField.createText(document.getPdfDocument(), new Rectangle(data.x, data.y, data.width, data.height), data.formName, data.formText)
form.addField(nameField)
However, what we would like to be able to do is add it after the last Paragraph on the page that we inserted. (i.e. This field just comes directly after). Is there a way that we can derive the proper rectangle, or is there an easier way?
Thanks
There is currently no out-of-the-box way to add fields to layout, but iText team is considering implementing this functionality.
Meanwhile, there are easy ways to achieve your goal, and there are a few of them.
My examples will be in Java, but I assume you will easily be able to use them in Scala.
The first approach is just to get the bottom position of the paragraph you have added and add your field with respect to that position. The bottom position of the last paragraph happens to be the top position of the rest of available box of content on the page (area), which converts to the following code:
Document doc = new Document(pdfDoc);
doc.add(new Paragraph("This is a paragraph.\nForm field will be inserted after it"));
Rectangle freeBBox = doc.getRenderer().getCurrentArea().getBBox();
float top = freeBBox.getTop();
float fieldHeight = 20;
PdfTextFormField field = PdfFormField.createText(pdfDoc,
new Rectangle(freeBBox.getLeft(), top - fieldHeight, 100, fieldHeight), "myField", "Value");
form.addField(field);
The part you are interested in is
Rectangle freeBBox = doc.getRenderer().getCurrentArea().getBBox();
which gives you the rectangle where the content is not placed yet.
Note, however, that this approach will not affect the following paragraphs after you the one after which you want to add the form field, which means this form field and the content might overlap.
Do deal with this situation, you might want to take advantage of possibility to create custom layout elements in iText7.
Which, in turn, is converted to the following code:
private static class TextFieldRenderer extends DivRenderer {
public TextFieldRenderer(TextFieldLayoutElement modelElement) {
super(modelElement);
}
#Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
PdfAcroForm form = PdfAcroForm.getAcroForm(drawContext.getDocument(), true);
PdfTextFormField field = PdfFormField.createText(drawContext.getDocument(),
occupiedArea.getBBox(), "myField2", "Another Value");
form.addField(field);
}
}
private static class TextFieldLayoutElement extends Div {
#Override
public IRenderer getRenderer() {
return new TextFieldRenderer(this);
}
}
Then you will just need to add the elements in a fancy way:
doc.add(new Paragraph("This is another paragraph.\nForm field will be inserted right after it."));
doc.add(new TextFieldLayoutElement().setWidth(100).setHeight(20));
doc.add(new Paragraph("This paragraph follows the form field"));
In short, what we have done here is that we created a custom dummy Div element (which is an analogue of HTML's div), which will occupy area during laying out, but we defined custom #draw() operator for this element so that form field is inserted right when we know the exact position where we want to do it.
You can find the complete code of the sample here. Note, however, that the link may change as samples repository is under reorganization now.
I am using a CellTable to display results of a query and I need these results to be shown as (html) links. I would like to react to a click on these links. So far, I had implemented it like this:
// ClickHandler on CellTable
cellTable.addCellPreviewHandler(new Handler<OperationalItemMultipleSearchRowData>() {
#Override
public void onCellPreview(CellPreviewEvent<OperationalItemMultipleSearchRowData> event) {
boolean isClick = "click".equals(event.getNativeEvent().getType());
if (isClick)
AdminUtils.EVENT_BUS.fireEvent(new SimpleSearchEvent(event.getValue().getName()));
}
});
The Problem is that this reacted to a Click on the whole row instead of the link. Due to architectural restrictions, the link itself is not a real html link, but a SafeHtml link that leads nowhere. I just needed the look&feel of a Link:
Column<OperationalItemMultipleSearchRowData, SafeHtml> nameColumn = new Column<OperationalItemMultipleSearchRowData, SafeHtml>(new SafeHtmlCell()) {
#Override
public SafeHtml getValue(final OperationalItemMultipleSearchRowData object) {
return new SafeHtml() {
#Override
public String asString() {
return "" + object.getName() + "";
}
};
}
};
How can I react to a click on this link only ? (instead of the whoel row)
Is there a more elegant way to implement this ?
Cheers
As with any other use of event delegation, the basic idea is to find walk up the hierarchy starting from the target of the event up until you find the link element you're looking for, or some other element that signals the search is over and the click was targetted outside the link (e.g. you reached the cell, the row or the table).
That being said, I think you should merge your behavior inside a specific Cell implementation rather than using a CellPreviewHandler (copy/paste the ActionCell or TextButtonCell as a starting point).
As a side note, I also believe you should not use a link when you're not actually linking anywhere, or try to provide a target for the link if the behavior is the one of a link (that way, right-clicking, middle-clicking or ctrl-clicking will Just Work™). If you want the look of a link (without the "feel"), then just use an ActionCell or TextButtonCell and style it accordingly.
I tried following code for draw a single line horizontal line but it is not working. i am not getting what is the problem.
HorizontalFieldManager horline = new HorizontalFieldManager()
{
protected void paint(Graphics graphics)
{
super.paint(graphics);
graphics.setColor(Color.RED);
graphics.drawLine(5, 21,10, 20);
}
};
There's at least a couple problems here:
Extent
The extent of a field (or manager) is basically the size of that field on screen. This size is normally set by a Field object in its layout() method, or by a Manager object in its sublayout() method. The problem is that your HorizontalFieldManager does not override these methods to set the size (by calling setExtent()), and it doesn't look like you add any fields to the manager. So, I believe your horline manager object simply has a size of {0, 0}. Drawing outside its extent doesn't do anything.
Manager vs Field
Manager classes are containers for fields. In this case, all you have is a line. I would definitely not use a Manager (including HorizontalFieldManager) for this, since you're not putting any fields into it, and there is overhead to adding Manager objects. Use a lighter-weight Field, or maybe even modify the paint() or paintBackground() method on whatever class contains this code ... you don't show us that, so I can't say for sure.
If you want to represent the line with a Field, then this will work:
Field line = new Field() {
protected void layout(int width, int height) {
setExtent(20, 21);
}
protected void paint(Graphics g) {
int oldColor = g.getColor();
g.setColor(Color.RED);
g.drawLine(5, 21,10, 20);
g.setColor(oldColor);
}
};
add(line);
Note that I am setting the extent to width=20, height=21, because those are the maximum coordinates you pass to drawLine(). Also, because your y values are 20 and 21, this isn't actually a truly horizontal line.
add()
This might have simply been left out of the code you show to keep the question short, but whether you use a Manager or a Field, you do need to remember to call add() for your field/manager object. Objects created, but not added to a screen, will never show. In your case, the setExtent() problem would also have caused this problem.
Update:
As Dinesh shows in his answer, you could also solve the problem by using SeparatorField. However, I believe that only gives you purely horizontal/vertical lines. Because of the coordinates in your code, I wasn't sure if you needed the ability to draw lines of any orientation ... if you do, then overriding paint() is necessary. If not, use SeparatorField ... but hopefully, you learned something from this answer, too :).
Use this
HorizontalFieldManager horline = new HorizontalFieldManager()
{
protected void paint(Graphics graphics)
{
super.paint(graphics);
graphics.setColor(Color.RED);
}
};
horline.add(new SeparatorField(SeparatorField.LINE_HORIZONTAL|SeparatorField.VISUAL_STATE_FOCUS));
I am developing a new custom control in VisualStudio and wonder whether you can limit the property selection at design time.
To illustrate the problem, there are two properties that rely on each other – orientation and textside. The control itself is rectangular and the orientation can be either vertical or horizontal. What I want is to limit the textside property so that if the orientation is vertical the textside can only be left or right and if orientation is horizontal the textside can only be top or bottom.
Clearly you can do this at runtime within a set property method by checking other properties but what I would like to do this within the property window as design time so there is no chance of someone choosing the wrong combination of properties and then nothing or the wrong information is displayed when the project is run.
Currently I have this:
public enum VerticalTextSide { Left, Right }
public enum HorizontalTextSide { Top, Bottom }
public enum TextSide { }
public enum Orientation { Vertical, Horizontal }
private VerticalTextSide vts;
private HorizontalTextSide hts;
private TextSide db;
private Orientation or;
public TextSide textSide
{
get
{
if (or == Orientation.Vertical)
{
[need help!!]
}
else
{
[need help!!]
}
}
set
{
[need help!!]
}
}
public Orientation orientation
{
get
{
return or;
}
set
{
or = value;
}
}
Where I need help is to return and set the enum values depending on the orientation chosen. Maybe there is another way, perhaps?
Hopefully this is doable?
Thanks
Not sure how to limit it at design time -- I've seen compile-time and run-time checking.
However, you may want to consider simplifying your enumerations by combining Orientation and TextSide.
For instance, System.Windows.Forms.TabControl has Alignment property (TabAlignment enum) which specifies Top, Bottom, Left and Right. Implicit in this Horizontal/Vertical.
By doing this, you simplify the interface and remove the possibility for error and invalid combinations.
The trouble is with that is that this will be taken futher and include something like text direction where you can have LeftToRight or RightToLeft either of which are acceptable for a horizontal control but not for a vertical control where you may want TopToBottom or BottomToTop!!
Is the only way to add properties to a control via a getter/setter type approach?
Is there really no way of dynamically changing properties which are dependent upon others? This seems to be a big shortfall.
I know this probably seems a bit clumsy but what about not using Left/Right or Up/Down but just Position1/Position2? For example in a horizontal setup Position1 would be Left (at least when thinking about LeftToRight) and in vertical setup Position2 would be Top (assuming TopToBottom).
You could then also forget about TopToBottom/BottomToTop or LeftToRight/RightToLeft but just use a boolean called something like IsReverseOrder.