FormLayout, FormData and controls - swt

can someone please explain to me how FormData on FormLayout works? I'm trying to understand the FormAttachment constructors and its parameters (numerator, offset, denominator). When do you need only one of them, two of them or all of the parameters... Also, if i have a group (or a composite) which will add widgets like buttons and labels which will need to be resized as per resolution using FormData, does the Group need to have a FormLayout also? I tried specifying a width of a group with form layout but no change

FormAttachment has several different constructors, I generally use two typically:
new FormAttachment (int numerator, int offset) - If there's only two integer parameters then the first parameter represents the percentage from the edge of the parent. Which edge is determined by which slot in the FormData object you insert the FormAttachment into: FormData.top, data.bottom, data.left, and FormData.right.
new FormAttachment (Control control, int offset) - Instead of positioning the object against the parent, this positions the object next to another child object. This works in conjunction with the previous constructor so that you effectively "anchor" one element against the parent, then build your layout by positioning other elements relative to the anchor. This also allows you to easily move and insert elements into the overall layout without having to rebuild the entire layout.
The others are variations on the themes of these two. FormAttachment (int numerator, int denominator, int offset) is the same as the FormAttachment with two integer parameters, but with two the denominator just becomes "100", i.e. it turns the numerator into a percentage. But you could say something like (1, 2, 0) for 1/2 of the way across or (1, 3, 0) for 1/3 of the space.
I'm not sure what you mean about whether the Group will need to have a layout defined but in general every parent Composite must have a layout defined on it to display children elements. If you want elements to resize as the parent resizes, one option is to attach the child to both the left and right sides of the element:
FormData formData = new FormData();
formData.left = new FormAttachment (0, 0); // Attach at the 0% left with 0 offset
formData.right = new FormAttachment (100, 0); // Attach at the 100% right with 0 offset
The Eclipse site has a lot of good snippets showing FormLayout, check out:
http://www.eclipse.org/swt/snippets/
Scroll down to the FormLayout section.

Related

2D Unity: expand UI element based on text to the bottom

I've got a game object (InfoBox) with a..
Vertical Layout Group (Padding 20 on all sides, Control Child Size Height active)
an image
a Content Size Fitter (Vertical Fit set to Preferred Size, Horizontal Unconstrained)
Inside this InfoBox is a Text-Element and every time I update the text, I want the InfoBox to expand or collapse, but to the bottom only. Right now my InfoBox always expands or collapses to both top and bottom, but I don't want that to happen. How can I achieve that? I added some screenshots to better visualise this.
These are my settings for the InfoBox:
And these are my settings for the text:
And this is what happens when I use for example less text, the box collapses from bottom and top, but I want it to stay fixed at the top (on the same line as the green box next to it) and only collapse on the bottom:
Any help is really appreciate!
You main issues looks like you are using a ContentSizeFitter also on the parent object. So it depends how this parent object is aligned with its according parent.
This sentence sounds strange I know but what you did is basically shifting up the alignment responsibility to the parent.
=> Make your UI element aligned to the top and grow downwards.
All you need to do for this is either set
Anchors Min y -> 1
Anchors Max y -> 1
Pivot y -> 1
or simply go to the RectTransform Inspector, open the alignment tool and hold Shift + Alt and click on the top alignment:
For the second instead of using the ContentSizeFitter I prefer to have my own script that only does what it should and nothing more.
You can get the preferredHeight which is exactly the value you are looking for.
The following script simply always applies the preferred height to the text rect. Using [ExecuteAlways] this also works in edit mode. Simply attach it on the same GameObject as the UI.Text component
[ExecuteAlways]
[RequireComponent(typeof(Text))]
[RequireComponent(typeof(RectTransform))]
public class TextHeightFitter : MonoBehaviour
{
[SerializeField] private RectTransform _rectTransform;
[SerializeField] private Text _text;
private void Update()
{
if (!_text) _text = GetComponent<Text>();
if (!_rectTransform) _rectTransform = GetComponent<RectTransform>();
var desiredHeight = _text.preferredHeight;
var size = _rectTransform.sizeDelta;
size.y = desiredHeight;
_rectTransform.sizeDelta = size;
}
}

How to determine if one offset contained with another offset area?

I would like to determine if a widget is touching another widget, so far I have the following offset - Positions of widgets. However, this is a single point rather the a contained area.
Offset(48.8, 425.6) <- Box 1
Offset(70.0, 456.0) <-- Box 2
What is the best way to determine if Box 1 is near box 2 ( Box 2 would be scaled out by xx number to improve the matching )
I am using GlobalKeys to determine position like below
RenderBox box1 = box1Key.currentContext.findRenderObject();
Offset box1Pos = box1.localToGlobal(Offset.zero);
RenderBox box2 = box2Key.currentContext.findRenderObject();
Offset box2Pos = box2.localToGlobal(Offset.zero);
You could use the class Rect to define the boundings of one of your widgets and then use the method contains
https://api.flutter.dev/flutter/dart-ui/Rect/contains.html
The Rect class also has the method intersect which can be better suited for your question.
https://api.flutter.dev/flutter/dart-ui/Rect/intersect.html

How to align a label versus its content?

I have a label (e.g. "A list of stuff") and some content (e.g. an actual list). When I add all of this to a PDF, I get:
A list of stuff: test A, test B, coconut, coconut, watermelons, apple, oranges, many more
fruites, carshow, monstertrucks thing
I want to change this so that the content is aligned like this:
A list of stuff: test A, test B, coconut, coconut, watermelons, apple, oranges, many more
fruites, carshow, monstertrucks thing, everything is startting on the
same point in the line now
In other words: I want the content to be aligned so that it every line starts at the same X position, no matter how many items are added to the list.
There are many different ways to achieve what you want: Take a look at the following screen shot:
This PDF was created using the IndentationOptions example.
In the first option, we use a List with the label ("A list of stuff: ") as the list symbol:
List list = new List();
list.setListSymbol(new Chunk(LABEL));
list.add(CONTENT);
document.add(list);
document.add(Chunk.NEWLINE);
In the second option, we use a paragraph of which we use the width of the LABEL as indentation, but we change the indentation of the first line to compensate for that indentation.
BaseFont bf = BaseFont.createFont();
Paragraph p = new Paragraph(LABEL + CONTENT, new Font(bf, 12));
float indentation = bf.getWidthPoint(LABEL, 12);
p.setIndentationLeft(indentation);
p.setFirstLineIndent(-indentation);
document.add(p);
document.add(Chunk.NEWLINE);
In the third option, we use a table with columns for which we define an absolute width. We use the previously calculated width for the first column, but we add 4, because the default padding (left and right) of a cell equals 2. (Obviously, you can change this padding.)
PdfPTable table = new PdfPTable(2);
table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
table.setTotalWidth(new float[]{indentation + 4, 519 - indentation});
table.setLockedWidth(true);
table.addCell(LABEL);
table.addCell(CONTENT);
document.add(table);
There may be other ways to achieve the same result, and you can always tweak the above options. It's up to you to decide which option fits best in your case.

Add rectangle as inline-element with iText

How do I add a rectangle (or other graphical elements) as inline-elements to an iText PDF?
Example code of what I'm trying to achieve:
foreach (Row r in entrylist)
{
p = new Paragraph();
p.IndentationLeft = 10;
p.SpacingBefore = 10;
p.SpacingAfter = 10;
p.Add(new Rectangle(0, 0, 10, 10)); <<<<<<<<< THAT ONE FAILS
p.Add(new Paragraph(r.GetString("caption"), tahoma12b));
p.Add(new Paragraph(r.GetString("description"), tahoma12));
((Paragraph)p[1]).IndentationLeft = 10;
doc.Add(p);
}
It's something like a column of text-blocks, of which each of them have (only a printed) checkbox.
I've tried various things with DirectContent, but it requires me to provide absolute X and Y values. Which I simply don't have. The elements should be printed at the current position, wherever that may be.
Any clues?
You need a Chunk for which you've defined a generic tag. For instance, in this example listing a number of movies, a snippet of pellicule is drawn around the year a movie was produced and an ellipse was drawn in the background of the link to IMDB.
If you look at the MovieYears example, you'll find out how to use the PdfPageEvent interface and its onGenericTag() method. You're right that you can't add a Rectangle to a Paragraph (IMHO that wouldn't make much sense). As you indicate, you need to draw the rectangle to the direct content, and you get the coordinates of a Chunk by using the setGenericTag() method. As soon as the Chunk is drawn on the page, its coordinates will be passed to the onGenericTag() method.

how to get the drop target from gwt-dnd

I have a vertical panel containing two rows, say row 1 and row 2, each
row contains couple of widgets, now i need to allow the user to drag
and drop widgets between row 1 and row 2, here is what i did
_handler = new DragHandler() { .... };
_widgetDragController = new PickupDragController(boundaryPanel, false);
_widgetDragController.setBehaviorMultipleSelection(false);
_widgetDragController.addDragHandler(_handler);
then for each row, create panel to hold widgets and assign a drop controller:
VerticalPanelWithSpacer vPanel = new VerticalPanelWithSpacer();
// initialize a widget drop controller for the current column VerticalPanelDropController
widgetDropController = new VerticalPanelDropController(vPanel);
_widgetDragController.registerDropController(widgetDropController);
how can i find the drop target (namely which row) when i dnd widgets between row 1 and row 2? is there any way the _widgetDragController can tell which drop controller got involved and then i can further call getDropTarget() from the drop controller?
You could implement the functionality in VerticalPanelDropController.onDrop(DragContext), which gets called when the users drop on that drop controller. The drop controller knows the VerticalPanelWithSpacer it belongs to, and the dragContext contains information such as the x, y coordinates. You could use this information (the y coordinate & the coordinates of the widget) to calculate the row which should be added (although you might need to take scrolling etc into account, which makes it a bit more tricky). Hope that helps :-)