For my plugin, I try to get the active Eclipse dialog with these lines:
String shellTitle = Display.getCurrent().getActiveShell().getTitle();
System.out.println("Opened dialog: " + shellTitle);
If e.g. I open the search dialog, these lines print me
Opened dialog: Search
in my console. But I would also want to print the keyword in the search field, for example
Opened dialog: Search (with the search word 'ChatSession')
I have read the API reference and there, I just can found the getTitle() and some other methods for getting bounds and so on.
Is my idea realizable? And if not, is it realizable with these so-called extension points? I have never used them but heard of them.
Mistakes in your question:
You are calling getTitle() method on Shell array object. It is wrong.
You are mixing dialog and Shell
Assuming you are talking about Shell. You can use the below code to get the controls on active Shell.
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class ShellControlsGetting {
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
Button button = new Button(shell, SWT.PUSH);
button.setText("Open 3 Shells");
final Shell[] shells = new Shell[3];
button.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent e) {
for (int i = 0; i < 3; i++) {
shells[i] = new Shell(shell);
shells[i].setText("Shell" + (i + 1));
shells[i].setLayout(new FillLayout());
shells[i].setSize(250, 50);
shells[i].setLocation(100, 200 + (i + 1) * 100);
Label label = new Label(shells[i], SWT.LEFT);
label.setText("Search Box" + (i + 1));
Text search = new Text(shells[i], SWT.SINGLE | SWT.BORDER);
search.setText("search key" + (i + 1));
shells[i].open();
}
Shell currentActiveShell = Display.getCurrent().getActiveShell();
String shellTitle = currentActiveShell.getText();
Control[] children = currentActiveShell.getChildren();
for (int i = 0; i < children.length; i++) {
Control child = children[i];
if (child instanceof Text) {
System.out.println("Opened dialog: " + shellTitle + "(with the search word '" + ((Text)child).getText()
+ "')");
}
}
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
If this not answers you question then edit your post add some code and clarify what exactly you are expecting.
Related
At present all my Java GUI applications have SWT.SWT as their window class. I would like for some of them to be linked as sub-windows in menu applications such as Cairo-Dock. This is the third column of the out put from wmctrl -lx.
I have tried using the Display.setAppName() method in an attempt to set this name. Neither Display.setAppName or display.SetAppname will change the app class from SWT.SWT to the class name I'm tring to set.
When I use the lower case display.setAppName it produces this warning in the Eclipse IDE:
Description Resource Path Location Type
The static method setAppName(String) from the type Display should be accessed in a static way WBTest.java /javaTools/src/javaTools line 31 Java Problem
Code Sample:
package javaTools;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.wb.swt.SWTResourceManager;
public class WBTest {
private Table table;
/**
* Launch the application.
* #param args
*/
public static void main(String[] args) {
try {
WBTest window = new WBTest();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
display.setAppName("myapplication");
Shell shell = new Shell();
shell.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLACK));
shell.setSize(560, 426);
shell.setText("SWT Application");
table = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
table.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
// table.setBounds(49, 21, 241, 158);
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableItem row = new TableItem(table, SWT.NONE);
row.setText("This is a test.");
shell.open();
// shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
My research shows how to do this in Python, which works:
#!/usr/bin/python
from gi.repository import Gtk
win = Gtk.Window()
win.connect("delete-event", Gtk.main_quit)
win.set_wmclass ("Hello World", "Hello World")
win.set_title ("Hello World")
win.show_all()
Gtk.main()
I'm trying to do the same thing with SWT/Java.
Is there something else I need to add to this function to make it work, or is there a differernt function that is specific to setting the application's class name?
I don't know whether to remove this question or provide the answer. I had worked on it since yesterday and was still trying lots of variations.
One finally works. Apparently, the line has to appear in the code before declaring the Display.
This works:
package javaTools;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.wb.swt.SWTResourceManager;
public class WBTest {
private Table table;
/**
* Launch the application.
* #param args
*/
public static void main(String[] args) {
try {
WBTest window = new WBTest();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display.setAppName("myapplication");
Display display = Display.getDefault();
Display.setAppName("myapplication");
Shell shell = new Shell();
shell.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLACK));
shell.setSize(560, 426);
shell.setText("SWT Application");
table = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
table.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
// table.setBounds(49, 21, 241, 158);
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableItem row = new TableItem(table, SWT.NONE);
row.setText("This is a test.");
shell.open();
// shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
I'm trying to dispose of columns and add new ones to a Nebula Grid, the data in the table won't change I just want to be able to change the columns used.
I am getting a bug where the Grid is throwing index out of bounds exceptions as it's iterating through a list of existing columns but using a value "endColumnIndex" to stop the loop, but the endColumnIndex value is bigger than the list of new columns.
I believe this is due to using Visual Range Support, and the value for the current on screen columns is not being updated as I am removing them.
I have written a class to reproduce this bug here, and am hoping someone has a workaround for this issue:
import org.eclipse.nebula.jface.gridviewer.GridTableViewer;
import org.eclipse.nebula.jface.gridviewer.GridViewerColumn;
import org.eclipse.nebula.widgets.grid.GridColumn;
import org.eclipse.nebula.widgets.grid.GridItem;
import org.eclipse.nebula.widgets.grid.GridVisibleRangeSupport;
import org.eclipse.nebula.widgets.grid.GridVisibleRangeSupport.RangeChangedEvent;
import org.eclipse.nebula.widgets.grid.GridVisibleRangeSupport.VisibleRangeChangedListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class GridRangeChangeBug {
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(800, 800);
shell.setLayout(new GridLayout(1, true));
Button go = new Button(shell, SWT.PUSH);
go.setText("Reproduce Bug");
final GridTableViewer viewer = new GridTableViewer(shell, SWT.H_SCROLL
| SWT.V_SCROLL | SWT.BORDER);
viewer.getGrid().setLayoutData(
new GridData(SWT.FILL, SWT.FILL, true, true));
viewer.getGrid().setHeaderVisible(true);
GridVisibleRangeSupport rangeSupport = GridVisibleRangeSupport.createFor(viewer.getGrid());
rangeSupport.addRangeChangeListener(new VisibleRangeChangedListener() {
#Override
public void rangeChanged(RangeChangedEvent event) {
}
});
for (int i = 0; i < 100; i++) {
GridViewerColumn col = new GridViewerColumn(viewer, SWT.NONE);
col.getColumn().setWidth(30);
col.getColumn().setText("" + i);
}
go.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
for (GridColumn c : viewer.getGrid().getColumns()) {
c.dispose();
}
for (int i = 0; i < 10; i++) {
GridViewerColumn col = new GridViewerColumn(viewer,
SWT.NONE);
col.getColumn().setWidth(30);
col.getColumn().setText("" + i);
}
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
So I have a problem, when I add an image to any column of a JFace table the first column also behaves like it has an image in and the text is indented by the size of that image.
Here's a screenshot illustrating my point with the code needed to produce it. Is there anyway to stop this from happening because it's really getting on my wick?
Regards,
Glen x
package widgets;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class ComponentTest {
private static Image image;
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, true));
TableViewer viewer1 = getViewer(shell, true);
TableViewer viewer2 = getViewer(shell, false);
List<String> rows = new ArrayList<String>();
rows.add("Row 1");
rows.add("Row 2");
viewer1.setInput(rows);
viewer2.setInput(rows);
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
private static TableViewer getViewer(final Shell shell, boolean addImage) {
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION
| SWT.H_SCROLL | SWT.V_SCROLL | SWT.NONE);
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.getTable().setLayoutData(
new GridData(SWT.FILL, SWT.FILL, true, true));
TableViewerColumn col = new TableViewerColumn(viewer, SWT.NONE);
col.getColumn().setWidth(100);
col.getColumn().setText("Text Column");
col.setLabelProvider(new StyledCellLabelProvider() {
#Override
public void update(ViewerCell cell) {
cell.setText((String) cell.getElement());
}
});
col = new TableViewerColumn(viewer, SWT.NONE);
col.getColumn().setWidth(100);
col.getColumn().setText("Second Text Column");
col.setLabelProvider(new StyledCellLabelProvider() {
#Override
public void update(ViewerCell cell) {
cell.setText((String) cell.getElement());
}
});
if (addImage) {
col = new TableViewerColumn(viewer, SWT.NONE);
col.getColumn().setWidth(100);
col.getColumn().setText("Image Column");
col.setLabelProvider(new StyledCellLabelProvider() {
#Override
public void update(ViewerCell cell) {
cell.setImage(getImage(shell.getDisplay()));
}
});
}
viewer.getTable().setHeaderVisible(true);
return viewer;
}
// make a little green square
private static Image getImage(Display display) {
if (image == null) {
PaletteData palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
ImageData imageData = new ImageData(16, 16, 24, palette);
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
imageData.setPixel(x, y, 0xFF00);
}
}
;
image = new Image(display, imageData);
}
return image;
}
}
That is a quite annoying bug when using Windows. You can use a dirty fix by skipping the first column (not using it) and setting its width to zero.
As far as I remember correctly, this will introduce some minor glitches when using MacOS.
I had the same problem and worked around it by using a StyledCellLabelProvider with owner draw and overriding the paint method to paint the image. The point is that you should not set the image of the viewer cell because this will give the bug. I posted example code to the Eclipse bug report.
TableItem line:301: I see a problem with SWT code here.
if (code == 0) return new RECT ();
if (!getImage) {
RECT iconRect = new RECT ();
iconRect.left = OS.LVIR_ICON;
parent.ignoreCustomDraw = true;
code = OS.SendMessage (hwnd, OS. LVM_GETITEMRECT, row, iconRect);
parent.ignoreCustomDraw = false;
if (code != 0) rect.left = iconRect.right;
//****problem
code = OS.SendMessage (hwnd, OS. LVM_GETITEMRECT, row, iconRect);
for the first table viewer with image, here code is 1 that why drawing text started iconRect right coordinate.
for the second table viwer with no image, code is zero. so it always starts from the actual bounds.
If you are really keen on fix it at CellStyleStyledCellLabelProvider i would suggest you to override paint method there.
I create a GC on the display, and then I do some drawing. My question is how do I un-draw?
The code looks like this:
final GC gc = new GC(display);
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
gc.setLineWidth(5);
gc.drawRectangle(rectangle);
gc.dispose();
Context:
I need to let users select a window from other applications. The behavior I expect can be seen here: http://tools.tortoisesvn.net/SendMessage.html Instead, All my screen is filled with red rectangles.
It is OK for me even if it is a Windows-only solution.
EDIT: sorry, red garbage remains even after I close my application.
EDIT2: The working example:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.addListener(SWT.MouseMove, new Listener() {
#Override
public void handleEvent(Event event) {
final Point displayPoint = display.map(shell, null, event.x, event.y);
final POINT point = new POINT();
point.x = displayPoint.x;
point.y = displayPoint.y;
final int windowHandle = OS.WindowFromPoint(point);
if (windowHandle != 0 && windowHandle != shell.handle) {
RECT rect = new RECT();
if (OS.GetWindowRect(windowHandle, rect)) {
Rectangle rectangle = new Rectangle(rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top);
final GC gc = new GC(display);
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
gc.setLineWidth(5);
gc.drawRectangle(rectangle);
gc.dispose();
}
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
To use it, start a mouse drag from the shell (not the title bar) and hover it over an application that uses real windows controls (not swing, QT, XUL). A good example of target application is Total Commander. You will see that the screen becomes full of red rectangles. Ideally I would like to have only one red rectangle visible.
I know I could make a new shell with regions that will simulate the red rectangle, but if the mouse jumps over that, I'm stuck.
I make some code. It's not perfect solution, cause after many tries I'm not able to make transparency everything except the "window" border, so I'm just making the whole shell (which covers the "window" area) partially transparent (and it makes nice effect though).
Here's the code
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.internal.win32.POINT;
import org.eclipse.swt.internal.win32.RECT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
public class ShellBorder {
private Display display = new Display();
private Shell shell = new Shell(display);
private RECT currRect = null;
private Shell paintShell = null;
public ShellBorder() {
shell.addListener(SWT.MouseUp, new Listener() {
#Override
public void handleEvent(Event event) {
paintShell.dispose();
// do whatever you need
// ...
currRect = null;
}
});
shell.addListener(SWT.MouseMove, new Listener() {
#Override
public void handleEvent(Event event) {
final Point displayPoint = display.map(shell, null, event.x, event.y);
final POINT point = new POINT();
point.x = displayPoint.x;
point.y = displayPoint.y;
if(currRect == null) {
getWindowAndDrawBorder(point);
} else {
// cursor is outside the current rectangle
if (point.x < currRect.left || point.x > currRect.right || point.y < currRect.top || point.y > currRect.bottom) {
currRect = null;
paintShell.dispose();
getWindowAndDrawBorder(point);
}
}
}
private void getWindowAndDrawBorder(POINT point) {
long windowHandle = OS.WindowFromPoint(point);
if (windowHandle != 0 && windowHandle != shell.handle) {
RECT rect = new RECT();
if (OS.GetWindowRect(windowHandle, rect)) {
currRect = rect;
paintShell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP);
paintShell.setLocation(currRect.left, currRect.top);
paintShell.setSize(currRect.right - currRect.left, currRect.bottom - currRect.top);
paintShell.setLayout(new FillLayout());
paintShell.setAlpha(50);
Canvas canvas = new Canvas(paintShell, SWT.NO_BACKGROUND);
canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
GC gc = e.gc;
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
gc.setLineWidth(5);
gc.drawRectangle(new Rectangle(0, 0, paintShell.getSize().x, paintShell.getSize().y));
}
});
paintShell.open();
}
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
public static void main(String[] args) {
new ShellBorder();
}
}
To do this, you must draw on a Shell that covers the complete display. When the Shell is disposed, the drawn rectangles are removed.
I don't know how to find the window under the cursor though...
In my first answer I assumed that you wanted to test for a window of other applications on the Desktop. As that is not the case, you should have a look at my answer to How to draw over child elements of a Composite in SWT? which automatically handles redraw of the relevant parts when a rectangle should be removed again...
In a Java SWT shell window, how do I set its inner size than its whole window frame size?
For instance, if I use shell.setSize(300, 250) this would make the whole window appearing as exactly 300x250. This 300x250 includes the size of the window frame.
How can I set the inner size, that is the content display region of the shell window to 300x250 instead? That's this 300x250 excludes the width of the window frame.
I tried to minus some offset values but the thing is different Operating Systems have different window frame sizes. So having a constant offset would not be accurate.
Thanks.
From your question what I understood is that you want to set the dimension of the Client Area. And in SWT lingo it is defined as a rectangle which describes the area of the receiver which is capable of displaying data (that is, not covered by the "trimmings").
You cannot directly set the dimension of Client Area because there is no API for it. Although you can achieve this by a little hack. In the below sample code I want my client area to be 300 by 250. To achieve this I have used the shell.addShellListener() event listener. When the shell is completely active (see the public void shellActivated(ShellEvent e)) then I calculate the different margins and again set the size of my shell. The calculation and resetting of the shell size gives me the desired shell size.
>>Code:
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
public class MenuTest {
public static void main (String [] args)
{
Display display = new Display ();
final Shell shell = new Shell (display);
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
layout.numColumns = 1;
shell.setLayout(layout);
shell.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,true));
final Menu bar = new Menu (shell, SWT.BAR);
shell.setMenuBar (bar);
shell.addShellListener(new ShellListener() {
public void shellIconified(ShellEvent e) {
}
public void shellDeiconified(ShellEvent e) {
}
public void shellDeactivated(ShellEvent e) {
}
public void shellClosed(ShellEvent e) {
System.out.println("Client Area: " + shell.getClientArea());
}
public void shellActivated(ShellEvent e) {
int frameX = shell.getSize().x - shell.getClientArea().width;
int frameY = shell.getSize().y - shell.getClientArea().height;
shell.setSize(300 + frameX, 250 + frameY);
}
});
shell.open ();
while (!shell.isDisposed()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
}
If I get you right you should set the size of the inner component to the needed size and use the method pack() (of the frame).
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
public class SWTClientAreaTest
{
Display display;
Shell shell;
final int DESIRED_CLIENT_AREA_WIDTH = 300;
final int DESIRED_CLIENT_AREA_HEIGHT = 200;
void render()
{
display = Display.getDefault();
shell = new Shell(display, SWT.SHELL_TRIM | SWT.CENTER);
Point shell_size = shell.getSize();
Rectangle client_area = shell.getClientArea();
shell.setSize
(
DESIRED_CLIENT_AREA_WIDTH + shell_size.x - client_area.width,
DESIRED_CLIENT_AREA_HEIGHT + shell_size.y - client_area.height
);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
display.dispose();
}
public static void main(String[] args)
{
SWTClientAreaTest appl = new SWTClientAreaTest();
appl.render();
}
}
Use computeTrim to calculate the bounds that are necessary to display a given client area. The method returns a rectangle that describes the bounds that are needed to provide room for the client area specified in the arguments.
In this example the size of the shell is set so that it is capable to display a client area of 100 x 200 (width x height):
Rectangle bounds = shell.computeTrim(0, 0, 100, 200);
shell.setSize(bounds.width, bounds.height);
This article describes the terms used by SWT for widget dimensions:
https://www.eclipse.org/articles/Article-Understanding-Layouts/Understanding-Layouts.htm