Most efficient way to display multiple components on n columns - gwt

I am creating a GWT app. In all my screens, one need is recurrent : adding a lot of components to a screen and have automatically them organized in 2 or 3 columns. I want to create a template for this but before, I wonder if there is already something defined for this need.
Ideally, that is what I would like to do:
MyLayout myLayout = new MyLayout(nbColumns);
myLayout.add(widget1);
myLayout.add(widget2);
myLayout.add(widget3);
myLayout.add(widget4);
myLayout.add(widget5);
...
and have the components automatically organizes in nbColumns columns.
Any solution in GWT or GXT 3 would be appreciated. I would also appreciate if this solution was usable with uiBinder.

Use TableLayout
Usage example:
public class TableForm extends ContentPanel{
setLayout(new TableLayout(2)); // number of columns in the table
Button button1 = new Button(); // any widget, button is just example
Button button2 = new Button();
add(button1,new TableData("100%","100%")); // width and height
add(button2,new TableData("100%","100%"));
}
Number in TableLayout's constructor is number of columns - layout automatically organizes your widgets in specified number of columns. You have to only perform add() operation.
Note, that usually it's better not to set height. In such case, widget's height will be default. Otherwise, it will be stretched to the specified percents.
One more advice - use setBorder(int width) (width>0) method of TableLayout to see how exactly TableLayout organized your components. Also, TableData objects has rowspan and colspan properties - you may find it useful.

Related

Disable JFace TableViwer single row

Does anyone know how to disable a single row of a JFace TableViwer? I have a TableViwer constructed as follows:
TableViwer tv = new TableViwer(composite, SWT.NONE| SWT.FULL_SELECTION | SWT.BORDER);
tv can have many rows, but I am adding a particular unique row to the table dynamically(when an external button is clicked) and I need to make only that row disabled (grayed out and not selectable. Not selectable can also be achieved through existing handler, if there is no other option).
I searched in google but did not get much information. I am new to SWT/JFace, so any help would be appreciated.
You would have to do something in the selection listener to reject selection of the row.
To make the row gray you can make your Label Provider implement IColorProvider which lets you define the two methods:
public Color getForeground(Object element);
public Color getBackground(Object element);
which can color the row.
You could also use a label provider derived from StyledCellLabelProvider which lets you define more complex coloring.

GWT - What layout can help for expense report by quarter

I need to create a quarterly expense report and I am confused what layout and widgets would be useful here
Quarter 1 Quarter 2 Quarter 3
Expense 1
Expense 2
Expense 3
I understand Celltable and DataGrids, but not sure If I can have data mappings of objects in the format as above. Mainly because these tables work with objects at a row level.
I have an object with data of the entire column instead.
Any ideas/ suggestions here ?
You have many options to choose from. The most obvious one is a FlexTable, but you can also simply put three floating FlowPanels next to each other.
With GWT you should use HTML for your layouts as much as possible unless you need some specific functionality from a widget.
EDIT:
Alternatively, you can use a DataGrid with a single row, where each cell is a custom cell that renders your object.
Finally, you can use DataGrid as a regular DataGrid - just modify the logic of what is displayed in each cell. For example, a cell can render like this:
final TextColumn<Integer> quarterColumn = new TextColumn<Integer>() {
#Override
public String getValue(Integer row) {
int column = myDataGrid.getColumnIndex(quarterColumn);
QuarterObject object = quarterObjects(column - 1);
return object.getExpense(row - 1);
}
};
Then you simply populate your DataProvider with an array of Integers from 1 to the number of records in your QuarterObject.

GWT drag and drop animation

I have a flow panel with many photo-widgets inside (gallery with random number of rows and columns, depends on screen size) for which I want to implement drag and drop behavior to change their order. I am using gwt-dnd library. Its FlowPanelDropController allows you to define your own positioner (delimiter) which shows the candidate location for dropping the dragged widget.
I want this positioner to be the empty space with defined width, and the challenging thing is to implement sliding animation effect for the when positioner is added and removed.
If you are a desktop Picasa app user you know what I mean: the target row slides both sides (little to the left, little to the right) extending the space between the items where you are going to drop a photo.
The whole thing is complex enough, but any help related to how to apply the animation for positioner attach/detach is appreciated. Maybe I need to use a different approach (e.g., use GWT native dnd instead of gwt-dnd lib and no "positioners" at all) if you have any ideas how this could be helpful.
Thanks.
Well, I ended up overriding AbstractPositioningDropController (parent of FlowPanelDropController) and adding some extra features.
1) newPositioner() method now builds the Label, which is vertical space with some small width, height and decoration. This widget's element has constant id (say, "POSITIONER"), which helps to distinguish between multiple positioners if you plan to have several of them while navigating with a drag object over multiple drop targets. Also some transition CSS effects were applied to the Label, which will be responsible for handling animated extension of Label's width.
2) in onEnter() I do the following
...
removePositioner(getPositionerElement());
Widget positioner = newPositioner();
dropTarget.insert(positioner, targetIndex);
animatePositionerExtension();
where getPositionerElement() returns DOM.getElementById(POSITIONER)
At the same time removePositioner(..) resets the id of this element to something abstract and ideally should provide some animation before calling .removeFromParent(). But I didn't have enough time to properly debug this so ended up just removing the old positioner with no animation.
Method animatePositionerExtension() contains the code that changes the width of the positioner widget, so that CSS transition will catch that and provides animation.
All access to positioner widget in the class should be provided through updated methods.
3) onLeave() contains line removePositioner(getPositionerElement());
4) In the end of onMove() I added a couple of lines:
galleryWidget.extendHoveredRow(targetIndex - 1);
animatePositionerExtension();
where extendHoveredRow(hoveredWidgetOrdinal) implemented the logic to "limit" the sliding effect in the single line:
int rowHovered = -1;
public void extendHoveredRow(int hoveredWidgetOrdinal) {
int newRowHovered = getRowByOrdinalHovered(hoveredWidgetOrdinal);
if (rowHovered != newRowHovered) {
// adjust position of items in the previously hovered row
int firstInPreviouslyHoveredRow = (rowHovered - 1) * itemsInARow;
shiftFirstItemLeft(firstInPreviouslyHoveredRow, false);
rowHovered = newRowHovered;
// extend this row
int firstInThisRow = getOrdinalFirstInThisRowByOrdinal(hoveredWidgetOrdinal);
shiftFirstItemLeft(firstInThisRow, true);
}
}
This is in short how I did the thing. And still there's some room for improvements, like adding animated removal.
Again, it's all about overriding DropController and manipulations with elements inside the "gallery" widget. The benefit of this approach is that I remain in the gwt-dnd operations framework, and also reused a bunch of existent code.
Some notes:
CSS transition is not supported in IE pre-9, but this is unrelated to
this topic.
Put a transparent "glass" div on top of the Image widget if you use it
as a face of dragProxy. This will save you tons of time trying to
understand why either setting element's draggable to false, or
calling event.preventDefault() somewhere else, or other workarounds don't work in one or several browsers and the image itself is being dragged instead of the whole dragProxy widget.

Gwt get Components

I have a Vertiacal panel object and This object contains many radiobuttons
So can i get those radioButton objects through Vertiacal panel object.
Maybe via iteration or ?
private void initCourse() {
coursePopupPanel.clear();
VerticalPanel verticalPanel = new VerticalPanel();
coursePopupPanel.setWidget(verticalPanel);
JsArray<JCourse> jCourseArray = JCourse.getList(stringMainData);
for (int i = 0; i < jCourseArray.length(); i++) {
final RadioButton courseRadioButton = new RadioButton("course");
courseRadioButton.setText(jCourseArray.get(i).getName());
courseRadioButton.getElement().setId(jCourseArray.get(i).getView());
verticalPanel.add(courseRadioButton);
//handler of course radio buttons
courseRadioButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
}
});
}
}
I have a reference to coursePopupPanel. but i have not reference to vertical panel, so can i get elements of vertical panel sonce holding reference to coursePopupPanel.
A GWT VerticalPanel is a subclass of ComplexPanel, an abstract class for Panels that contain more than one child widget. In ComplexPanel (and so inherited by VerticalPanel) are methods for getting the number of child widgets, getting references to them by index, and so on. You could build an iterator something like this:
Iterator<Widget> vPanelWidgets = myVerticalPanel.iterator();
while (vPanelWidgets.hasNext()){
Widget childWidget = vPanelWidgets.next();
if (childWidget instanceof RadioButton) {
...do stuff
}
}
I tend not to query a widget for its members. That ties me to the decisions I made about how to display the RadioButtons, following your example. What if you decide later to display your radio buttons in the cells of a FlexTable in order to control vertical and horizontal arrangement? To make that change means your widget iterator won't work. FlexTable is a Panel but not a ComplexPanel. The code I wrote above won't work if you decide to replace the VerticalPanel with a FlexTable.
If was to take something like this approach, I would keep my lists of related widgets (like a group of RadioButtons) in some sort of Java Collection. I pass that Collection to my presentation class, and inside there I write the code to do the layout. Usually that's a UiBinder class, with "#UiField(provided = true)" for these RadioButtons. The code in the presenter then associates the RadioButton elements of the Collection I passed in to the UiField placeholders for the RadioButtons in the UiBinder layout. So all my layout decisions are actually in the UiBinder xml file. If I decide to rip out my Vertical Panel and replace it with a FlexTable, I might not have to touch a single line of Java code, assuming I separated things out correctly.
[Actually, I would probably keep my decision to use RadioButtons inside the presentation layer, and inside the XML file in particular. That presentation class would fire a message on the EventBus to indicate the user had made a selection via a RadioButton ValueChangeHandler, and I wouldn't care if I used RadioButtons in a VerticalPanel or ToggleButtons in a FlexTable.]
You're not being to specific, add more details and maybe a code example.
I'm gonan try to guesstimate what you're trying to say here: You have a verticalPanel object. To it you add several radioButton objects. Later you want to retrive those radioButton objects (to maybe check if they're selected or not), right? There's several ways to do this. At any rate, why don't you check the code examples at the Gwt Showcase site here:
http://gwt.google.com/samples/Showcase/Showcase.html?locale=en_UM#!CwRadioButton
it has tons of visual examples, each with the attached code and css.
Since PopupPanel implements HasOneWidget interface you can coursePopupPanel.getWidget() to get a reference to your verticalPanel. And iterate widgets in it simply using
for (Widget w : verticalPanel){
//Do Stuff
}

GWT Accessing Widget Methods without knowing the name of the Widget

This may have been asked before but I have no idea how to word it to search for it.
I have a composite widget that has methods to update some of the widgets that make up the composite widget. When I add this composite widget to my panel I use a do while loop to pull data from an XML file and populate the composite data. When I instantiate the object each time to add the data it has a scope local to the do-while loop and I cannot call methods to update the data in the composite widget later on. Is there maybe a way to make an array of these composite widgets or another solution to be able to access the Widget?
Eric
Sure... use
List<Composite> widgetList = new ArrayList<Composite>();
// loop
widgetList.add(widget);
// end loop
widgetList.get(3).toString();
You'll want to use your custom class instead of Composite in the list generic... there's nothing stopping you from making data structures using widgets, just like you would with any other Java class.
If you are putting all your Widgets in that loop into one panel (presumably on of the subclasses of ComplexPanel, since you are adding many Widgets to one panel), then you could use one of the methods to access Widgets contained within a panel (assuming you add only those XML generated Widgets to the panel and nothing more):
com.google.gwt.user.client.ui.ComplexPanel.iterator() - returns an java.util.Iterator<Widget> you can use to traverse the list of Widgets within that Panel
com.google.gwt.user.client.ui.ComplexPanel.getWidgetCount() and getWidget(int index) can be used in a for loop to go through all the Widgets within a panel
So, let's look at an example:
VerticalPanel vPanel = new VerticalPanel();
// Fill up the vPanel using XML
Iterator<Widget> iterator = vPanel.iterator();
while(iterator.hasNext()) {
Widget w = iterator.next();
// Do something with w
}
// Or...
for (int i = 0; i < vPanel.getWidgetCount(); i++) {
Widget w = vPanel.getWidget(i);
// Do something with w
}
Of course, substitute VerticalPanel with the one you are you using :)
I definately recommend that you watch "Best Practices for Architecting GWT App" (from Google I/O 2009):
http://www.youtube.com/watch?v=PDuhR18-EdM
At about 24 minutes through it talks about how to write composite widgets using the MVP design pattern - although you should watch it all. Unfortunately it does not provide ready to use code snipets, but it does show you how to construct a framework to decouple your XML and UI objects nicely.