Auto - Resize NatTable dynamically - nattable

I want to Auto - Resize NatTable dynamically according to the number of rows.
In other words, I have a nattable of height 'x' with 10 rows. If rows are less than 10 then the height of nattable should reduce, so that empty space cannot be seen. If number of rows exceeds 10, vertical scroll bar should come.

That is a SWT layout question in the end. Basically you are asking for a way to specify a minimum height based on the table content. You could solve this with a GridLayout and a resize listener that updates the minimum height dependent on the available container height.
Composite panel = new Composite(parent, SWT.NONE);
panel.setLayout(new GridLayout());
NatTable natTable = new NatTable(panel);
// minimum height of NatTable + scrollbar
int minHeight = natTable.getPreferredHeight() + 18;
GridDataFactory
.swtDefaults()
.align(SWT.FILL, SWT.BEGINNING)
.grab(true, true)
.minSize(SWT.DEFAULT, minHeight)
.applyTo(natTable);
panel.addListener(SWT.Resize, new Listener() {
#Override
public void handleEvent(Event event) {
GridData data = ((GridData) natTable.getLayoutData());
// minHeight + 10 because of the margins
if (panel.getBounds().height < (minHeight + 10)) {
data.minimumHeight = SWT.DEFAULT;
data.verticalAlignment = SWT.FILL;
} else {
data.minimumHeight = minHeight;
data.verticalAlignment = SWT.BEGINNING;
}
}
});
Note that this is just one solution for this. There might be more elegant ones dependent on the layout you are using.

Related

Adapting row height in JFace TableViewer as I scroll my table

I have a JFace TableViewer with an ILazyContentProvider and a StyledCellLabelProvider for each column, which I mostly grabbed from https://wiki.eclipse.org/JFaceSnippets#Snippet006TableMultiLineCells to enable multiline rows. When I open the table, all rows have the height of the row which takes up the most space, as intended. As I scroll down the table, the row heights will change as intended if a row takes up more space. However, this does not currently work in the other direction, i.e., if I scroll so that the current rows showing take up less space, all rows still have the height of the largest row in the whole table.
Is there a way to solve this? Somehow there seems to be a memory of the content that the lazy content provider should be forgetting?
This is my measure method in the StyledCellLabelProvider:
#Override
protected void measure(Event event, Object element) {
event.width = viewer.getTable().getColumn(event.index).getWidth();
if (event.width == 0) {
return;
}
TableEntryData rowData = (TableEntryData) element;
TableCellData cellData = getCellData(rowData, event.index);
int height = event.gc.textExtent(SOME_STRING).y; // Height of a written string on one line.
int lines = cellData.getPoints().size();
event.height = height * lines;
event.gc.dispose();
}
and this is most of my ILazyContentProvider:
#Override
public void updateElement(int index) {
viewer.replace(entries.get(index), index);
}
#SuppressWarnings("unchecked") // TODO:
#Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
this.entries = (List<TableEntryData>) newInput;
}
The measure item code in the Table class (used by TableViewer) will never reduce the size of rows once it has grown bigger, so there is no way to change this.
The measure code is Table.sendMeasureItem but it can't be overridden. The code here is platform specific, but I checked both the Windows and macOS version (not sure about the Linux/GTK version).
I do have a hack to work around this, but it is platform dependent and I only have it for macOS.

Hw to Freeze the Button in Scroll bar

I am using unity 2018.3.7. In my project I have instantiate 25 buttons in the scroll bar..I am scrolling the button. It is working well.
Actually i want freeze the 12 the button.When i scroll the button. The 12 th button should be constantly should be there and other button should scroll go up.
scrolling should be done but the freeze button should be constantly there.
Like Excel. If we freeze the top row. The top row is constantly there and scrolling is happened.
Like that i have to do in unity.
How to Freeze the button in scroll bar.
Edit:
Actually I have uploaded new gif file. In that gif file 2 row is freezed (Row Heading1,Row Heading2, Row Heading3,RowHeading4).
2nd row is constantly there. Rest of the the rows 4 to 100 rows are going up.
Like that i have to do ...
How can i do it..
Though your question still is very broad I guess I got now what you want. This will probably not be exactly the solution you want since your question is quite vague but it should give you a good idea and starting point for implementing it in the way you need it.
I can just assume Unity UI here is the setup I would use. Since it is quite complex I hope this image will help to understand
so what do we have here:
Canvas
has the RowController script attached. Here reference the row prefab and adjust how many rows shall be added
Panel is the only child of Canvas. I just used it as a wrapper for having a custom padding etc - it's optional
FixedRowPanel
Here we will add the fixed rows on runtime
Initially has a height of 0!
Uses anchore pivot Y = 1! This is later important for changing the height on runtime
Uses a Vertical Layout Group for automatically arranging added children
ScrollView - Your scrollview as you had it but
Uses streched layout to fill the entire Panel (except later the reduced space for the fixed rows)
Uses anchor pivot Y = 1! Again important for changing the height and position on runtime later
Viewport afaik it should already use streched anchors by default but not sure so make it
Content
Uses a Vertical Layout Group
Initially has a height of 0 (but I set this in the code anyway) and will grow and shrink accordingly when adding and removing rows
And finally RowPrefab
I didn't add its hierachy in detail but it should be clear. It has a Toggle and a Text as childs ;)
Has the Row script attached we use for storing and getting some infos
Now to the scripts - I tried to comment everything
The Row.cs is quite simple
public class Row : MonoBehaviour
{
// Reference these via the Inspector
public Toggle FixToggle;
public Text FixTogText;
public Text RowText;
public RectTransform RectTransform;
// Will be set by RowController when instantiating
public int RowIndex;
private void Awake()
{
if (!RectTransform) RectTransform = GetComponent<RectTransform>();
if (!FixToggle) FixToggle = GetComponentInChildren<Toggle>(true);
if (!FixTogText) FixTogText = FixToggle.GetComponentInChildren<Text>(true);
}
}
And here is the RowController.cs
public class RowController : MonoBehaviour
{
public Row RowPrefab;
public RectTransform ScrollView;
public RectTransform Content;
public RectTransform FixedRowParent;
public int HowManyRows = 24;
public List<Row> CurrentlyFixedRows = new List<Row>();
public List<Row> CurrentlyScrolledRows = new List<Row>();
// Start is called before the first frame update
private void Start()
{
// initially the content has height 0 since it has no children yet
Content.sizeDelta = new Vector2(Content.sizeDelta.x, 0);
for (var i = 0; i < HowManyRows; i++)
{
// Create new row instances and set their values
var row = Instantiate(RowPrefab, Content);
// store the according row index so we can later sort them on it
row.RowIndex = i;
row.RowText.text = $"Row Number {i + 1}";
// add a callback for the Toggle
row.FixToggle.onValueChanged.AddListener(s => HandleToggleChanged(row, s));
// increase the content's size to fit the children
// if you are using any offset/padding between them
// you will have to add it here as well
Content.sizeDelta += Vector2.up * row.RectTransform.rect.height;
// don't forget to add them to this list so we can easily access them
CurrentlyScrolledRows.Add(row);
}
}
// called every time a row is fixed or unfixed via the Toggle
private void HandleToggleChanged(Row row, bool newState)
{
if (newState)
{
// SET FIXED
// Update the button text
row.FixTogText.text = "Unfix";
// Move this row to the fixedRow panel
row.transform.SetParent(FixedRowParent);
// be default we assume we want the first position
var targetIndex = 0;
// if there are other fixed rows already find the first child of FixedRowParent that has a bigger value
if (CurrentlyFixedRows.Count > 0) targetIndex = CurrentlyFixedRows.FindIndex(r => r.RowIndex > row.RowIndex);
// handle case when no elements are found -> -1
// this means this row is the biggest and should be the last item
if (targetIndex < 0) targetIndex = CurrentlyFixedRows.Count;
// and finally in the hierachy move it to that position
row.transform.SetSiblingIndex(targetIndex);
// insert it to the fixed list and remove it from the scrolled list
CurrentlyFixedRows.Insert(targetIndex, row);
CurrentlyScrolledRows.Remove(row);
// Make the fixed Panel bigger about the height of one row
FixedRowParent.sizeDelta += Vector2.up * row.RectTransform.rect.height;
// Make both the scrollView and Content smaller about one row
Content.sizeDelta -= Vector2.up * row.RectTransform.rect.height;
ScrollView.sizeDelta -= Vector2.up * row.RectTransform.rect.height;
// Move the scrollView down about one row in order to make space for the fixed panel
ScrollView.anchoredPosition -= Vector2.up * row.RectTransform.rect.height;
}
else
{
// SET UNFIXED - Basically the same but the other way round
// Update the button text
row.FixTogText.text = "Set Fixed";
// Move this row back to the scrolled Content
row.transform.SetParent(Content);
// be default we assume we want the first position
var targetIndex = 0;
// if there are other scrolled rows already find the first child of Content that has a bigger value
if (CurrentlyScrolledRows.Count > 0) targetIndex = CurrentlyScrolledRows.FindIndex(r => r.RowIndex > row.RowIndex);
// handle case when no elements are found -> -1
// this means this row is the biggest and should be the last item
if (targetIndex < 0) targetIndex = CurrentlyScrolledRows.Count;
// and finally in the hierachy move it to that position
row.transform.SetSiblingIndex(targetIndex);
// insert it to the scrolled list
CurrentlyScrolledRows.Insert(targetIndex, row);
// and remove it from the fixed List
CurrentlyFixedRows.Remove(row);
// shrink the fixed Panel about ne row height
FixedRowParent.sizeDelta -= Vector2.up * row.RectTransform.rect.height;
// Increase both Content and Scrollview height by one row
Content.sizeDelta += Vector2.up * row.RectTransform.rect.height;
ScrollView.sizeDelta += Vector2.up * row.RectTransform.rect.height;
// Move scrollView up about one row height to fill the empty space
ScrollView.anchoredPosition += Vector2.up * row.RectTransform.rect.height;
}
}
}
Result:
As you can see I can now fix and unfix rows dynamically while keeping their correct order within both according panels.

Resizeable quadratic grid

I would like to display a quadratic GridPane inside a window. The window can have every possible size and normally width and height are not equal. Anyway I would like to display the GridPane as square centered like this:
respectively
Ideally there is a configurable padding around the square. The pictures are taken from a canvas approach, but I want to switch to standard controls. Can anyone give me some hints how to achieve this?
One way to achieve an squared layout for your grid for any resolution of your window is rescaling it to use the maximum size of the window (after some padding), while keeping the squared size.
Instead of a GridPane, a simple Group is more flexible for moving its children, though it requires manual layouting of them.
This simple snippet is based on the JavaFX implementation of the 2048 game you can find here. It uses styleable rectangles to create a grid, and over them the 'tiles' are added. To find out more about styling, layouting or tile movement, go to the refered link.
private static final int NUM_CELLS = 15;
private static final int CELL_SIZE = 50;
private static final int TILE_SIZE = CELL_SIZE-15;
private final static int MARGIN = 20;
#Override
public void start(Stage primaryStage) {
// create background square grid
Group gridGroup = new Group();
IntStream.range(0,NUM_CELLS).boxed().forEach(i->
IntStream.range(0,NUM_CELLS).boxed().forEach(j->{
Rectangle cell = new Rectangle(i * CELL_SIZE, j * CELL_SIZE, CELL_SIZE, CELL_SIZE);
cell.setFill(Color.WHEAT);
cell.setStroke(Color.GREY);
gridGroup.getChildren().add(cell);
})
);
// Add grid to board
Group board = new Group(gridGroup);
// add random tiles to board
IntStream.range(0,NUM_CELLS).boxed().forEach(i->
IntStream.range(0,NUM_CELLS).boxed().forEach(j->{
if(i==j || NUM_CELLS-i-1==j){
Label label = new Label();
label.setMinSize(TILE_SIZE, TILE_SIZE);
label.setPrefSize(TILE_SIZE, TILE_SIZE);
label.setMaxSize(TILE_SIZE, TILE_SIZE);
label.setStyle("-fx-background-color: red; -fx-background-radius: 50");
label.setLayoutX((i+0.5)*CELL_SIZE-TILE_SIZE/2);
label.setLayoutY((j+0.5)*CELL_SIZE-TILE_SIZE/2);
board.getChildren().add(label);
}
})
);
Bounds gameBounds = board.getLayoutBounds();
StackPane root = new StackPane(board);
// Listener to rescale and center the board
ChangeListener<Number> resize = (ov, v, v1) -> {
double scale = Math.min((root.getWidth() - MARGIN) / gameBounds.getWidth(),
(root.getHeight() - MARGIN) / gameBounds.getHeight());
board.setScaleX(scale);
board.setScaleY(scale);
board.setLayoutX((root.getWidth() - gameBounds.getWidth()) / 2d);
board.setLayoutY((root.getHeight() - gameBounds.getHeight()) / 2d);
};
root.widthProperty().addListener(resize);
root.heightProperty().addListener(resize);
Scene scene = new Scene(root);
// Maximum size of window
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
double factor = Math.min(visualBounds.getWidth() / (gameBounds.getWidth() + MARGIN),
visualBounds.getHeight() / (gameBounds.getHeight() + MARGIN));
primaryStage.setScene(scene);
primaryStage.setWidth((gameBounds.getWidth() + MARGIN) * factor);
primaryStage.setHeight((gameBounds.getHeight() + MARGIN) * factor);
primaryStage.show();
}
And this is how it will look like after some window resizing:

Having a dynamic number of standalone views divide the space evenly

When showing multiple instances of the same view, I would like the following to hold true:
The views do not stack
The number of them is dynamic (let's say 1 to 10) and not known initially: they are added by the user, one by one
They are positioned above/below each other
They take up all the vertical space amongst themselves
By default they have equal height (if there are 3 views, each gets 1/3 of the total vertical space, adding a 4th view causes them all to get 1/4 etc)
What I use to add the views in Perspective is the following:
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.addStandaloneViewPlaceholder(MarkerView.VIEW_ID + ":0", IPageLayout.TOP, 0.6F, editorArea, true);
layout.addStandaloneViewPlaceholder(MarkerView.VIEW_ID + ":1", IPageLayout.BOTTOM, 0.6F, editorArea, true);
layout.addStandaloneViewPlaceholder(MarkerView.VIEW_ID + ":2", IPageLayout.BOTTOM, 0.6F, editorArea, true);
The problem is that not knowing what the number of views will be, the ratios won't provide equal space to all instances of the view.
Is it somehow possible to adjust the ratios of existing views after adding a new one?
I've also tried having the view class implement ISizeProvider (which I admit I do not have a full grasp of), but haven't managed to achieve what I want with that either:
#Override
public int getSizeFlags(boolean width) {
return width ? 0 : SWT.FILL | SWT.MIN | SWT.MAX;
}
#Override
public int computePreferredSize(boolean width, int availableParallel, int availablePerpendicular, int preferredResult) {
int windowHeight = PlatformUI.getWorkbench().getDisplay().getActiveShell().getBounds().height;
int nrOfViews = Model.getInstance().markerCounter;
return width ? preferredResult : windowHeight / nrOfViews;
}
Is this approach something in the right direction at least?

How to add Lables to SWT Scale ticks?

I have a SWT Scale widget, and I need to add labels to the ticks on the scale.
Is there a way to do this? maybe on a Slider widget?
Thanks
This might be not exactly what you are asking, but you could incorporate a Text widget beside the Scale widget, responding to your Scale values.
For instance:
final Scale scale = new Scale(shell, SWT.HORIZONTAL);
scaleValue = new Text(shell, SWT.SINGLE | SWT.BORDER);
//scale properties omitted...
scale.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
int perspectivevalue = scale.getSelection();
scaleValue.setText("" + (perspectivevalue));
}
});
This has the effect of updating the value in the Text widget given whatever you drag the Scale slider to.