SWT: Table with copy/paste functions - java

This maybe a really silly question but I just could not find the answer anywhere, is there any way for the user to be able to highlight rows in an SWT Table and either ctrl+c or right-click+c to copy the values?
I would specifically like to be able to copy into an excel sheet.
This is how I create the table,
Table aTable = new Table(parent, SWT.SINGLE | SWT.BORDER
| SWT.FULL_SELECTION);
aTable.setHeaderVisible(true);
aTable.setLinesVisible(true);
aTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
I have seen information about this using a JTable but nothing with an SWT. If JTable is my only option, then what would be the dis/advantages of using either?

You can easily code it.
Add a key listener to your table and listen for Ctrl+C keys. When Ctrl+C is hit, get the selection from the table, extract text from each of the TableItems and form a tab-separated-fields/newline-separated-rows String containing your data. Then just put it into clipboard (see org.eclipse.swt.dnd.Clipboard#setContents, use TextTransfer data type).
That is it - your result will be pasteable into Excel.

The accepted answer is good, but since developers prefer code snippets over text I'd answer the question this way:
aTable.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.stateMask == SWT.CTRL && (e.keyCode == 'c' || e.keyCode == 'C')) {
Clipboard clipboard = new Clipboard(Display.getDefault());
clipboard.setContents(new Object[] { getTextFromSelectedRows() }, new Transfer[] { TextTransfer.getInstance() });
clipboard.dispose();
}
}
});
Then just implement a getTextFromSelectedRows()-Method that - based on the table selection - returns the String that should be added to the clipboard.

Related

Text editor: if certain key pressed want to cancel key event and give new functionality

I have a JEditorPane with text/html type. When an enter key is pressed with the editor focused, I want to do some checks about the state of the document and then override the enter key default functionality if conditions are met.
I believe this can be done with a KeyListener listening for a key, then consume the event if conditions are met to cancel the key making any change to the input. Testing this idea I'm just trying to consume the key event when any key is pressed. The key listener below is printing output when i press any key, but the characters are still getting inserted into the editor pane.
How can I stop the characters getting inserted altogether?
Thanks for your help.
String content = "";
String type = "text/html";
editor = new JEditorPane(type, content);
editor.setEditorKit(new HTMLEditorKit());
editor.setEditable(true);
editor.setPreferredSize(new Dimension(500, 500));
panel.add(editor);
editor.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e){
System.out.println("huh?");
e.consume();
}
});
EDIT----------
Removed key listener, and added instead
Action enter = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("enter!");
if ( condition == true ){
// default enter key behaviour
}
}
};
editor.getActionMap().put("insert-break", enter);
Ok I got rid of the KeyListener and added this, which prevents the default enter-key functionality which is great. But how would i insert a break (the default enter key behaviour) if my if clause is true?
I can't figure out how to trigger that on the editor programmatically.
You are over thinking it.
We save the Action because we want to invoke the actionPerformed(...) method of the Action.
Assuming the original Action is stored in the variable "original" the code would be:
if (condition == true)
original.actionPerformed( e );

Menu accelerator SWT.ALT+SWT.ARROW is not triggered

I'm using SWT 4.4.2 (win32) to build the Graphical User Interface for a simple mp3 player application.
In a SWT tree I show some folders and files to play.
Now I want to change the volume of a playing file by clicking a menu item and also by pressing ALT+ARROW_UP and ALT+ARROW_DOWN.
So I have these components:
tree = new Tree(shell, SWT.BORDER | SWT.FULL_SELECTION | SWT.SINGLE | SWT.V_SCROLL);
tree.setLinesVisible(true);
tree.setLocation(10, 10);
tree.setSize(240, 440);
audioLouderMenu = new MenuItem(audioVolumeMenu, SWT.PUSH);
audioLouderMenu.setAccelerator(SWT.ALT | SWT.ARROW_UP);
audioLouderMenu.setText("Louder");
audioLouderMenu.addListener(SWT.Selection, audioVolumeMenuHandler);
audioQuieterMenu = new MenuItem(audioVolumeMenu, SWT.PUSH);
audioQuieterMenu.setAccelerator(SWT.ALT | SWT.ARROW_DOWN);
audioQuieterMenu.setText("Quieter");
audioQuieterMenu.addListener(SWT.Selection, audioVolumeMenuHandler);
The problem is that if the tree view has the focus and I press ALT+ARROW_DOWN then another entry in the tree will be selected and not the shortcut of the menu item is triggered.
Is this a bug of SWT and how can I solve the problem?
I know that I can define another shortcut but I think that it should also be possible to use ALT+ARROW_UP/DOWN...
This isn't a bug but a (platform-dependant) keyboard navigation feature of the tree.
I recommend to choose a different shortcut for the audio volume in order to not confuse your users. If you nonetheless want to use ALT+ARROW_DOWN, you can try to prevent the tree from consuming this key combination and thus give the menu a chance to consume it:
tree.addListener( SWT.KeyDown, new Listener() {
#Override
public void handleEvent( Event event ) {
if( event.keyCode == SWT.ARROW_DOWN && ( event.stateMask & SWT.MOD3 ) != 0 ) {
event.doit = false;
}
}
} );

How to make SWT Table in CheckboxTableViewer scrollable?

I couldn't find any answers for this special case (using CheckboxTableViewer), so I hope it's not a duplicate.
I have the following createPartControl() in an Eclipse view (3.x).
I'm trying to display two buttons and a checkable table in a GridLayout, as below
-------------------
| Button | Button |
-------------------
| Table |
-------------------
Nothing spectacular. Everything is displayed fine so far. My table is embedded within a CheckboxTableViewer, has a single column and sometimes the content (String) is longer than the column width. So I'm trying to make the Table (got via viewer.getTable(), not explicitly constructed!) scrollable to make all content available. This doesn't work and I cannot understand why.
I have played around with SWT style bits (SWT.H_SCROLL, SWT.V_SCROLL), I've tried a ScrollableComponent, but to no avail. I couldn't get the ScrolledComponent to work because I'm not constructing my table explicitly, and thus couldn't setContents() properly.
Below is the gist of my createPartControl().
public void createPartControl(Composite parent) {
parent.setLayout(new GridLayout(2, false));
addSelectionButtons(parent); // Works
myTableViewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER);
myTableViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
Table myTable = (Table) myTableViewer.getControl();
TableLayout tableLayout = new TableLayout();
tableLayout.addColumnData(new ColumnWeightData(100, 50, true));
myTable.setLayout(tableLayout);
myTableViewer.setContentProvider(new MyContentProvider());
TableViewerColumn viewerCol = new TableViewerColumn(myTableViewer, SWT.LEFT);
TableColumn col = viewerCol.getColumn();
col.setText("My column");
viewerCol.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return text; // Dummy var
}
});
myTableViewer.setInput(getInput()); // Gets model
myTableViewer.getTable().setHeaderVisible(true);
myTableViewer.getTable().setLinesVisible(true);
}
I know this is borderline "give me teh codez", but I really cannot find the issue with this setup.
I've managed to solve this issue by going back to square one and re-implementing in the most generic fashion I could find documented. I.e.:
I've added a proper LabelProvider (and got rid of the ColumnLabelProvider),
set a simple GridData layout data object to the table (and otherwise haven't messed with it),
and simplified the TableColumn section a lot (despite having only one column in the table, I still need to declare a TableColumn to be able to set a column heading). Note: The TableColumn must be pack()ed, otherwise the content doesn't show. From the TableColumn API: "Causes the receiver to be resized to its preferred size."
Simple and working.
public void createPartControl(Composite parent) {
parent.setLayout(new GridLayout(1, true));
addSelectionButtons(parent); // Adds select/deselect all buttons
myTableViewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
myTableViewer.getTable().setLayoutData(new GridData(GridData.FILL_BOTH));
myTableViewer.setContentProvider(new MyContentProvider());
myTableViewer.setLabelProvider(new MyLabelProvider());
myTableViewer.setInput(getInput()); // Gets model
TableColumn column = new TableColumn(myTableViewer.getTable(), SWT.FILL);
column.setText("My column");
column.pack();
myTableViewer.getTable().setHeaderVisible(true);
myTableViewer.getTable().setLinesVisible(true);
}

Trying to add a menu to a TableViewer's header row (titles row)

I am trying to add an action to a menu to the header (titles) of a TableViewer.
This is the code that I am using now:
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL
| SWT.FULL_SELECTION | SWT.BORDER);
//...
MenuManager manager = new MenuManager();
viewer.getControl().setMenu(manager.createContextMenu(viewer.getControl()));
manager.add(new Action("MENU ITEM TEXT") {
#Override
public void run() {
// get the current selection of the tableviewer
IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
// do something
if (selection.getFirstElement() instanceof MyObject)
return;
System.out.println("OK: "+selection.getFirstElement().getClass().getName());
}
});
And this is how it looks:
The problem is that the menu gets added to the entire TableViewer, not only to the header row.
Because for the other rows I will need to use a different menu.
I have tryied to find a way of adding the action only to the top row (the titles row), but with no success so far.
So how can I add the menu only for the header?
You add a MouseListener to the table, and you check for the following things:
Clicked button is mouse right-click.
The pointer of the event is located within the bounds of your table item (i.e. your first TableItem - you will use table.getItem(Point)).
If these conditions are met, you open the menu at mouse location.
Actually, here's a snippet of how this can be done.

How to disable horizontal scroll bars in the swt table?

To disable vertical scroll bar i used the following syntax
table.getHorizontalBar().setEnabled(false);
But it is not working. It is ruining my application ui. How can i disable it?
Use option SWT.NO_SCROLL and SWT.V_SCROLL while constructing the table as following:
new Table (shell, SWT.NO_SCROLL | SWT.V_SCROLL);
You can't prevent the Table from showing its scrollbars if it wants to. However, if you give the table the space it requires, it should not have to display any scrollbars.
Note:
You can simply use SWT.NO_SCROLL in the constructor but if you want to update it later it won't be possible.
ScrollBar / Table position synchronization in Java SWT turorial
Probably, if you you want to disable a scrollbar, it means you want to synchronize the content with something else. Here is example how to do it with two tables, where content of main table called tableExcel is mirrored in extra table called tableRow (please, be aware the code may not be perfect, because I am beginner):
*Note: the code is not complete & shows only key things (beginners, please use Window Builder and then edit/add code):
1) As ankur.trapasiya mentioned, do this:
tableRow = new Table(sashFormExcel, SWT.BORDER | SWT.VIRTUAL | SWT.NO_SCROLL);
2) And (SWT.VIRTUAL will be required to do the workaround, and to load tables fast, it will load what you see & where you scroll)
tableExcel = new Table(sashFormExcel, SWT.BORDER | SWT.VIRTUAL);
3) Because I used sash-form for better navigation, insert this above point 1:
SashForm sashFormExcel = new SashForm(sashForm_Main, SWT.NONE);
4) Then implement this (after point 3):
synchronizer synchronize = new synchronizer(tableRow, tableExcel); tableExcel.getVerticalBar().addSelectionListener(synchronize);
5) Add this class (will synchronize the tables content position):
class synchronizer implements SelectionListener
{
Table t1, t2;
public synchronizer(Table tableRow, Table tableMain)
{
t1 = tableRow;
t2 = tableMain;
}
#Override
public void widgetSelected(SelectionEvent e) {
t1.setTopIndex(t2.getTopIndex());
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
}
6) And after point 2, add this (it will make to load main table fast, and will also synchronize your table where scroll bar is disabled):
tableExcel.addListener( SWT.SetData, new Listener() {
public void handleEvent( Event event ) {
TableItem item = (TableItem) event.item;
int index = event.index;
int page = index / PAGE_SIZE;
int start = page * PAGE_SIZE;
int end = start + PAGE_SIZE;
end = Math.min (end, virtTableExcel.size());
for (int i = start; i < end; i++) {
item = tableExcel.getItem (i);
item.setText (virtTableExcel.get(i));
tableRow.getItem(i).setText(Integer.toString(i));
}
}
});
And on top of code, add this:
private static Table tableExcel;
ArrayList<String[]> virtTableExcel = new ArrayList<String[]>();
final int PAGE_SIZE = 64;
private Table tableRow;
As it is mentioned in point 7, you take data from array list virtTableExcel, but to trigger point 6, use this (somewhere in code, after you generated virtTableExcel with data), where rowMax is integer which is equal to virtTableExcel.size(); :tableExcel.setItemCount(rowMax);
tableRow.setItemCount(rowMax);
Please, don't blame me for code, I used it from my application. But, all these bits might be useful for other beginners.
What work for me:
When declaring the TableViewer I do this:
this.viewer.getTable().getHorizontalBar().setVisible(false);
this.viewer.getTable().pack();
this.viewer.getTable().getParent().layout();
this.viewer.getTable().getParent().getParent().layout();
and when i am changing the viewer input i also call the three last lines.
I got this solution from: https://bugs.eclipse.org/bugs/show_bug.cgi?id=304128
Try
table.getHorizontalBar().setVisible(false);
Is't simple:
leftTable.getVerticalBar().addListener(SWT.Selection, event -> {
rightTableViewer.getTable().setTopIndex(leftTableViewer.getTable().getTopIndex());
});
and vice versa.

Categories

Resources