In the following code I use SWT and also draw2d. When I run the program however nothing shows up. After some debugging I've found it to be because the container's size are all 0. I have to manually enter a size like
canvasData.heightHint = 500;
canvasData.widthHint = 500;
This is fine and dandy but I need these containers to fit themselves into the space given to them by form. Is there any way to accomplish this? Any advice would be helpful.
/* (non-Javadoc)
* #see org.eclipse.ui.forms.editor.FormPage#createFormContent(org.eclipse.ui.forms.IManagedForm)
*/
#Override
protected void createFormContent( IManagedForm managedForm )
{
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
Composite tabParent = managedForm.getToolkit().createComposite(form.getBody());
GridData tabParentData = new GridData(SWT.FILL,SWT.FILL,true,true);
tabParent.setLayoutData(tabParentData);
tabParent.setLayout(new GridLayout());
FigureCanvas canvas = new FigureCanvas(tabParent);
GridData canvasData = new GridData(SWT.FILL,SWT.FILL,true,true);
canvas.setLayoutData(canvasData);
//diagramContents is an IFigure from draw2d. it holds other IFigures, Labels, ect.
//Essentially everything being displayed
canvas.setContents(diagramContents);
//This method is what creates everything being displayed (the stuff in diagramContents)
refreshDisplayFromModel();
canvas.pack();
tabParent.pack();
}
Throw out GridLayout and GridData and try to set a FillLayout onto tabParent like this:
form.getBody().setLayout(new FillLayout()); //*
Composite tabParent = managedForm.getToolkit().createComposite(form.getBody());
tabParent.setLayout(new FillLayout());
FigureCanvas canvas = new FigureCanvas(tabParent);
//no layouting
canvas.setContents(diagramContents);
FillLayout doesn't need a constraints object and just makes its child grab everything. If you have more than one child, I propose you take a look at RowLayout for simple stuff and FormLayout for complex stuff, and just forget about GridLayout.
You can get rid of the pack() calls aswell.
*: Since you gave tabParent a GridData object aswell, I figured your form has a GridLayout. Got rid of that for you, too.
Use
canvas.getViewPort().setContentsTracksWidth( true );
canvas.getViewPort().setContentsTracksHeight( true );
Related
When I use setText() on one or both Text fields, it resizes the field to the length of the text. How do I prevent that from happening?
inner = new Composite(middle, SWT.NONE);
inner.setLayout(new GridLayout(5, false));
chkbxBtn = new Button(inner, SWT.CHECK);
chkbxBtn.setText("Check box button: ");
chkbxBtn.setSelection(false);
new Label(inner, SWT.NONE).setText("Text field 1: ");
startCol = new Text(inner, SWT.BORDER | SWT.NONE);
new Label(inner, SWT.NONE).setText("Text field 2: ");
endCol = new Text(inner, SWT.BORDER | SWT.NONE);
To clarify, SWT does not re-layout after changing the text (or any other property) of a Text control (or controls in general). It is your code or a resize event that causes the re-layout.
If you want a control to have a pre-set size, and its parent uses a GridLayout, you can set GridData with a widthHint like this:
GridData gridData = new GridData();
gridData.widthHint = ...
text.setLayoutData( gridData );
However, it is usually a bad idea trying to control the size of widgets. Thus make sure that your layout strategy aligns with best practices of UI design.
There are situations when changes to the text trigger a component re-layout. For example, show an error message as a text validation result (I found it in SWT forms).
Setting the width hint in the GridData for the text component fixes this. Width hint can be set to 0 or the minimum required size.
GridDataFactory.swtDefaults()//
.grab(true, false)//
.hint(0, SWT.DEFAULT)// width hint prevents text from expanding to full line
.align(SWT.FILL, SWT.CENTER)//
.applyTo(text);
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).
I'm developing a Vaadin application and am having extreme difficulty getting some aspects of the layout as I want. The major problem right now is that I can't seem to get a vertical scroll in my layout no matter how big the size of the content is or how small the browser window is..
I have read up on the subject, I know that the hLayout and the vLayout doesn't support scrollbars but the Panel do. I've tried in many different combinations to make it work but I've only managed to get a horizontal scrollbar to generate but never a vertical one.
Another problem is that I'm building the application inside an existing "template" provided by the company. This template contains a footer containing some copyright information. This footer doesn't seem to occupy any space in the browser window with regards to the content I'm adding, which causes when viewing on smaller screens the horizontal scrollbar to appear "underneath" the footer, non-accessible... I'll provide some of the code of how it looks now.
public class InventorySimCardTable extends M2MViewBase { //M2MViewBase extends VerticalLayout
private final SPanel mainContent = Cf.panel("");
private final SPanel tabPanel = Cf.panel("");
private final SVerticalLayout tabcontent = Cf.vLayout();
protected InventoryFilterPanel inventoryFilterPanel;
#Override
protected void initComponent() {
setSizeFull();
tabPanel.setSizeFull();
tabPanel.getContent().setSizeUndefined();
Table simCardTable = new Table();
simCardTable.setWidth("1898px");
simCardTable.setPageLength(15);
tableContainer.setSizeUndefined();
tableContainer.addComponent(simCardTable);
mainContent.setWidth("99%");
mainContent.setHeight("100%");
mainContent.setContent(tableContainer);
mainContent.setScrollable(true);
centeringlayout.setSizeFull();
centeringlayout.addComponent(mainContent);
centeringlayout.setComponentAlignment(mainContent, Alignment.MIDDLE_CENTER);
tabPanel.addComponent(centeringlayout);
addComponent(tabPanel);
}
}
I would love to know if anyone sees any obvious errors in my code. And if anyone knows what property I can set on the footer CSS to have it occupy space in the content view so that the horizontal scroll doesn't appear underneath it. Thank you!
What I did to solve this issue was to structure the code as follows. This will create a vertical and horizontal scroll bar for the Panel holding my filter component and the table. Hopefully this can help someone with a similar problem.
#Override
protected void initComponent() {
super.initComponent();
if(!tableCreated) {
createSimCardsTable();
tableCreated = true;
}
mainWindow = this.getWindow();
Panel basePanel = new Panel("");
basePanel.addComponent(inventoryFilterPanel);
AbstractComponent separatorLine = Cf.horizontalLine(); //Of no signficance
separatorLine.addStyleName("m2m-horizontal-line-list-separator");
separatorLine.setWidth("99%");
basePanel.addComponent(separatorLine);
basePanel.addComponent(simCardTable);
basePanel.setSizeFull();
basePanel.getContent().setSizeUndefined(); // <-- This is the important part
addComponent(basePanel);
setExpandRatio(basePanel, 1);
}
All Vaadin components have size undefined by default, so usually there is no need to call method setSizeUndefined(). Also there is no need to call setScrollable(true), because it enables only programmatic scrolling possibility.
When I was trying to make a sense of scrolling appearance I wrote a simple skeleton of layout. Try this out as a content of the main window:
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.VerticalLayout;
public class Skeleton extends VerticalLayout {
public Skeleton() {
setSizeFull();
addComponent(new Label("Header component"));
HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
Panel leftComponent = new Panel();
Panel rightComponent = new Panel();
splitPanel.setFirstComponent(leftComponent);
splitPanel.setSecondComponent(rightComponent);
for (int i = 0 ; i < 200 ; i ++) {
leftComponent.addComponent(new Label("left"));
rightComponent.addComponent(new Label("right"));
}
leftComponent.setSizeFull();
rightComponent.setSizeFull();
addComponent(splitPanel);
setExpandRatio(splitPanel, 1);
addComponent(new Label("Footer component"));
}
}
You should see scrollbars inside the nested panels. But if setSizeFull() is removed from Skeleton layout, then it is not limited in size (by default) and grows downwards - then only the scrollbar of the whole window appears.
Add this to your styles.css
.v-verticallayout > div {
overflow-y: auto ! important;
}
First of all try to make your panel scrollable by calling setScrollable(true) method, but this will not work if you set some custom layout with setSizeFull() as this panel new layout.
If you exactly know that you application will be opened in device with small screen resolution, you simple can set for your "primary"/"main" layout some fixed width and height, or add some CSS style with params like min-width: {some value} px, min-height: {some value} px.
Based on this post, I added vertical.setSizeUndefined(); and started seeing vertical scrollbars.
setMainWindow(new Window(title ));
vertical.setSizeFull();
vertical.setHeight("100%");
toolbar = createToolbar();
vertical.addComponent(toolbar);
vertical.setExpandRatio(toolbar, 0.03f);
Component tree = buildTree();
vertical.addComponent(tree);
vertical.setExpandRatio(tree, 0.97f);
vertical.setSizeUndefined();
getMainWindow().setContent(vertical);>
The only way I could fix this now (v6.8.14) is to specify the height in px values in stead of %
Use CustomLayout, always. It's faster, more efficient and by controlling html and css easily you can acieve a graphically consistent result
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.
I'm developing a an eclipse plugin that uses an SWT interface. I need to display text, and within that text there needs to be links. The only two widgets that I've found that will allow me to include clickable links in text are Link and Browser. Browser, however, is overkill for my needs, and I couldn't properly customize the look of it. This only leaves the Link widget.
The problem is I need the Link widget to inherit a gradient from the Composite in which it is in. It does this correctly, only when it is resized or scrolled the Link component flickers. The Link is the only component in which I have seen this effect.
In an attempt to fix this I've tried manipulating other components into having clickable links, but I haven't found a good solution yet.
Is there anyway to fix the flickering effect on the Link, or is there a different component which would support links?
Thanks,
Brian
After spending the day working on this, I came up with a workaround. I created a Composite for the text area. For each word that isn't part of a url,got its own label. For links, each letter got its own label. Then the labels for the url characters got a listener to launch a browser. Using this method provided the Link functionality, handled resizing properly, and has no flicker.
Have you tried passing SWT.NO_BACKGROUND to your Link widget? It might get a little strange... and you may have to do a little more work to get the gui drawing properly, but that would be my first guess.
Other than that, here's my Quick n' dirty implementation of a link inside of a StyledText. You will need to fill in for changing the cursor (if that's something you want), as well as coming up with a good "text to link" mapping scheme.
The only thing is I'm not sure if StyledText will inherit your background... give it a shot.
public class StyledTextExample {
public static void main(String [] args) {
// create the widget's shell
Shell shell = new Shell();
shell.setLayout(new FillLayout());
shell.setSize(200, 100);
Display display = shell.getDisplay();
// create the styled text widget
final StyledText widget = new StyledText(shell, SWT.NONE);
String text = "This is the StyledText widget.";
widget.setText(text);
widget.setEditable(false);
final StyleRange hyperlinkStyle = new StyleRange();
String linkWord = "StyledText";
hyperlinkStyle.start = text.indexOf(linkWord);
hyperlinkStyle.length = linkWord.length();
hyperlinkStyle.fontStyle = SWT.BOLD;
hyperlinkStyle.foreground = display.getSystemColor(SWT.COLOR_BLUE);
widget.setStyleRange(hyperlinkStyle);
widget.addMouseListener(new MouseAdapter() {
public void mouseUp(MouseEvent arg0) {
Point clickPoint = new Point(arg0.x, arg0.y);
try {
int offset = widget.getOffsetAtLocation(clickPoint);
if (widget.getStyleRangeAtOffset(offset) != null) {
System.out.println("link");
}
} catch (IllegalArgumentException e) {
//ignore, clicked out of text range.
}
}});
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch()) display.sleep();
}
}