I have a pretty large ZEST Tree, displaying a Hashtree (Merkletree). Because of its size and limited available space it gets so compressed you can't read it anymore:
Therefore I want to be able to grab more space than the actual shell has, and implement a scrolling/dragging option to move around with the mouse.
However, I can't find a subelement in which I can contain it, which doesn't get filled into the space I have.
I already have tried SashForm (org.eclipse.swt.custom.SashForm), but it couldn't become bigger than the window.
Is there a possibility to implement my plan or is it generally not supported in SWT?
I know little about Zest, thus you should first look if Zest itself offers zooming and/or scrolling.
If there is no built-in support, you can use SWT's ScrolledComposite. See here for more information:
Detailed article: http://www.codeaffine.com/2016/03/01/swt-scrolledcomposite/
Code snippets: https://www.eclipse.org/swt/snippets/ (search for ScrolledComposite)
Layout: Java SWT - ScrolledComposite inside Group
By setting the style of the Graph to SWT.V_SCROLL | SWT.H_SCROLL you can make the graph scrollable:
Graph graph = new Graph(shell, SWT.H_SCROLL | SWT.V_SCROLL);
After some time I got it working in a decent way. I use a simple PaintListener with the method setSize. For the Zooming I use the class org.eclipse.gef.editparts.ZoomManager. I found one big disatvantage, this class needs a lot of performance and there are certainly other solutions as well.
I hope the code makes clear why and how.
public class ZoomableZestGraph extends Composite {
private GraphViewer graphViewer;
private Graph graph;
public ZoomableZestGraph(Composite parent, int style) {
super(parent, style);
this.setLayout(new GridLayout(1, true));
this.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1,1));
//create a GraphViewer and Graph
graphViewer = new GraphViewer(this, SWT.V_SCROLL | SWT.H_SCROLL);
graph = graphViewer.getGraphControl();
graph.setLayoutAlgorithm(new TreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING), true);
graph.setHorizontalScrollBarVisibility(Graph.ALWAYS);
graph.setVerticalScrollBarVisibility(Graph.ALWAYS);
//Fill our graph with some nodes and connect them
GraphNode node1 = new GraphNode(graph, SWT.NONE, "Earendil");
GraphNode node2 = new GraphNode(graph, SWT.NONE, "Elros");
GraphNode node3 = new GraphNode(graph, SWT.NONE, "Elrond");
GraphNode node4 = new GraphNode(graph, SWT.NONE, "Elladan");
GraphNode node5 = new GraphNode(graph, SWT.NONE, "Elrohir");
GraphNode node6 = new GraphNode(graph, SWT.NONE, "Arwen");
new GraphConnection(graph, ZestStyles.CONNECTIONS_DIRECTED, node1, node2);
new GraphConnection(graph, ZestStyles.CONNECTIONS_DIRECTED, node1, node3);
new GraphConnection(graph, ZestStyles.CONNECTIONS_DIRECTED, node2, node4);
new GraphConnection(graph, ZestStyles.CONNECTIONS_DIRECTED, node2, node5);
new GraphConnection(graph, ZestStyles.CONNECTIONS_DIRECTED, node2, node6);
/*
This graphViewer consists of 2 components: the control and the graph (Figure)
We want to give the control a size by the layout and the graph a custom, bigger value.
For the control (graphViewer.getControl) I simply grab all available space
*/
GridDataFactory.fillDefaults().grab(true, true).applyTo(graphViewer.getControl());
//For the graph we have to create a PaintListener.
graph.addPaintListener(new PaintListener() {
#Override
public void paintControl(PaintEvent e) {
graph.setSize(1300, 1080);
}
});
//The Graph now fills the shell/parent composite,
//but the actual graph size can be set as we want in the paint //listener
//Zooming with the class org.eclipse.gef.editparts.ZoomManager
//As arguments we need a ScalableFigure which we receive by graph.getRootLayer and the Viewport.
ZoomManager zoomManager = new ZoomManager(graph.getRootLayer(), graph.getViewport());
//we bind the zoom mechanic to a simple mouse wheel listener
graph.addMouseWheelListener(new MouseWheelListener() {
#Override
public void mouseScrolled(MouseEvent e) {
if (e.count < 0) {
zoomManager.zoomOut();
} else {
zoomManager.zoomIn();
}
}
});
//We give the focus to our graphViewer, so it receives the MouseWheel Events
graphViewer.getControl().forceFocus();
}
#Override
protected void checkSubclass() {
//we are a composite subclass
}
}
Note: I didn't include the imports
Related
The current implementation of the VirtualFlow only makes scrollbars visible when view rect becomes less than control size. By control I mean ListView, TreeView and whatever standard virtualized controls. The problem is that vertical scrollbar appearance causes recalculation of the control width, namely it slightly shifts cell content to the left side. This is clearly noticeable and very uncomfortable movement.
I need to reserve some space for the vertical scrollbar beforehand, but none of controls provide API to manipulate VirtualFlow scrollbars behavior, which is very unfortunate API design. Not to mention that most of the implementations place scrollbars on top of the component, thus just overlapping the small part of it.
The question is, "Which is the best way to achieve this?". Paddings won't help, and JavaFX has no margins support. I could put control (e.g ListView) inside of ScrollPane, but I'd bet VirtualFlow won't continue to reuse cells in that case, so it's not a solution.
EXAMPLE:
Expand and collapse node2, it shifts lbRight content.
public class Launcher extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
TreeItem<UUID> root = new TreeItem<>(UUID.randomUUID());
TreeView<UUID> tree = new TreeView<>(root);
tree.setCellFactory(list -> new CustomCell());
TreeItem<UUID> node0 = new TreeItem<>(UUID.randomUUID());
TreeItem<UUID> node1 = new TreeItem<>(UUID.randomUUID());
TreeItem<UUID> node2 = new TreeItem<>(UUID.randomUUID());
IntStream.range(0, 100)
.mapToObj(index -> new TreeItem<>(UUID.randomUUID()))
.forEach(node2.getChildren()::add);
root.getChildren().setAll(node0, node1, node2);
root.setExpanded(true);
node2.setExpanded(true);
BorderPane pane = new BorderPane();
pane.setCenter(tree);
Scene scene = new Scene(pane, 600, 600);
primaryStage.setTitle("Demo");
primaryStage.setScene(scene);
primaryStage.setOnCloseRequest(t -> Platform.exit());
primaryStage.show();
}
static class CustomCell extends TreeCell<UUID> {
public HBox hBox;
public Label lbLeft;
public Label lbRight;
public CustomCell() {
hBox = new HBox();
lbLeft = new Label();
lbRight = new Label();
lbRight.setStyle("-fx-padding: 0 20 0 0");
Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
hBox.getChildren().setAll(lbLeft, spacer, lbRight);
}
#Override
protected void updateItem(UUID uuid, boolean empty) {
super.updateItem(uuid, empty);
if (empty) {
setGraphic(null);
return;
}
String s = uuid.toString();
lbLeft.setText(s.substring(0, 6));
lbRight.setText(s.substring(6, 12));
setGraphic(hBox);
}
}
}
Reacting to
you can't just extend the VirtualFlow and override a method
certainly true if the method is deeply hidden by package/-private access (but even then: javafx is open source, checkout-edit-compile-distribute is also an option :). In this case we might get along with overriding public api as outlined below (not formally tested!).
VirtualFlow is the "layout" of cells and scrollBars: in particular, it has to cope with handling sizing/locating of all content w/out scrollBars being visible. There are options on how that can be done:
adjust cell width to always fill the viewport, increasing/decreasing when vertical scrollBar is hidden/visible
keep cell width constant such that there is always space left for the scrollBar, be it visible or not
keep cell width constant such that there is never space left the scrollBar, laying it out on top of cell
others ??
Default VirtualFlow implements the first with no option to switch to any other. (might be candidate for an RFE, feel free to report :).
Digging into the code reveals that the final sizing of the cells is done by calling cell.resize(..) (as already noted and exploited in the self-answer) near the end of the layout code. Overriding a custom cell's resize is perfectly valid and a good option .. but not the only one, IMO. An alternative is to
extend VirtualFlow and override layoutChildren to adjust cell width as needed
extend TreeViewSkin to use the custom flow
Example code (requires fx12++):
public static class XVirtualFlow<I extends IndexedCell> extends VirtualFlow<I> {
#Override
protected void layoutChildren() {
super.layoutChildren();
fitCellWidths();
}
/**
* Resizes cell width to accomodate for invisible vbar.
*/
private void fitCellWidths() {
if (!isVertical() || getVbar().isVisible()) return;
double width = getWidth() - getVbar().getWidth();
for (I cell : getCells()) {
cell.resize(width, cell.getHeight());
}
}
}
public static class XTreeViewSkin<T> extends TreeViewSkin<T>{
public XTreeViewSkin(TreeView<T> control) {
super(control);
}
#Override
protected VirtualFlow<TreeCell<T>> createVirtualFlow() {
return new XVirtualFlow<>();
}
}
On-the-fly usage:
TreeView<UUID> tree = new TreeView<>(root) {
#Override
protected Skin<?> createDefaultSkin() {
return new XTreeViewSkin<>(this);
}
};
Ok, this is summary based on #kleopatra comments and OpenJFX code exploration. There will be no code to solve the problem, but still maybe it will spare some time to someone.
As being said, it's VirtualFlow responsibility to manage virtualized control viewport size. All magic happens in the layoutChildren(). First it computes scrollbars visibility and then recalculates size of all children based on that knowledge. Here is the code which causes the problem.
Since all implementation details are private or package-private, you can't just extend the VirtualFlow and override method or two, you have to copy-paste and edit entire class (to remove one line, yes). Given that, changing internal components layout could be a better option.
Sometimes, I adore languages those have no encapsulation.
UPDATE:
I've solved the problem. There is no way no reserve space for vertical scrollbar without tweaking JavaFX internals, but we can limit cell width, so it would be always less than TreeView (or List View) width. Here is simple example.
public class Launcher extends Application {
public static final double SCENE_WIDTH = 500;
#Override
public void start(Stage primaryStage) {
TreeItem<UUID> root = new TreeItem<>(UUID.randomUUID());
TreeView<UUID> tree = new TreeView<>(root);
tree.setCellFactory(list -> new CustomCell(SCENE_WIDTH));
TreeItem<UUID> node0 = new TreeItem<>(UUID.randomUUID());
TreeItem<UUID> node1 = new TreeItem<>(UUID.randomUUID());
TreeItem<UUID> node2 = new TreeItem<>(UUID.randomUUID());
IntStream.range(0, 100)
.mapToObj(index -> new TreeItem<>(UUID.randomUUID()))
.forEach(node2.getChildren()::add);
root.getChildren().setAll(node0, node1, node2);
root.setExpanded(true);
node2.setExpanded(true);
BorderPane pane = new BorderPane();
pane.setCenter(tree);
Scene scene = new Scene(pane, SCENE_WIDTH, 600);
primaryStage.setTitle("Demo");
primaryStage.setScene(scene);
primaryStage.setOnCloseRequest(t -> Platform.exit());
primaryStage.show();
}
static class CustomCell extends TreeCell<UUID> {
public static final double RIGHT_PADDING = 40;
/*
this value depends on tree disclosure node width
in my case it's enforced via CSS, so I always know exact
value of this padding
*/
public static final double INDENT_PADDING = 14;
public HBox hBox;
public Label lbLeft;
public Label lbRight;
public double maxWidth;
public CustomCell(double maxWidth) {
this.maxWidth = maxWidth;
hBox = new HBox();
lbLeft = new Label();
lbRight = new Label();
lbRight.setPadding(new Insets(0, RIGHT_PADDING, 0, 0));
Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
hBox.getChildren().setAll(lbLeft, spacer, lbRight);
}
#Override
protected void updateItem(UUID uuid, boolean empty) {
super.updateItem(uuid, empty);
if (empty) {
setGraphic(null);
return;
}
String s = uuid.toString();
lbLeft.setText(s.substring(0, 6));
lbRight.setText(s.substring(6, 12));
setGraphic(hBox);
}
#Override
public void resize(double width, double height) {
// enforce item width
double maxCellWidth = getTreeView().getWidth() - RIGHT_PADDING;
double startLevel = getTreeView().isShowRoot() ? 0 : 1;
double itemLevel = getTreeView().getTreeItemLevel(getTreeItem());
if (itemLevel > startLevel) {
maxCellWidth = maxCellWidth - ((itemLevel - startLevel) * INDENT_PADDING);
}
hBox.setPrefWidth(maxCellWidth);
hBox.setMaxWidth(maxCellWidth);
super.resize(width, height);
}
}
}
It's far from perfect, but it works.
Incredible easy question: I have a SWT table (viewer) and use a SWT.MeasureItem listener to set the cell height. How do I align the cell content to the bottom of the cell?
(It would probably work with another listener to SWT.PaintItem and some math and rendering all my cells manually, but that can't be the right way.)
public class TableDialog extends Dialog {
public static void main(String[] args) {
TableDialog dialog = new TableDialog(new Shell());
dialog.open();
}
public TableDialog(Shell parent) {
super(parent);
}
#Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText("Table Test");
newShell.setSize(500, 300);
}
#Override
protected Control createDialogArea(Composite parent) {
Composite container = (Composite) super.createDialogArea(parent);
container.setLayout(new FillLayout());
TableViewer viewer = new TableViewer(container, SWT.BORDER | SWT.FULL_SELECTION);
viewer.setContentProvider(new ArrayContentProvider());
viewer.setInput(Arrays.asList("A", "B", " C"));
Table table = viewer.getTable();
table.setLinesVisible(true);
table.addListener(SWT.MeasureItem, e -> e.height = 90);
return container;
}
}
Once you start using SWT.MeasureItem you need to do the drawing as well.
Since you are using TableViewer you can combine all this in one class by using an OwnerDrawLabelProvider as the viewer label provider. A very simple version would be something like this:
viewer.setLabelProvider(new OwnerDrawLabelProvider()
{
#Override
protected void paint(final Event event, final Object element)
{
String text = element.toString();
GC gc = event.gc;
int textHeight = gc.textExtent(text).y;
int yPos = event.y + event.height - textHeight;
gc.drawText(text, event.x, yPos);
}
#Override
protected void measure(final Event event, final Object element)
{
event.height = 90;
}
#Override
protected void erase(final Event event, final Object element)
{
// Stop the default draw of the foreground
event.detail &= ~SWT.FOREGROUND;
}
});
I am afraid, SWT.PaintItem is the right way in this case.
One of the SWT Snippets demonstrates how to draw multiple lines in a table item. It may serve as a starting point for your custom drawing code:
http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet231.java
The Custom Drawing Table and Tree Items article provides further information.
I'm working on adding a preference page to my eclipse application (Juno). I would like create something similar to what you see on the following Eclipse preference page: Eclipse (Juno) > Window Menu > Preferences > Java > Compiler > Building. That preference page appears to be created using org.eclipse.swt.widgets.Tree, but I'm not sure. If that is the case, how did they create the TreeItems? Are they org.eclipse.swt.widgets.TreeItems? I need to add StringFieldEditors and IntegerFieldEditors, or some type of fields (TextArea??), with some labels in front of them, that I could validate later on. From what I understand, it's not possible to add a Composite to a TreeItem, so how should I go around this problem? Any suggestion is greatly appreciated. Thanks.
Need to add that, since I can't use the Eclipse internal packages, is there other way to implement what I described above using the public API?
Here is an idea, but this code places the TreeItems contents under the tree. Thoughts?
Composite comp = getFieldEditorParent();
Tree tree = new Tree(comp, SWT.NONE);
tree.setLayout(new FillLayout());
tree.setHeaderVisible(true);
TreeItem item1 = new TreeItem(tree, SWT.NONE);
item1.setText("Name1");
TreeItem item11 = new TreeItem(item1, SWT.NONE);
item11.setText("Name11");
StringFieldEditor s11 = new StringFieldEditor(
"name11",
"label11:",
comp);
item11.setData(s11);
TreeItem item12 = new TreeItem(item1, SWT.NONE);
item12.setText("Name12");
StringFieldEditor s12 = new StringFieldEditor(
"name12",
"label12:",
comp);
item12.setData(s12);
item1.setExpanded(true);
item11.setExpanded(true);
item12.setExpanded(true);
TreeItem item2 = new TreeItem(tree, SWT.NONE);
item2.setText("Name2");
If you are interested in the implementation of any UI element in Eclipse, then install the Eclipse SDK (via Help > Install New Software...) and use the plug-in spy. The spy tells you which class implements the UI element (in your case it's org.eclipse.jdt.internal.ui.preferences.JavaBuildPreferencePage in the org.eclipse.jdt.ui bundle). Since the SDK includes the source, you can jump right there from the spy's pop-up and look for yourself how it's done.
The problem was solved by using org.eclipse.ui.forms.widgets.ExpandableComposite.
See the example below. I hope this helps someone :).
protected final void createFieldEditors()
{
// Create the ScrolledComposite to scroll horizontally and vertically
fScrolledComposite = new ScrolledComposite(
getFieldEditorParent(),
SWT.H_SCROLL | SWT.V_SCROLL);
//Displays the scrollbars when the window gets smaller
fScrolledComposite.setAlwaysShowScrollBars(false);
// Sets the minimum size for the composite to work for scrolling
fScrolledComposite.setMinSize(fCompositeWidth, fCompositeHeight);
fScrolledComposite.setExpandHorizontal(true);
fScrolledComposite.setExpandVertical(true);
Composite composite = new Composite(fScrolledComposite, SWT.NONE);
composite.setLayout(new GridLayout());
fScrolledComposite.setContent(composite);
// Sets up the toolkit.
Display display = composite.getDisplay();
toolkit = new FormToolkit(display);
// Creates a form instance.
form = toolkit.createForm(composite);
form.getBody().setLayout(new GridLayout());
form.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
form.setText("Model: " + SignalGeneratorDevice.MODEL_ID);// Sets title of the Preference page
// Add the three main nodes to the preference page
addNode1();
}
/**
* Adds the first node to the preference page
*/
private void addNode1()
{
ExpandableComposite expandableComposite = createExpandableComposite(
"Signal Generator Device Host/Port:",
true);
Composite childComposite = createChildComposite(expandableComposite);
//Builds fields here (StringFieldEditor, IntegerFieldEditor, etc.)
..................
}
/**
* Creates an ExpandableComposite that will be added to the preference page
*
* #param label
* #param expanded
* #return
*/
private ExpandableComposite createExpandableComposite(
String label,
boolean expanded)
{
ExpandableComposite expandableComposite = null;
if (expanded) {
expandableComposite = toolkit.createExpandableComposite(
form.getBody(),
ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT
| ExpandableComposite.EXPANDED);
} else {
expandableComposite = toolkit
.createExpandableComposite(
form.getBody(),
ExpandableComposite.TWISTIE
| ExpandableComposite.CLIENT_INDENT);
}
expandableComposite.setText(label);
expandableComposite.setBackground(form.getBackground());
expandableComposite.addExpansionListener(new ExpansionAdapter() {
#Override
public void expansionStateChanged(
ExpansionEvent e)
{
form.pack();
}
});
GridData gd = new GridData();
expandableComposite.setLayoutData(gd);
return expandableComposite;
}
/**
* Creates a child composite for an ExpandableComposite
*
* #param expandableComposite
* #return
*/
private Composite createChildComposite(
ExpandableComposite expandableComposite)
{
Composite childComposite = new Composite(expandableComposite, SWT.None);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 2;
//gd.horizontalAlignment = GridData.END;
childComposite.setLayoutData(gd);
expandableComposite.setClient(childComposite);
return childComposite;
}
I've got an issue with the drag and drop support for my tree items within a tab, the simple piece of code below works well on Windows XP/Seven, Ubuntu, Fedora and RedHat 4 but fails on RedHat 5.
#Override
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
setShellStyle(getShellStyle() | SWT.RESIZE);
TabFolder tabFolder = new TabFolder(composite, SWT.NONE);
tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH));
TabItem tab = new TabItem(tabFolder, SWT.NONE);
tab.setText("TabName");
/*
* TabItem 1 Content:
*/
TreeViewer tree = new TreeViewer(tabFolder, SWT.SINGLE|SWT.BORDER);
tree.setLabelProvider(provider);
tree.setContentProvider(provider);
tree.getTree().setHeaderVisible(true);
tree.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
TreeColumn tc = new TreeColumn(tree.getTree(), SWT.NONE, 0);
tc.setText("Name");
tc.setWidth(100);
tab.setControl(tree.getTree());
tree.setInput(provider.getInput());
/*
* Drag&Drop Support
*/
Transfer[] transfers = new Transfer[] { TextTransfer.getInstance()};
DragDropItemsSupport dndItemsListener = new DragDropItemsSupport(tree);
tree.addDragSupport(DND.DROP_MOVE, transfers, dndItemsListener);
tree.addDropSupport(DND.DROP_MOVE, transfers, dndItemsListener);
return composite;
}
When I said "works well", I'm able to pass through the method dragOver of ViewerDropAdapter on mentioned hosts.
#Override
public void dragOver(DropTargetEvent event) {
if (event.item != null)
System.out.println("Drag over : " + ((TreeItem)event.item).getText());
}
Is someone has a explanation, a way to investigate, or a solution :) ?
I see the same thing on a TableViewer in a TabItem in a TabFolder on Centos 5. Haven't tested on other OS. Can be fixed by changing to CTabFolder and CTabItem.
I've been tasked with creating a Composite that contains two TableViewers. The top table contains a single row of editable cells. These table cells will be used to filter data in the bottom table. There are a number of things that are not working properly, but I'll limit my inquiry, here, to one in particular. The TableViewers' tables extend beyond the width and height of the Composite that contains them, and I am not able to view table columns beyond the right edge (or rows of the bottom table that extend below the bottom) of the Composite. The Composite's horizontal scroll bar scrolls properly, but only as far as the width of the Composite (not surprisingly). I'm sure it is as simple as tweaking GridData or SWT constants during construcion. Sadly, I've tried several different combinations without success. Here's a snippet of my relevant code:
public class ControlledColumnFilterTableComposite<T> extends Composite {
private TableViewer filterViewer;
private TableViewer mainViewer;
public ControlledColumnFilterTableComposite(Composite parent,
IControlledColumnTableContentProvider<T> content) {
super(parent, SWT.H_SCROLL);
createComposite(parent, content);
}
private void createComposite(Composite parent,
IControlledColumnTableContentProvider<T> content) {
this.setLayout(new GridLayout(1, false));
GridData data = getLayoutData(parent);
this.setLayoutData(data);
addHorizontalBarListener();
this.filterViewer = createFilterViewer(parent, content);
this.mainViewer = createMainViewer(parent, content);
}
private TableViewer createFilterViewer(Composite parent,
IControlledColumnTableContentProvider<T> content) {
TableViewer viewer = new TableViewer(this, SWT.MULTI
| SWT.FULL_SELECTION | SWT.BORDER);
viewer.getTable().setHeaderVisible(true);
viewer.getTable().setLinesVisible(true);
viewer.setContentProvider(content);
ControlledColumnTableMetadata<T> metadata = content.getMetadata();
for (int i = 0; i < metadata.getBean().getDeclaredFields().length; i++) {
getViewerColumn(viewer, metadata.getBean().getDeclaredFields()[i],
true);
}
return viewer;
}
private TableViewer createMainViewer(Composite parent,
IControlledColumnTableContentProvider<T> content) {
TableViewer viewer = new TableViewer(this, SWT.MULTI | SWT.V_SCROLL
| SWT.FULL_SELECTION | SWT.BORDER);
viewer.getTable().setHeaderVisible(false);
viewer.getTable().setLinesVisible(true);
viewer.setContentProvider(content);
viewer.setInput(((IPagingContentProvider<T>) content)
.getModelProvider().getTableRows());
ControlledColumnTableMetadata<T> metadata = content.getMetadata();
for (int i = 0; i < metadata.getBean().getDeclaredFields().length; i++) {
getViewerColumn(viewer, metadata.getBean().getDeclaredFields()[i],
false);
}
viewer.getTable().setLayoutData(getLayoutData(parent));
/*
* I've tried getLayoutData(this) and I've also tried manipulating the
* grabExcessHorizontalSpace and grabExcessVerticalSpace on the returned
* GridData without getting the desired results
*/
return viewer;
}
private TableViewerColumn getViewerColumn(TableViewer viewer, Field field,
boolean listen) {
final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
SWT.NONE);
final TableColumn column = viewerColumn.getColumn();
setColumnProperties(viewer, column, field);
viewerColumn.setLabelProvider(getColumnLabelProvider(field));
// Only the filter TableViewer should have Listeners and EditingSupport
if (listen) {
// add sorting support
viewerColumn.getColumn().addListener(SWT.Selection,
new SortListener(field));
// add support for saving column width preferences
viewerColumn.getColumn()
.addControlListener(createControlListener());
// add editing support
viewerColumn.setEditingSupport(getEditingSupport(viewer, field));
}
return viewerColumn;
}
private void setColumnProperties(TableViewer viewer, TableColumn column,
Field field) {
ControlledColumnTableMetadata<T> metadata = ((IControlledColumnTableContentProvider<T>) viewer
.getContentProvider()).getMetadata();
column.setText(metadata.getColumnHeader(field));
column.setToolTipText(metadata.getColumnHeader(field));
if (metadata.isVisible(field)) {
column.setWidth(metadata.getColumnWidth(field));
column.setResizable(true);
column.setMoveable(true);
} else {
column.setWidth(0);
column.setResizable(false);
column.setMoveable(false);
}
}
private GridData getLayoutData(Composite parent) {
GridLayout layout = (GridLayout) parent.getLayout();
// Layout the viewer
GridData gridData = new GridData();
gridData.verticalAlignment = GridData.FILL;
gridData.horizontalAlignment = GridData.FILL;
gridData.horizontalSpan = layout.numColumns;
gridData.grabExcessHorizontalSpace = true;
gridData.grabExcessVerticalSpace = true;
return gridData;
}
...
}
Any suggestions are GREATLY appreciated. Thanks, in advance.
dont do this
GridData data = getLayoutData(parent); // inside getLayoutData: GridLayout layout = (GridLayout) parent.getLayout();
this.setLayoutData(data);
setLayout should be used by composite which arranges child-controls (this.setlayout). same as this.someControl.setLayoutData(). In your case: parent handles where ControlledColumnFilterTableComposite is placed and ControlledColumnFilterTableComposite handles how TableViewer are arranged. This means that you should never call: parent.getLayout() and this.setLayoutData() because you might not now which Layout parent uses and using invalid LayoutData leads to some exceptions.
try this
this.setLayout(new GridLayout(1,false));
this.filterViewer = createFilterViewer();
this.filterViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,true));
this.mainViewer = createMainViewer();
this.mainViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,true));
GridLayout works as table in HTML - places controls in cells. SWT.FILL means that control will fill sorounding cell horizontally and vertically, and true (3rd and 4th argument) means that cell will expand to maximum available size horizontally and vertically
remove the H_SCROLL, If you want Scrolling in your Composite use ScrolledComposite