How to set max composite size in SWT - java

Is there any way to set maximal size of composite? Only what i have found methods
setMinimumSize(Point point)
setSize(Point point)
which allow me to set minimal and prefered size.

As far as I know, there is no Layout, that has a setting for maximal size, which is a good thing in my opinion.
Consider the following szenario: You set the maximal size of a Widget/Composite to a value that you think "looks good". Depending on the screen resolution and text size of the end-user, the chosen maximal size might just look wrong. This is why the layouts usually adapt to the available space.
Nevertheless, here is some code, that restricts the size:
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new GridLayout(1, false));
final Button left = new Button(shell, SWT.PUSH);
left.setText("Restricted width");
left.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
left.addListener(SWT.Resize, new Listener()
{
#Override
public void handleEvent(Event arg0)
{
Point size = left.getSize();
if(size.x > 200)
{
left.setSize(200, size.y);
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
Before resizing:
After resizing:

i am curious about why you want to set a maximum size. can you give a concrete example? i had a situation where i wanted this option, but i came up with a solution, that was even better. just think of a widget in a layout that has a preferred size based on its contents, e.g. a text widget. now you want that widget to be as big as the available space allows it. but since that widget is claiming space based on its contents, it might claim more space than necessary. so what i needed was a maximum size, but if more space is available, that widget will still be able to take the space without claiming more.
but lets have a look at an example:
public static void main(final String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
final Text text = new Text(shell, SWT.WRAP | SWT.MULTI | SWT.V_SCROLL);
text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
text.setText(getLongText());
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
the call to shell.pack() will make the shell use the preferred size to display its contents. the layout will then ask the text widget to compute its preferred size. the text widget does not know, that the shell will be expanded as well and does not have a fixed size.
well this problem can be solved if we could give the text widget a maximum size. but it will cause another problem with the grid layout, since we don't want the text widget to be smaller in case that the shell has a minimum size which is bigger than the preferred size of the text widget. i cannot give you a code example of this case, since there is no maximum size, but just imagine the shell be of a fixed size, and the the text widget inside has a maximum size that is smaller.
the solution is to limit the preferred size computed by the widget to be of a maximum preferred size. i didn't find yet a method to set this value, but you can achieve this effect by overriding the computeSize method of the widget:
final Text text = new Text(shell, SWT.WRAP | SWT.MULTI | SWT.V_SCROLL) {
/** The maximum preferred size. */
private final Point maxSize = new Point(500, 400);
#Override
public Point computeSize(final int wHint, final int hHint, final boolean changed) {
final Point preferredSize = super.computeSize(wHint, hHint, changed);
return new Point(Math.min(maxSize.x, preferredSize.x), Math.min(maxSize.y, preferredSize.y));
}
#Override
protected void checkSubclass() {
// noop, allow subclassing, since we know what we are doing
}
};
now you are still able to increase the shells size by a user drag operation and the widget will still we able to grab more space above the maximum size.

Related

How to avoid SWT table enlargement correctly?

I have a simple SWT program like this:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
shell.setMinimumSize(300, 300);
// table
final Table table = new Table(shell, SWT.BORDER);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.heightHint = 0; // "hack"
table.setLayoutData(gridData);
// example data
for (int i = 0; i < 50; i++) {
final TableItem item = new TableItem(table, SWT.NONE);
item.setText("item no." + i);
}
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
What I expect - I want the table to completely fill out the shells space without changing it's size. (Screenshot 1 and 3)
Problem - If I add rows to the table, the table automatically gets resized (and so also the shell). (Screenshot 2)
Workaround - To avoid this behaviour I added the line gridData.heightHint = 0; to the code. But this seems like a hack to me.
Question - What would be the correct way to avoid the enlargement of the table (and the shell) when data is added?
Regards, winklerrr
Screenshot 1
Without data, table and shell don't get resized, correct behaviour, in both versions
Screenshot 2
With data, table and shell are getting enlarged, wrong behaviour, only without the hack
Screenshot 3
With data, table and shell don't get resized, scrollbar is added, correct behaviour, only with the hack
call shell.setSize(int width, int height) at some point before adding data to the table?
You usually expect the table to have a certain logical height, say 20 rows. At least that's an approach I often choose.
To achieve that, I compute the expected initial height in pixels like this and use it as a height hint.
gridData.heightHint = table.getItemHeight() * 20;
To be more accurate, you would also want to add the table's trim.
shell.setSize(int width, int height)
add this code after the data to your table.

How to get height of string / character in java?

I want to get the height of a string. Here is what i mean:
Say I have string : Hi , then I want the height(Hi) as the max height among all the characters in that string, so it will be the height of H. I saw few posts which said to use graphics to measure it, but i am not printing it, but i just want the height!
If I can get the height of character then i will write a loop to see which is the highest height!
So either of the two is fine:
Get height of string(max height among all letters in string) or
Get height of specified letter!
Just use the method GC#textExtent() to get a Point with the height and width of the text:
public static void main(String[] args)
{
final Display display = Display.getDefault();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
GC gc = new GC(display);
System.out.println(gc.textExtent("Hi").y);
gc.dispose();
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
Javadoc:
Returns the extent of the given string. Tab expansion and carriage return processing are performed.
The extent of a string is the width and height of the rectangular area it would cover if drawn in a particular font (in this case, the current font in the receiver).

SWT RowLayout: what is the minimum size?

I must be missing something stupid. The docs clearly state that the RowData object for the RowLayout layout lets you specify a minimum size (width and height), which makes sense. However, when the underlying widget exceeds this size, the size does not increases and the widget is cropped. Is it really a minimum?
Example
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Example");
shell.setBounds(100, 100, 325, 200);
shell.setLayout(new FillLayout());
Composite comp = new Composite(shell, SWT.BORDER);
comp.setLayout(new RowLayout(SWT.VERTICAL));
Label label1 = new Label(comp, SWT.CENTER);
label1.setLayoutData(new RowData(20,20));
label1.setText("Trying with bounded rowdata...");
Label label2 = new Label(comp, SWT.CENTER);
label2.setText("Trying with no rowdata...");
comp.layout(true,true); // no difference
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
Result:
The javadoc of the constructor RowData(int, int) must be wrong! If you read carrefully the header of the RowData javadoc, it is said that RowData are used to set an initial size for Controls, not the minimum. That's why your Labelis croped by a square of 20x20 px!
Try turning packing off on the layout:
Composite comp = new Composite(shell, SWT.BORDER);
RowLayout layout = new RowLayout(SWT.VERTICAL);
layout.pack = false;
comp.setLayout(layout);
On the other hand you can also consider using a GridLayout if you want the controls to resize with respect to their parents but not less than a minimum width. The minimum width works with GridData.

SWT - Creating a grid of numbers that I'd like to be able to tab through with keyboard

This problem has been driving me CRAZY!!! Using SWT, I'd like to create a grid of numbers that I can tab traverse using the keyboard. I'd like to be able to select and click into each cell (not just on the numbers) to perform some action. In other words, I'm looking for a way to make a true FLAT button. The goal here is to make the grid accessible with screen readers such that when a cell has focus, the screen reader will read the number value in the middle of each cell.
Originally, I created a GridLayout with a set of button controls to display the number values. This actually worked but I didn't want the buttons to look like buttons. The SWT.FLAT style for button controls doesn't work on Windows operating systems. This is caused by an OS limitation.
Next I then tried converting all buttons to labels but since label controls cant take focus, I couldn't implement any type of tab traversal. Next I tried replacing all labels with read-only text controls. I was able to re-introduce the tab traversal/focusing but I can't get the text to display in the dead-center of each cell. This is actually caused by a SWT limitation. The SWT.CENTER style for text controls only affects the horizontal alignment. Text controls can't be vertically aligned.
So finally, someone told me to wrap each read-only text control in a Composite. This allowed me to center the read-only text controls but I don't know how to make the composite itself to be tab traversed.
Any ideas on how I can get this done or how I can make controls that typically dont take focus (like composite, canvas, label) actually take focus so I can tab traverse each control with my keyboard?
I'm fairly new to java and SWT so I apologize if some of this is confusing. Many thanks. This is how I've constructed each of my cells thus far (I've replaced the read-only text with CLabel controls):
Display display = new Display();
Shell shell = new Shell(display);
GridLayout gridLayout = new GridLayout(5, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
gridLayout.horizontalSpacing = 1;
gridLayout.verticalSpacing = 1;
shell.setLayout(gridLayout);
Composite resetComp = new Composite(shell, SWT.BORDER);
GridData compgridData = new GridData(SWT.CENTER, SWT.CENTER, true, true);
GridData resetGD = new GridData(SWT.FILL, SWT.FILL, false, false);
resetGD.verticalSpan = 2;
resetComp.setLayoutData(resetGD);
resetComp.setLayout(new GridLayout(1, false));
CLabel resetCLabel = new CLabel(resetComp, SWT.SHADOW_OUT | SWT.CENTER);
resetCLabel.setText("Reset"); //$NON-NLS-1$
resetCLabel.setLayoutData(compgridData);
resetCLabel.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); //$NON-NLS-1$
resetComp.setToolTipText(resetCLabel.getText());
Here is a trick, maybe it will suits you: create each button inside a Composite, and set the size of the Button bigger than its parent Composite; This way, the border of button is not visible, because outside of its parent composite.
private static final int GRID_SIZE = 5;
private static final int CELL_SIZE = 40;
private static final int PADDING = 3;
public static void main (String [] args) {
Display display = new Display ();
Shell shell = new Shell (display);
shell.setLayout(new GridLayout(GRID_SIZE, true));
for (int i = 0; i < GRID_SIZE * GRID_SIZE; i++) {
createButton(shell, i+1);
}
shell.pack ();
shell.open ();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
private static void createButton(Shell shell, final int number) {
Composite c = new Composite(shell, SWT.NONE);
c.setLayoutData(new GridData(CELL_SIZE, CELL_SIZE));
Button button = new Button(c, SWT.NONE);
button.setText(Integer.toString(number));
button.setBounds(-PADDING, -PADDING, CELL_SIZE + 2 * PADDING, CELL_SIZE + 2 * PADDING);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
System.err.println("click on " + number);
}
});
}
It fulfills your requirement: focus, centered. The result may be more or less nice depending on the Windows version (try to change the padding, or add a border to the Composite, it may look nicer).

How to have text fields fill 100% horizontally

If I have a text field with SWT, how can I get the field to fill to 100% or some specified width.
For example, this text field will only reach for so much horizontally.
public class Tmp {
public static void main (String [] args) {
Display display = new Display ();
Shell shell = new Shell (display);
GridLayout gridLayout = new GridLayout ();
shell.setLayout (gridLayout);
Button button0 = new Button(shell, SWT.PUSH);
button0.setText ("button0");
Text text = new Text(shell, SWT.BORDER | SWT.FILL);
text.setText ("Text Field");
shell.setSize(500, 400);
//shell.pack();
shell.open();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ())
display.sleep ();
}
display.dispose ();
}
}
Make something like this:
Text text = new Text(shell, SWT.BORDER);
text.setText ("Text Field");
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER));
/: Since this is the accepted answer I remove the errors. Thx for correcting me.
Positioning of elements in a Component depends on the Layout object that you are using. In the sample provided, you are using a GridLayout. That means, that you need to provide a specific LayoutData object to indicate how you want your component displayed. In the case of GridLayout, the object is GridData.
To achieve what you want, you must create a GridData object that grabs all horizontal space and fills it:
// Fills available horizontal and vertical space, grabs horizontal space,grab
// does not grab vertical space
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
text.setLayoutData(gd);
Alternative ways include using a different LayoutManager, such as FormLayout. This layout uses a FormData object that also allows you to specify how the component will be placed on the screen.
You can also read this article on Layouts to understand how Layouts work.
As a side note, the constructor new GridData(int style) is marked as "not recommended" in the documentation. The explicit constructor shown in this example is preferred instead.

Categories

Resources