Bug 248700 - [GalleryTreeViewer] New groups added via refresh() appear collapsed
Summary: [GalleryTreeViewer] New groups added via refresh() appear collapsed
Status: RESOLVED WONTFIX
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Nebula (show other bugs)
Version: unspecified   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P1 normal (vote)
Target Milestone: ---   Edit
Assignee: Nicolas Richeton CLA
QA Contact:
URL:
Whiteboard:
Keywords: plan
Depends on:
Blocks:
 
Reported: 2008-09-26 05:25 EDT by Justin Dolezy CLA
Modified: 2021-07-05 11:40 EDT (History)
1 user (show)

See Also:


Attachments
Unit test for this bug (5.70 KB, text/plain)
2008-09-26 08:41 EDT, Nicolas Richeton CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Justin Dolezy CLA 2008-09-26 05:25:29 EDT
Build ID: I20080617-2000

Steps To Reproduce:
Here's an example demostrating this. I've just modified the existing gallery viewer snippet to add some new groups periodically.


/*******************************************************************************
 * Copyright (c) 2007-2008 Peter Centgraf.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors :
 *    Peter Centgraf - initial implementation
 *******************************************************************************/
package com.neckdiagrams.instruments.ui.internal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.nebula.jface.galleryviewer.GalleryTreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

/**
 * Simple visual test harness for GalleryTreeViewer.
 *  * @author Peter Centgraf
 * @since Dec 5, 2007
 */
public class SnippetGalleryViewerTester {

protected static class GalleryTestContentProvider implements ITreeContentProvider {
// implements IStructuredContentProvider { // Use this to test
// FlatTreeContentProvider
public static final int NUM_GROUPS = 1;
public static final int NUM_ITEMS = 9;

List<String> groups = new ArrayList<String>();
HashMap<String, List<String>> itemsByGroup = new HashMap<String, List<String>>();

public GalleryTestContentProvider() {
for (int i = 0; i < NUM_GROUPS; i++) {
    addNewGroup();
}
}

public Object[] getChildren(Object parentElement) {
    return itemsByGroup.get(parentElement).toArray();
}

public Object getParent(Object element) {
return null;
}

public boolean hasChildren(Object element) {
return ((String) element).startsWith("Group");
}

public Object[] getElements(Object inputElement) {
return groups.toArray();
}

public void dispose() {
}

public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}

public void addNewGroup() {
            List<String> items = new ArrayList<String>();
            for (int j = 0; j < NUM_ITEMS; j++) {
                items.add("Item " + (j + 1));
            }
            final String group = "Group " + (groups.size() + 1);
            itemsByGroup.put(group, items);
            groups.add(group);
}
}

protected static class GalleryTestLabelProvider extends LabelProvider implements IColorProvider, IFontProvider {
protected static Image itemImage = new Image(Display.getCurrent(), Program.findProgram("jpg").getImageData());

public Image getImage(Object element) {
return itemImage;
}

public Color getBackground(Object element) {
String label = (String) element;
if (Integer.parseInt(label.substring(label.indexOf(' ') + 1)) % 2 > 0) {
return Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);
} else {
return null;
}
}

public Color getForeground(Object element) {
String label = (String) element;
if (Integer.parseInt(label.substring(label.indexOf(' ') + 1)) % 2 > 0) {
return null;
} else {
return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
}
}

public Font getFont(Object element) {
String label = (String) element;
if (Integer.parseInt(label.substring(label.indexOf(' ') + 1)) % 2 > 0) {
return null;
} else {
FontData sysFontData = Display.getCurrent().getSystemFont().getFontData()[0];
sysFontData.setStyle(SWT.BOLD | SWT.ITALIC);
return new Font(Display.getCurrent(), sysFontData);
}
}
}

protected static class OddNumbersFilter extends ViewerFilter {
public boolean select(Viewer viewer, Object parentElement, Object element) {
try {
String label = (String) element;
return (Integer.parseInt(label.substring(label.indexOf(' ') + 1)) % 2

    0);

} catch (Exception e) {
return true;
}
}
}

protected static final int WIDTH = 800;
protected static final int HEIGHT = 600;
protected Shell shell;

public SnippetGalleryViewerTester() {
// Initialize the containing Shell
final Display display = new Display();
shell = new Shell(display);
shell.setSize(WIDTH, HEIGHT);
shell.setBackground(display.getSystemColor(SWT.COLOR_RED));
GridLayoutFactory.fillDefaults().applyTo(shell);

final GalleryTreeViewer viewer = new GalleryTreeViewer(shell);
GridDataFactory.fillDefaults().grab(true, true).applyTo(viewer.getGallery());
final GalleryTestContentProvider contentProvider = new GalleryTestContentProvider();
viewer.setContentProvider(contentProvider);
viewer.setLabelProvider(new GalleryTestLabelProvider());
viewer.setComparator(new ViewerComparator());
// viewer.addFilter(new OddNumbersFilter());
viewer.setInput(new Object());

// Show the Shell
shell.open();
shell.layout();

final Runnable runnable = new Runnable() {
public void run() {
contentProvider.addNewGroup();
viewer.refresh();
if (contentProvider.groups.size() < 7) display.timerExec(3000, this);
}
};
display.timerExec(3000, runnable);

// Run the event loop
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}

/**
* @param args
*/
public static void main(String[] args) {
new SnippetGalleryViewerTester();
}

}


More information:
See newsgroup posting: http://www.eclipse.org/newsportal/article.php?id=1555&group=eclipse.technology.nebula#1555

Have run this on Leopard but I expect same thing happens on other platforms too.
Comment 1 Nicolas Richeton CLA 2008-09-26 08:41:12 EDT
Created attachment 113585 [details]
Unit test for this bug

There are 2 tests : one for the GalleryTreeViewer and one for the TreeViewer as reference.
Comment 2 Nicolas Richeton CLA 2008-09-26 08:41:39 EDT
I made some quick tests on this and it seems that the TreeViewer has the same behavior than the GalleryTreeViewer. See attached unit test.
Comment 3 Justin Dolezy CLA 2008-09-26 11:47:33 EDT
Interesting, maybe this is just a documentation deficiency in AbstractTreeViewer.

The public API says this:

	/**
	 * Sets the auto-expand level. The value 0 means that there is no
	 * auto-expand; 1 means that top-level elements are expanded, but not their
	 * children; 2 means that top-level elements are expanded, and their
	 * children, but not grandchildren; and so on.
	 * <p>
	 * The value <code>ALL_LEVELS</code> means that all subtrees should be
	 * expanded.
	 * </p>
	 * 
	 * @param level
	 *            non-negative level, or <code>ALL_LEVELS</code> to expand all
	 *            levels of the tree
	 */
	public void setAutoExpandLevel(int level) {
		expandToLevel = level;
	}


But then looking at the private field 'expandToLevel' mentions that this auto-expand applies onto to input changes!


	/**
	 * The level to which the tree is automatically expanded each time the
	 * viewer's input is changed (that is, by <code>setInput</code>). A value
	 * of 0 means that auto-expand is off.
	 * 
	 * @see #setAutoExpandLevel
	 */
	private int expandToLevel = 0;



Maybe the JFace guys should update the documentation here so this is more visible on the public doc?
Comment 4 Nicolas Richeton CLA 2008-09-26 11:58:57 EDT
Tom: Could you give us your opinion on this ? The public javadoc of AbstractTreeViewer may be not be clear enough. Thanks. 
Comment 5 Nicolas Richeton CLA 2009-04-17 15:54:42 EDT
Since this is exactly the behavior of other jface viewers, resolving as WONTFIX. 
Please reopen if the jface team changes this.