Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Table & Tableviewer column pack(the pack is based on the column header)
Table & Tableviewer column pack [message #634359] Thu, 21 October 2010 12:00 Go to next message
Luca Ferrari is currently offline Luca FerrariFriend
Messages: 159
Registered: November 2009
Senior Member
Hi,
I've got a table viewer created and initialized with headers as follows:

       TableViewer viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.VIRTUAL | SWT.FULL_SELECTION);

       List<String> labels = ....


       for (int i = 0; i < labels.length; i++) {
	    TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
	    column.getColumn().setText(labels[i]);
	    column.getColumn().setResizable(true);
	    column.getColumn().setMoveable(true);
	}


	Table table = viewer.getTable();
	table.setHeaderVisible(true);
	table.setLinesVisible(true);


after this the table is created an the columns are automatically packed to the header string length. After an input changed, I call the pack on each column in order to adjust the column width to the right size depending on the data the table is displaying:

        Table table = viewer.getTable();
	
	
	for( int i = 0; i < table.getColumnCount(); i++ )
	    table.getColumn(i).pack();


The problem is that nothing change, I mean the table remains with the column at a fixed size, so that the user cannot display text longer than the column header.
Am I doing something wrong? What is the way to resize the columns width in order to make long text appearing?
Re: Table & Tableviewer column pack [message #634584 is a reply to message #634359] Fri, 22 October 2010 10:54 Go to previous messageGo to next message
Luca Ferrari is currently offline Luca FerrariFriend
Messages: 159
Registered: November 2009
Senior Member
Does nobody have an idea on how to auto pack table columns? Should I compute manually the size of the fonts?
Re: Table & Tableviewer column pack [message #635074 is a reply to message #634584] Mon, 25 October 2010 15:03 Go to previous messageGo to next message
Grant Gayed is currently offline Grant GayedFriend
Messages: 2151
Registered: July 2009
Senior Member
At the swt level calling TableColumn.pack() should set a column's width to
the maximum width of its header and items. Since you're working at the
jface level, maybe it's doing something to "help" you? For instance, you
say that when your TableViewer is initially shown, all columns start with an
appropriate width. Are you doing this (setting their widths or pack()ing
them), or is it "just happening" (eg.- via a TableColumnLayout, etc.)? If
it's just happening then TableViewer may be managing your column widths for
you, and therefore could be overwriting the width changes you're trying to
make with TableColumn.pack().

The other possibility is that if you're pack()ing the columns immediately
after changing the input object, maybe the new values from the input object
have not been put into the Table yet, in which case the pack()s would still
be using the old column text values? My guess is that this is not the case,
unless TableViewer populates the underlying Table asynchronously for some
reason, but is just a thought.

HTH,
Grant


"Luca Ferrari" <fluca1978@infinito.it> wrote in message
news:i9rqb9$c6$1@news.eclipse.org...
> Does nobody have an idea on how to auto pack table columns? Should I
> compute manually the size of the fonts?
Re: Table & Tableviewer column pack [message #635357 is a reply to message #635074] Tue, 26 October 2010 14:52 Go to previous messageGo to next message
Luca Ferrari is currently offline Luca FerrariFriend
Messages: 159
Registered: November 2009
Senior Member
I discovered it is the second case you mention: when I call pack() the contentprovider has not yet filled the whole table.
At the moment the system works as follows:
- the content provider starts a thread that creates the objects to insert into the table
- when the thread has all the objects it calls the contentprovider.inputChanged()
- inputChanged fills (thru an asyncExec) the table and performs both a viewer.refresh() and a pack() on each column.

The above does not work, so I put a random sleep into the thread after the call to the inputchanged(), and then I call a pack on each column and it works! So it is an async problem. I've tried to change the asyncExec of the inputChanged() method into a syncExec but it does not work.
Below you can find code snippets of the system:

public void inputChanged(final Viewer viewer, Object oldInput, final Object newInput) {
	PlatformUI.getWorkbench().getDisplay().asyncExec( new Runnable(){

	    @Override
	    public void run() {
		
		if( viewer.getControl().isDisposed() )
		    return;
		
               // insert elements into the view	
		
		// now refresh the view (this should be not necessary)
		viewer.refresh();
		
               // get the table of this viewer
      	       Table table = viewer.getTable();
	
	       // iterate on each column and pack it
 	       for( int i = 0; i < table.getColumnCount(); i++ )
	         table.getColumn(i).pack();
	    }
	   
	    
	});


and the thread, with the change to pack the columns is:

public synchronized void run() {
       List<T> loadedElements = // load elements

	this.contentProvider.inputChanged( this.viewer, loadedElements, loadedElements );
	
	try {
	    this.sleep(2000);
	    PlatformUI.getWorkbench().getDisplay().asyncExec( new Runnable(){

		    @Override
		    public void run() {
                          // here pack the columns as above
		    }
	    });
	    
	} catch (InterruptedException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}
	
	
    }



But the two asyncExec should be managed as equivalent. What am I doing wrong?
Re: Table & Tableviewer column pack [message #635491 is a reply to message #635357] Wed, 27 October 2010 05:24 Go to previous messageGo to next message
Daniel Krügler is currently offline Daniel KrüglerFriend
Messages: 853
Registered: July 2009
Senior Member
On 26.10.2010 16:52, Luca Ferrari wrote:
> I discovered it is the second case you mention: when I call pack() the
> contentprovider has not yet filled the whole table. At the moment the
> system works as follows:
> - the content provider starts a thread that creates the objects to
> insert into the table
> - when the thread has all the objects it calls the
> contentprovider.inputChanged()
> - inputChanged fills (thru an asyncExec) the table and performs both a
> viewer.refresh() and a pack() on each column.
>
> The above does not work, so I put a random sleep into the thread after
> the call to the inputchanged(), and then I call a pack on each column
> and it works! So it is an async problem. I've tried to change the
> asyncExec of the inputChanged() method into a syncExec but it does not
> work.
> Below you can find code snippets of the system:
>
>
> public void inputChanged(final Viewer viewer, Object oldInput, final
> Object newInput) {
> PlatformUI.getWorkbench().getDisplay().asyncExec( new Runnable(){
>
> @Override
> public void run() {
>
> if( viewer.getControl().isDisposed() )
> return;
>
> // insert elements into the view
>
> // now refresh the view (this should be not necessary)
> viewer.refresh();
>
> // get the table of this viewer
> Table table = viewer.getTable();
>
> // iterate on each column and pack it
> for( int i = 0; i < table.getColumnCount(); i++ )
> table.getColumn(i).pack();
> }
> });

Note that you are on the SWT newsgroup and your snippet is not useful
for anyone of us willing to help you to reproduce/solve your problem.

Please provide a fully working code snippet that does not require more
than SWT (jface would be OK as well, but then this question should
actually be presented in the RCP group). For examples of these snippets
see

http://www.eclipse.org/swt/snippets/

Greetings from Bremen,

Daniel Krügler
Re: Table & Tableviewer column pack [message #635630 is a reply to message #635357] Wed, 27 October 2010 14:41 Go to previous message
Grant Gayed is currently offline Grant GayedFriend
Messages: 2151
Registered: July 2009
Senior Member
It's hard to know what's happening in your case, I would have thought that
changing inputChanged()'s asyncExec() to syncExec() might have helped.

I found a jface snippet that's populating a TableViewer from a background
thread at
http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jface.s nippets/Eclipse%20JFace%20Snippets/org/eclipse/jface/snippet s/viewers/Snippet045TableViewerFillFromBackgroundThread.java ?revision=1.2&view=markup .
I trimmed it a bit and added some lines to pack() the columns when the input
changes and it seems to work, so maybe it will give you a hint. The
modified snippet follows.

import java.util.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableColumn;
public class Snippet045TableViewerFillFromBackgroundThreadMODIFIED {
private static String COUNTER = "1";
private class MyContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object inputElement) {
return ((List) inputElement).toArray();
}
public void dispose() {}
public void inputChanged(Viewer viewer, Object oldInput, Object
newInput) {}
}
public class MyModel {
public String counter;
public MyModel(String counter) {
this.counter = counter;
}
public String toString() {
return "Item " + this.counter;
}
}
public Snippet045TableViewerFillFromBackgroundThread(final Shell shell)
{
final TableViewer v = new TableViewer(shell, SWT.BORDER |
SWT.FULL_SELECTION);
v.setContentProvider(new MyContentProvider());
final TableColumn column1 = new TableColumn(v.getTable(), SWT.NONE);
column1.setText("Column 1");
final TableColumn column2 = new TableColumn(v.getTable(), SWT.NONE);
column2.setText("Column 2");
final ArrayList model = new ArrayList();
v.setInput(model);
v.setComparator(new ViewerComparator() {
public int compare(Viewer viewer, Object e1, Object e2) {
return 1;
}
});
v.getTable().setLinesVisible(true);
v.getTable().setHeaderVisible(true);
TimerTask task = new TimerTask() {
public void run() {
shell.getDisplay().syncExec(new Runnable() {
public void run() {
COUNTER += '0';
MyModel el = new MyModel(COUNTER);
v.add(el);
model.add(el);
column1.pack();
column2.pack();
}
});
}
};
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(task, 1000, 1000);
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
new Snippet045TableViewerFillFromBackgroundThreadMODIFIED(shell) ;
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
}

Grant


"Luca Ferrari" <fluca1978@infinito.it> wrote in message
news:ia6po3$9ed$1@news.eclipse.org...
>I discovered it is the second case you mention: when I call pack() the
>contentprovider has not yet filled the whole table. At the moment the
>system works as follows:
> - the content provider starts a thread that creates the objects to insert
> into the table
> - when the thread has all the objects it calls the
> contentprovider.inputChanged()
> - inputChanged fills (thru an asyncExec) the table and performs both a
> viewer.refresh() and a pack() on each column.
>
> The above does not work, so I put a random sleep into the thread after the
> call to the inputchanged(), and then I call a pack on each column and it
> works! So it is an async problem. I've tried to change the asyncExec of
> the inputChanged() method into a syncExec but it does not work.
> Below you can find code snippets of the system:
>
>
> public void inputChanged(final Viewer viewer, Object oldInput, final
> Object newInput) {
> PlatformUI.getWorkbench().getDisplay().asyncExec( new Runnable(){
>
> @Override
> public void run() {
>
> if( viewer.getControl().isDisposed() )
> return;
>
> // insert elements into the view
> // now refresh the view (this should be not necessary)
> viewer.refresh();
>
> // get the table of this viewer
> Table table = viewer.getTable();
>
> // iterate on each column and pack it
> for( int i = 0; i < table.getColumnCount(); i++ )
> table.getColumn(i).pack();
> }
> });
>
>
> and the thread, with the change to pack the columns is:
>
>
> public synchronized void run() {
> List<T> loadedElements = // load elements
>
> this.contentProvider.inputChanged( this.viewer, loadedElements,
> loadedElements );
>
> try {
> this.sleep(2000);
> PlatformUI.getWorkbench().getDisplay().asyncExec( new Runnable(){
>
> @Override
> public void run() {
> // here pack the columns as above
> }
> });
> } catch (InterruptedException e) {
> // TODO Auto-generated catch block
> e.printStackTrace();
> }
>
>
> }
>
>
>
> But the two asyncExec should be managed as equivalent. What am I doing
> wrong?
Previous Topic:strange index update with virtual table
Next Topic:strange transform error
Goto Forum:
  


Current Time: Sat Dec 20 18:42:31 GMT 2014

Powered by FUDForum. Page generated in 0.02463 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software