Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Rich Client Platform (RCP) » List vs JList
List vs JList [message #1371551] Wed, 21 May 2014 12:26 Go to next message
Xavipen Mising name is currently offline Xavipen Mising nameFriend
Messages: 49
Registered: March 2011
Member
Hi,

I was migrating a project from Swing to SWT when i run into the following issue.

List Widgets only display text.

However, with JList it is posible to return Composites for the objects in the JList. This is a feture that was used a lot, as most of the "lists" in the aplication do not display text nor images.

Is there any other widget that could also do what JList does?

Cheers,
Javi
Re: List vs JList [message #1371814 is a reply to message #1371551] Wed, 21 May 2014 14:58 Go to previous messageGo to next message
Simon Scholz is currently offline Simon ScholzFriend
Messages: 73
Registered: April 2012
Location: Germany
Member
Hello Xavipen,

actually SWT tries to use native OS Widgets for visualisation rather than drawing their own components like Swing does.

Therefore the SWT List is limited.

By the way I usually use a Table, and especially the TableViewer JFace abstraction of a Table, with one column instead of a list, because a table offers more functionallity, but that won´t help you either.

In your case you unfortunately have to write your own implementation of a custom List, which contains Composite Items.

For instance you could use a org.eclipse.swt.custom.ScrolledComposite and place your custom Composite Items on it.

Or could you explain your custom Composites in the Swing List a bit more?
Maybe a SWT Table is able to fullfil your needs as those native widgets are rendered much faster than custom drawn widgets.

Let me know, if you need further assistence Wink

Best regards,

Simon

[Updated on: Wed, 21 May 2014 15:05]

Report message to a moderator

Re: List vs JList [message #1372023 is a reply to message #1371814] Wed, 21 May 2014 16:45 Go to previous messageGo to next message
Xavipen Mising name is currently offline Xavipen Mising nameFriend
Messages: 49
Registered: March 2011
Member
Hi Simon,

Thanks for your reply.

There are two scenarios where i would use such a "composite List".

1) A scheduling system. Each row would use a canvas to display when a resource is used. So it is a list of Resources but instead of the name or a string, I would need to draw the events on a time scale. I Guess using Canvas.

2) Monitoring system: A System has two types of services. A would need a list of the system but each row would show two tables one per each type of service. These tables are normal SWT tables with tableviewers data bindings and so on. The List of system can change add anytime and it is not known before hand.

Following your advise i started to develop something called CompositeList<T>. However, i do not get anything displayed and i do not understand why. Could you let me know if i am missing something?

I will only put the relevant parts, but i do not have any problem in posting the full code.


public class CompositeList<T> extends ScrolledComposite {

	private CompositeListRowRenderer<T> renderer = null;
	
	final private HashMap<T, Control> controlMap = new HashMap<T, Control>();
	final private Composite listComposite;
	
	private int rowHeight = 100;
	
	public CompositeList(Composite parent, int style) {
		super(parent, style);
		listComposite = new Composite(this, SWT.NONE);
		GridLayout gridLayout = new GridLayout();
 		gridLayout.numColumns = 1;
		listComposite.setLayout(gridLayout);
	}

	public void add(Collection<T> items){
		for (T item : items ){
			doAdd(item);
		}
//		//is this the rigth call to update the composite?
//		this.redraw();
//		this.update();
		//how to calculate the min size?
		this.setMinSize(listComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
		this.update();
	}
	
	protected boolean doAdd(T item){
		final Control control;
		if ( renderer == null ){
			log.error("label");
			final Label defaultLabel = new Label(this, SWT.NONE);
			defaultLabel.setText(item.toString());
			control = defaultLabel;
		}else{
			control = renderer.render(listComposite, controlMap.size(), item);
		}
		if ( control == null ){
			return false;
		}
		GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
		data.heightHint = rowHeight ;
		control.setLayoutData(data);
		controlMap.put(item, control);
		return true;
	}
}


The create part control, on the view I had used to tested it, is as follows:

	@Override
	public void createPartControl(Composite arg0) {
		arg0.setLayout(new GridLayout(1, false));
		
		CompositeList<ISLEProviderInstanceManager> compositeList = new CompositeList<ISLEProviderInstanceManager>(arg0, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
		compositeList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		compositeList.setExpandHorizontal(true);
		compositeList.setExpandVertical(true);
		
//		compositeList.setRowRenderer(new ManagerCompositeListRowRenderer());
	
		compositeList.add(AppContext.getManagers());
	}


The ScrolledComposite is shown but no labels appear. I did check taht get managers returned some data Wink

Did i have miss something, how could i force the ScrolledComposite to be updated so that the added labels appear?

Cheers
Javi
Re: List vs JList [message #1376122 is a reply to message #1372023] Fri, 23 May 2014 09:14 Go to previous messageGo to next message
Simon Scholz is currently offline Simon ScholzFriend
Messages: 73
Registered: April 2012
Location: Germany
Member
Hi Javi,

in order to see the widgets on a org.eclipse.swt.custom.ScrolledComposite you have to set the content of the ScrolledComposite.
You can archive that by using the org.eclipse.swt.custom.ScrolledComposite.setContent(Control) method.

	public CompositeList(Composite parent, int style) {
		super(parent, style);
		listComposite = new Composite(this, SWT.NONE);
		GridLayout gridLayout = new GridLayout();
 		gridLayout.numColumns = 1;
		listComposite.setLayout(gridLayout);
                this.setContent(listComposite);
	}


And instead of final Label defaultLabel = new Label(this, SWT.NONE); you should use the listComposite as the labels parent. You already pass the listComposite to the renderer, but you missed to also use the listComposite as label´s parent.

Hope that helps. And if you have further questions do not hestitate to ask =)

Best regards,

Simon
Re: List vs JList [message #1385278 is a reply to message #1376122] Thu, 05 June 2014 10:52 Go to previous message
Xavipen Mising name is currently offline Xavipen Mising nameFriend
Messages: 49
Registered: March 2011
Member
Hi Simon,

Thanks for your help. I got it running and just in case anyone is interested here is the CompositeList i have implemented. Of course it has plenty of room from improvement


@SuppressWarnings("serial")
public class CompositeList<T> extends ScrolledComposite {
	
	protected IObservableList list;
	
	final private Composite listComposite;
	
	private CompositeListRenderer<T> renderer = null;
	
	final private HashMap<T, Control> controlMap = new HashMap<T, Control>();
	
	private int rowHeight = 100;
	
	final protected org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(this.getClass());

	public CompositeList(Composite parent, int style) {
		super(parent, style);

		listComposite = new Composite(this, SWT.NONE);
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 1;
		listComposite.setLayout(gridLayout);
		
		this.setContent(listComposite);
		this.setMinSize(listComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
			
	}

	@SuppressWarnings("unchecked")
	public void setInput(IObservableList list){
		clearData();
		addData(list);
		list.addListChangeListener(listChangeListener);
	}
	
	protected void clearData() {
		if ( list != null ) list.removeListChangeListener(listChangeListener);
		for ( Control control : controlMap.values()){
			if ( control instanceof ExpandableComposite){
				((ExpandableComposite) control).removeExpansionListener(expansionListener);
			}else{
				control.removeControlListener(resizeListener);
			}
			control.dispose();
		}
		controlMap.clear();
	}

	protected boolean addData(T item){
		final Control control;
		if ( renderer == null ){
			final Label defaultLabel = new Label(listComposite, SWT.NONE);
			defaultLabel.setText(item.toString());
			control = defaultLabel;
		}else{
			control = renderer.render(listComposite, controlMap.size(), item);
		}
		if ( control == null ){
			return false;
		}
		
		if ( control instanceof ExpandableComposite){
			((ExpandableComposite) control).addExpansionListener(expansionListener);
		}else{
			control.addControlListener(resizeListener);
		}
		
		GridData data = new GridData(SWT.FILL, SWT.UP, true, false);
		data.heightHint = rowHeight ;
		control.setLayoutData(data);
		controlMap.put(item, control);
		return true;
	}
	
	protected void addData(Collection<T> items){
		for (T item : items ){
			addData(item);
		}
	}
	
	protected void removeData(T item){
		final Control control = controlMap.remove(item);
		if ( control != null ){
			doRemove(control);
		}
	}
	
	protected void removeData(Collection<T> items){
		for (T item : items ){
			final Control control = controlMap.remove(item);
			if ( control != null ){
				doRemove(control);
			}
		}
	}

	protected void doRemove(Control control){
		if ( control instanceof ExpandableComposite){
			((ExpandableComposite) control).removeExpansionListener(expansionListener);
		}else{
			control.removeControlListener(resizeListener);
		}
		control.dispose();
	}

	public CompositeListRenderer<T> getRenderer() {
		return renderer;
	}


	public void setRenderer(CompositeListRenderer<T> renderer) {
		this.renderer = renderer;
	}
	
	public int getRowHeight() {
		return rowHeight;
	}

	public void setRowHeight(int rowHeight) {
		this.rowHeight = rowHeight;
	}
	
	protected void fireListUpdate(){
		listComposite.update();
		CompositeList.this.setMinSize(listComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
	}

	public void fireListResize(){
		this.setMinSize(listComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
	}
	
	final private ControlListener resizeListener =  new ControlListener(){

		@Override
		public void controlMoved(ControlEvent arg0) {}

		@Override
		public void controlResized(ControlEvent arg0) {
			Display.getDefault().asyncExec(new Runnable() {
				@Override
				public void run() {
					CompositeList.this.setMinSize(listComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
				}
			});
		}
	};
	
	final private IExpansionListener expansionListener =  new IExpansionListener(){
		@Override
		public void expansionStateChanged(ExpansionEvent event) {
			Display.getDefault().asyncExec(new Runnable() {
				@Override
				public void run() {
					CompositeList.this.setMinSize(listComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
				}
			});
		}

		@Override
		public void expansionStateChanging(ExpansionEvent event) {}
		
	};
	
	final private IListChangeListener listChangeListener = new IListChangeListener() {
		
		@SuppressWarnings("unchecked")
		@Override
		public void handleListChange(ListChangeEvent event) {
			final List<T> addedElements = new ArrayList<T>();
			final List<T> removedElements = new ArrayList<T>();
			try{
				for (ListDiffEntry change : event.diff.getDifferences()){
					if ( change.isAddition() ) {
						addedElements.add((T) change.getElement());
					}else{
						removedElements.add((T) change.getElement());
					}
				}
			} catch ( Exception e){
				//add log.
				return;
			}
			if ( !addedElements.isEmpty()) addData(addedElements);
			if ( !removedElements.isEmpty()) removeData(removedElements);
			fireListUpdate();
		}
	};
	
	@Override
	public void dispose(){
		clearData(); 
		super.dispose();
		
	}
}

public interface CompositeListRenderer<T> {
	
	public Control render(Composite listComposite, int row, T data );

}



And the usage:


CompositeList<ISLEProviderInstanceManager> compositeList = 
				new CompositeList<ISLEProviderInstanceManager>(frmMissions.getBody(), SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
			compositeList.setExpandHorizontal(true);
			compositeList.setExpandVertical(true);
		
		compositeList.setRenderer(new ManagerListRenderer());
		
		IObservableList input = getManagerList();
		compositeList.setInput(input);





Simon Scholz wrote on Fri, 23 May 2014 11:14
Hi Javi,

in order to see the widgets on a org.eclipse.swt.custom.ScrolledComposite you have to set the content of the ScrolledComposite.
You can archive that by using the org.eclipse.swt.custom.ScrolledComposite.setContent(Control) method.

	public CompositeList(Composite parent, int style) {
		super(parent, style);
		listComposite = new Composite(this, SWT.NONE);
		GridLayout gridLayout = new GridLayout();
 		gridLayout.numColumns = 1;
		listComposite.setLayout(gridLayout);
                this.setContent(listComposite);
	}


And instead of final Label defaultLabel = new Label(this, SWT.NONE); you should use the listComposite as the labels parent. You already pass the listComposite to the renderer, but you missed to also use the listComposite as label´s parent.

Hope that helps. And if you have further questions do not hestitate to ask =)

Best regards,

Simon

Previous Topic:Product validation doesn't find the 2 lucene.core versions required
Next Topic: Exception thrown if Part is closed PartStack within Area
Goto Forum:
  


Current Time: Sat Dec 20 02:28:55 GMT 2014

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

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