I am using SWT StyledText to populate the responses to my queries in my plugin. I learnt how to autoscroll to the bottom, but couldn't figure out the correct way to auto select the last entry. I have managed to do this in an un-optimized way, i.e updating the background of all the previous lines to white and then highlighting the latest added line, but there has to be a better way to do this.
Here is my code:
rspST.append(rsp + "\n"); ** //<--- Appending the new response to the styledText **
rspST.setTopIndex(rspST.getLineCount() - 1); ** //<-- Scroll to bottom**
for(int i=0; i<rspST.getLineCount() - 2; i++) ** //Setting the background of previous entries to white**
{
rspST.setLineBackground(i, 1,rspST.getDisplay().getSystemColor(SWT.COLOR_WHITE));
}
rspST.setLineBackground(rspST.getLineCount() - 2,
1,rspST.getDisplay().getSystemColor(SWT.COLOR_GRAY)); ** Setting the background of the last line added to gray**
Thanks!
This code will select the last line added by clicking the Button:
private static int lineNr = 0;
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
final StyledText text = new StyledText(shell, SWT.BORDER);
text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Button button = new Button(shell, SWT.PUSH);
button.setText("Add new line");
button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
button.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event arg0)
{
/* Get the start position of the new text */
int start = text.getText().length();
/* Create the new line */
String newText = "Line: " + lineNr++ + "\n";
/* Add it */
text.append(newText);
/* Determine the end of the new text */
int end = start + newText.length();
/* Set the selection */
text.setSelection(start, end);
}
});
shell.pack();
shell.setSize(600, 400);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
This is what it looks like:
Related
I have a parent ScrolledComposite with a dynamic child Composite. When I delete a row, the alignment appears off when using the ScrolledComposite. I have tried this using just Composite instead of ScrolledComposite and it appears to work, so I am wondering if the scrolled layout is just not updating correctly.
Attached are some images showing 1 entry versus 3 entries. The area of interest is the Movable Rings section. The alignment is clearly off when a single entry, but near normal with 3 entries. Code below...
/**
* Create display area for movable rings.
*
* #param topComposite
*/
private void createMovableRingsComposite(Composite topComposite) {
new Label(topComposite, SWT.NONE).setText("Movable Rings");
Composite borderComposite = new Composite(topComposite, SWT.BORDER);
borderComposite.setLayout(new GridLayout(1, false));
borderComposite.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL));
scroll = new ScrolledComposite(borderComposite,SWT.V_SCROLL|SWT.BORDER);
GridLayout gridL = new GridLayout(1, false);
GridData gridD = new GridData(SWT.FILL,SWT.FILL,true,true);
gridD.heightHint = 200;
scroll.setLayout(gridL);
scroll.setLayoutData(gridD);
scroll.setAlwaysShowScrollBars(true);
scroll.setExpandHorizontal(true);
scroll.setExpandVertical(true);
movableRingsComposite = new Composite(scroll, SWT.NONE);
movableRingsComposite.setLayoutData(new GridData(SWT.CENTER,
SWT.CENTER, true, true, 1, 1));
movableRingsComposite.setLayout(new GridLayout(6, false));
// Make all the labels
new Label(movableRingsComposite, SWT.NONE).setText("Show");
new Label(movableRingsComposite, SWT.NONE).setText("ID");
new Label(movableRingsComposite, SWT.NONE).setText("Lat");
new Label(movableRingsComposite, SWT.NONE).setText("Lon");
new Label(movableRingsComposite, SWT.NONE).setText("Radius");
new Label(movableRingsComposite, SWT.NONE).setText("Labels");
scroll.setContent(movableRingsComposite);
Composite createComposite = new Composite(borderComposite, SWT.NONE);
createComposite.setLayout(new GridLayout(3, false));
createComposite.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER,
true, true, 1, 1));
new Label(createComposite, SWT.NONE).setText("New at: ");
pointsMenuButton = new MenuButton(createComposite);
populatePointsMenuButton();
pointsDataManager.addPointsChangedListener(this);
pointsMenuButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
MenuButton menuButton = (MenuButton) e.widget;
MenuItem mi = menuButton.getSelectedItem();
addMovableRing(mi.getText());
menuButton.setSelectedItem("Select One");
}
});
Button delete = new Button(createComposite, SWT.PUSH);
delete.setText("Delete");
delete.addListener(SWT.Selection, new Listener() {
#Override
public void handleEvent(Event event) {
deleteMovableRing();
}
});
}
/**
* Remove the ring of the selected movable ring row.
*/
private void deleteMovableRing() {
for (MovableRingRow row : movableRings) {
if (row.isSelected()) {
row.dispose();
movableRings.remove(row);
movableRingsComposite.layout(true);
getShell().pack();
if (!movableRings.isEmpty()) {
movableRings.iterator().next().selectRow(true);
}
break;
}
}
}
I want to get the control the mouse hovers over which normally is done by Display#getCursorControl. However when one control in the hierarchy is disabled, this method doesn't work any longer:
Example:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(400, 300);
shell.setLayout(new GridLayout(2, false));
final Label mouseControl = new Label(shell, SWT.BORDER);
mouseControl.setLayoutData(GridDataFactory.fillDefaults().span(2, 1).grab(true, true).create());
display.addFilter(SWT.MouseMove,
e -> mouseControl.setText("" + e.display.getCursorControl()));
final Group enabledGroup = new Group(shell, SWT.NONE);
enabledGroup.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
enabledGroup.setText("Enabled Group");
createControls(enabledGroup);
final Group disabledGroup = new Group(shell, SWT.NONE);
disabledGroup.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
disabledGroup.setText("Disabled Group");
disabledGroup.setEnabled(false);
createControls(disabledGroup);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
private static void createControls(Composite parent) {
parent.setLayout(new GridLayout());
final Label label = new Label(parent, SWT.NONE);
label.setText("Label");
final Text text = new Text(parent, SWT.BORDER);
text.setText("Text");
}
Hold the mouse over the left label and then over the right one. The control is only displayed for an enabled parent, else the shell is displayed.
How do I get the control below the mouse pointer? Do I have to implement this functionality myself? Are there any methods that can help me or do I have to calculate the bounds of each control inside the tree and check if it is on the mouse position?
I can't see anything in Display that would help.
The following will search the children of a Shell for a control containing the cursor and works with disabled controls:
static Control findCursorinShellChildren(final Shell shell)
{
return findLocationInCompositeChildren(shell, shell.getDisplay().getCursorLocation());
}
static Control findLocationInCompositeChildren(final Composite composite, final Point displayLoc)
{
final var compositeRelativeLoc = composite.toControl(displayLoc);
for (final var child : composite.getChildren())
{
if (child.getBounds().contains(compositeRelativeLoc))
{
if (child instanceof Composite)
{
final var containedControl = findLocationInCompositeChildren((Composite)child, displayLoc);
return containedControl != null ? containedControl : child;
}
return child;
}
}
return null;
}
I imagine this is going to be significantly slower than Display.getCursorControl
I am using Java's SWT toolkit to create a GUI with text field inputs. These input fields require numerical input and have units assigned to them. I'm trying to create a fancy way to integrate units within the field as a fixed suffix to the text, such that the user can only edit the numerical part. I'd also like for the suffix to be greyed out so the user knows it is disabled - something like the following:
While searching, I saw some solutions with a mask formatter from Swing that might do the trick, but I'm sort of hoping there might be something default with SWT. Any suggestions on how to make this work?
The field is part of a a matrix, so I can't simply add the units to a header label. I suppose I could create another column after the text field that could provide units as a label, but I'm going for something more intuitive and aesthetic.
Any suggestions?
One option would be to group Text and Label widgets in the same composite, and set the text on the Label to the desired suffix:
The area to the left of the suffix is the single-line text field, which can be edited, and the suffix is a disabled Label.
public class TextWithSuffixExample {
public class TextWithSuffix {
public TextWithSuffix(final Composite parent) {
// The border gives the appearance of a single component
final Composite baseComposite = new Composite(parent, SWT.BORDER);
baseComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
final GridLayout baseCompositeGridLayout = new GridLayout(2, false);
baseCompositeGridLayout.marginHeight = 0;
baseCompositeGridLayout.marginWidth = 0;
baseComposite.setLayout(baseCompositeGridLayout);
// You can set the background color and force it on
// the children (the Text and Label objects) to add
// to the illusion of a single component
baseComposite.setBackground(new Color(parent.getDisplay(), new RGB(255, 255, 255)));
baseComposite.setBackgroundMode(SWT.INHERIT_FORCE);
final Text text = new Text(baseComposite, SWT.SINGLE | SWT.RIGHT);
text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final Label label = new Label(baseComposite, SWT.NONE);
label.setEnabled(false);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true));
label.setText("kg/m^3");
}
}
final Display display;
final Shell shell;
public TextWithSuffixExample() {
display = new Display();
shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
new TextWithSuffix(shell);
}
public void run() {
shell.setSize(200, 100);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
public static void main(final String[] args) {
new TextWithSuffixExample().run();
}
}
I am having an issue trying to do what seemed to be an easy task.
Coding an UI in java/swt, I'm trying to get the text of a button display on two lines (wrap the string passed to the button), but I can't manage to do so with the carriage return in the string, nor with the SWT.WRAP style of the button.
Here is a sample of my code :
Button myButton = new Button(compoCentre, SWT.WRAP);
myButton.setBounds(40, 200, 240, 40);
myButton.setText("A long text, but not so long, just enough);
However, this results in the text displaying on one single line, hiding the part not fitting the size of the button.
Any ideas / workaround ?
Thank you for your time.
Check out below code :
public class Sample {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
Composite comp = new Composite(shell, SWT.NONE);
comp.setLayout(new GridLayout(1, false));
comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Button testButton = new Button(comp, SWT.PUSH | SWT.WRAP);
testButton.setText("A long text, but not so long, just enough");
final GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
layoutData.widthHint = 100;
testButton.setLayoutData(layoutData);
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
Output on Windows 10:
I am looking for a method to add a kind of watermark to a SWT CTabFolder.
My goal is that the tab folder does not look as "boring" if there are no tabs present.
I am aware of the setBackgroundImage method of CTabFolder. Unfortunately, this seems to be non adjustable and can only display an image in "tiled" format.
Do you know of any way to add a centered image to an empty tab folder?
You'll have to add your own Listeners for SWT.Paint, and SWT.Resize. Then draw your Image on the GC. Here is an example:
public static void main(String[] args)
{
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
final Image image = new Image(null, "info.png");
final CTabFolder folder = new CTabFolder(shell, SWT.TOP);
folder.addListener(SWT.Paint, new Listener()
{
#Override
public void handleEvent(Event event)
{
if (image.isDisposed())
return;
Rectangle parentSize = folder.getBounds();
int tabHeight = folder.getTabHeight();
Rectangle imageSize = image.getBounds();
event.gc.drawImage(image, (parentSize.width - imageSize.width) / 2, (parentSize.height - imageSize.height + tabHeight) / 2);
}
});
folder.addListener(SWT.Resize, new Listener()
{
#Override
public void handleEvent(Event event)
{
folder.redraw();
}
});
CTabItem item = new CTabItem(folder, SWT.CLOSE);
item.setText("TEST");
Composite content = new Composite(folder, SWT.NONE);
content.setLayout(new FillLayout());
new Label(content, SWT.NONE).setText("bla");
item.setControl(content);
shell.pack();
shell.setSize(400, 200);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
display.dispose();
image.dispose();
}
Looks like this when you have a CTabItem:
And like this when you close the item: