How to set item renderer for ListView in ext-gwt? - gwt

I have a ListView in ext-gwt and I'm adding some custom data to it. How can I set an item renderer on the ListView? As of right now, whenever an item is added, there's just a small line representing each entry in the view.
Here's my basic code:
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ListView;
import com.foo.bar.FooModelData;
private final ListStore<FooModelData> listStore =
new ListStore<FooModelData>();
private final ListView<FooModelData> listView =
new ListView<FooModelData>();
public initializeView()
{
listView.setStore(listStore);
listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
}
public void addItem(FooModelData data) {
listStore.add(data);
}
public class FooModelData extends BaseModel
{
public ModelDataInstance(Foo foo, String style)
{
setFoo(foo);
setStyle(style);
}
public String getStyle()
{
return get("style");
}
public Foo getFoo()
{
return (Foo) get("foo");
}
public void setStyle(String style)
{
set("style", style);
}
public void setFoo(Foo foo)
{
set("foo", foo);
}
}
Thanks for all help!

GXT uses a templating implementation.
Using a simplified version of the Sencha explorer example you could use your data as follows (foo.name assumes foo is also a model:
public initializeView()
{
listView.setStore(listStore);
listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
listView.setTemplate(getTemplate());
}
private native String getTemplate() /*-{
return ['<tpl for=".">',
'<div class="{style}">{foo.name}</div>',
'</tpl>',
'<div class="x-clear"></div>'].join("");
}-*/;

Related

Breaking cyclic dependency in Dagger

I am very new to dagger--I don't even know yet if it will work for my application
I have a search page that returns the latest news about a given celebrity.
I have written a test to verify that results appear on the page when we search for a popular celebrity.
The page has a searchField, which requires page in its constructor so the web driver I use for my tests can select it.
Celebrity Search Page Test
public class CelebritySearchPageTest {
#Test
public void testSearchResultsForKevinBaconVerifyHisPopularity() {
CelebritySearchPage searchPage = new CelebritySearchPage();
searchPage.searchFor("Kevin Bacon");
Assert.assertTrue(searchPage.getNumberOfResults() > 9999999, "Verify that Kevin Bacon is still relevant");
}
}
Celebrity Search Page
public class CelebritySearchPage extends Page {
#Inject
#Named("search field")
TextField searchField;
public void searchFor(String text) {
searchField.setText(text);
// ...
}
public int getNumberOfResults() {
// ...
}
}
Celebrity Search Page Module
#Module(injects = CelebritySearchPage.class)
public class CelebritySearchPageModule {
#Provides
#Named("search field")
public TextField provideSearchField() {
return new TextField(/* How do I get the page? */, "#searchField");
}
}
Page
public abstract class Page {
// ...
}
Text Field
public class TextField {
protected Page page;
protected String selector;
public TextField(Page page, String selector) {
this.page = page;
this.selector = selector;
}
public void setText(String text) {
// ...
}
}
The problem is that page needs searchField, but searchField needs page. How do I get over this cyclic dependency?
I can't initialize searchField inside of CelebritySearchPage
Consider this:
CelebritySearchPage
public class CelebritySearchPage extends Page {
private final Lazy<TextField> searchField;
// always prefer constructor injection
// avoid #Named if possible, since the compiler cannot check the string
#Inject
CelebritySearchPage(#Named("search field") Lazy<TextField> searchField) {
this.searchField = searchField;
}
}
Text Field
public class TextField {
protected final Lazy<Page> page;
protected final String selector;
#Inject TextField(Lazy<Page> page, String selector) {
this.page = page;
this.selector = selector;
}
/*
Lazy::get()
Return the underlying value, computing the value if necessary. All calls to the same Lazy instance will return the same result.
*/
}
I guess one Lazy should suffice as well.

Custom Renderer in GWT

I'm trying to create a widget that will render its associated value in a format that is not the same as the native value. For example, if the value (in the database) is "abcde" I want to show "ab.cd.e" on the screen, and if the user types "abcde" I would also want to show "ab.cd.e". If the user types "ab.cd.e" then I would want to store just "abcde" in the database. I am doing this within the GWT editor framework. I have attempted to use the advice from this answer: Converting String to BigDecimal in GWT, but I can't get it to work. Here's what I have in the UiBinder file:
<g:TextBox ui:field='myTextBox' width='300px'/>
And in the associated Java unit:
#UiField
TextBox myTextBox;
...
initWidget(binder.createAndBindUi(this));
new MyValueBox(myTextBox);
And here's the definition of the MyValueBox widget:
public class MyValueBox extends ValueBox<String> {
//=========================================================================
public static class MyRenderer extends AbstractRenderer<String> {
private static MyRenderer _instance;
private static MyRenderer instance() {
if (_instance == null) {
_instance = new MyRenderer();
}
return _instance;
}
#Override
public String render(final String text) {
// validation is required before doing this!
return text.substring(0, 2) + "." + text.substring(2, 4) + "."
+ text.substring(4);
}
}
//=========================================================================
public static class MyParser implements Parser<String> {
private static MyParser _instance;
private static MyParser instance() {
if (_instance == null) {
_instance = new MyParser();
}
return _instance;
}
#Override
public String parse(final CharSequence text) throws ParseException {
return "parsed string";
}
}
//=========================================================================
public MyValueBox(final TextBox valueBox) {
super(valueBox.getElement(), MyRenderer.instance(), MyParser.instance());
}
}
As you can see, I'm trying to wrap the TextBox that was created using UiBinder, but I don't see any effect from this. I know that I'm missing something very simple, and that there is a much easier way to accomplish this, but I'm stumped. Thank you for any suggestions!
--Edit--
I eventually decided to use a CellWidget, which had the added advantage that I can use this code in a cell widget (e.g., a DataGrid), in addition to using it on a panel. I have documented my solution here: GWT: A Custom Cell Example
You are missing to declare your custom Widget in the UIBinder. You need to tie the package to the xml declaration, adding yours to the standard one (called 'g'):
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:myurn='urn:import:mypackage'>
Then you should use your declared urn, and the name of your class when declaring your TextBox in the UIBinder:
<myurn:MyValueBox ui:field='myTextBox' width='300px'/>
======EDIT=====
You should extend ValueBoxBase instead of wrapping TextBox, that way you will get control over the Renderer and the Parser as you intend, now you will be able to use your custom box as a widget from within the UIBinder:
public class CustomText extends ValueBoxBase<String>
{
public CustomText() {
super(Document.get().createTextInputElement(),CustomRenderer.instance(),
CustomParser.instance());
}
private static class CustomRenderer extends AbstractRenderer<String>
{
private static CustomRenderer INSTANCE;
public static CustomRenderer instance() {
if (INSTANCE == null) {
INSTANCE = new CustomRenderer();
}
return INSTANCE;
}
#Override
public String render(String text)
{
return "rendered string";
}
}
private static class CustomParser implements Parser<String>
{
private static CustomParser INSTANCE;
public static CustomParser instance() {
if (INSTANCE == null) {
INSTANCE = new CustomParser();
}
return INSTANCE;
}
#Override
public String parse(CharSequence text) throws ParseException
{
return "parsed string";
}
}
}

ButtonCell in CellTable footer only works in first column

I have a cell table with a custom button as a footer in one of the columns which works fine. But when I try to move the button to another column the clickevent (valueupdater) of the button does not work anymore. I simply add the button as a footer in another column no changes in the functionality are done! Here is how its done:
public class TestCellTable extends CellTable<Object> {
...
public TestCellTable() {
...
addFirstColumn();
addSecondColumn();
addThirdColumn();
...
}
public static abstract class FooterButton extends Header<String> {
public ButtonFooter(ValueUpdater<String> value) {
super(new ButtonCell());
this.setUpdater(value);
}
}
private Header<String> initButton() {
ValueUpdater<String> updater = new ValueUpdater<String>() {
#Override
public void update(String value) {
Window.alert("TEST");
}
};
Header<String> footer = new FooterButton(updater) {
#Override
public String getValue() {
return "TEST";
}
};
return footer;
}
public void addFirstColumn() {
...
addColumn(COLUMN, HEADER, initButton());
}
public void addSecondColumn() {
...
addColumn(COLUMN, HEADER);
}
public void addThirdColumn() {
...
addColumn(COLUMN, HEADER);
}
}
I just would like to move the button from the first Column to the send column but then when I click the button nothing happens??

auto refresh eclipse view

i have created a sample view in eclipse using the following code.i want the view to be
automatically refereshed.the part of code in quotes "" gives refresh option but it is done
manually.can anyone help me know how it can be done automatically
public class SampleView extends ViewPart {
public static final String ID = "tab.views.SampleView";
private TableViewer viewer;
class ViewContentProvider implements IStructuredContentProvider {
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
}
public void dispose() {
}
public Object[] getElements(Object parent) {
return new String[] { "Status of your hudson build is: " +hudson.d};
}
}
class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {
public String getColumnText(Object obj, int index) {
return getText(obj);
}
public Image getColumnImage(Object obj, int index) {
return getImage(obj);
}
public Image getImage(Object obj) {
return PlatformUI.getWorkbench().
getSharedImages().getImage(ISharedImages.IMG_OBJ_ADD);
}
}
public SampleView() {
}
public void createPartControl(Composite parent) {
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new ViewLabelProvider());
viewer.setInput(getViewSite());
PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), "Tab.viewer");
hookContextMenu();
}
" private void hookContextMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu");
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
Action refresh =new Action() {
public void run() {
// initialize();
viewer.refresh();
}
};
refresh.setText("Refresh");
menuMgr.add(refresh);
}"
public void setFocus() {
viewer.getControl().setFocus();
}
}
It is only possible to refresh the tree contents automatically, if you fill it using JFace Data Binding, that would not work with remote build results.
I recommend either using a model with notification support: when the model changes, its listeners are notified. Then your view could listen for these notifications and refresh itself.
If for some reason this is not possible, you have to poll your models manually. For that I recommend creating a Job that is executed in the background automatically (its last step is to reschedule itself some times later), that checks whether the model changed and refreshes the view.

GWT ValueListBox Editor

I'm puzzled about how to use GWT's ValueListBox with an Editor. I'm getting this ERROR:
The method setValue(String) in the type TakesValueEditor<String>
is not applicable for the arguments (List<String>)
Here's the relevant code.
public class MyBean {
private List<String> dateFormats;
public List<String> getDateFormats() {
return dateFormats;
}
public void setDateFormats(List<String> dateFormats) {
this.dateFormats = dateFormats;
}
}
public interface MyBeanView extends IsWidget, Editor<MyBean> {
#Path("dateFormats")
IsEditor<TakesValueEditor<String>> getDateFormatEditor();
}
public class MyBeanViewImpl implements MyBeanView {
#UiField(provided=true) ValueListBox<String> dateFormats;
public MyBeanViewImpl() {
dateFormats = new ValueListBox<String>(PassthroughRenderer.instance(),
new ProvidesKey<String>() {
#Override
public Object getKey(String item) {
return item;
}
});
dateFormats.setAcceptableValues(Arrays.asList(new String[] {"YYYY"}));
// ... binder.createAndBindUi(this);
}
#Override
public IsEditor<TakesValueEditor<String>> getDateFormatEditor() {
return dateFormats;
}
}
Here's what's in ui.xml with xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:HTMLPanel>
Data Formats: <g:ValueListBox ui:field="dateFormats"> </g:ValueListBox>
</g:HTMLPanel>
I'm surely missing something obvious here. Much thanks.
The problem that you're running into has to do with trying to map the List<String> dateFormats from MyBean onto the ValueListBox<String> dateFormats editor. The datatypes are incompatible, since a ValueListBox<T> doesn't edit a List<T>, but instead a single instance of T chosen from a list provided by setAcceptableValues(). Given the example above, it would make sense for MyBean to have a String getDateFormat() property and rename the editor field to dateFormat.