Custom Composite design view and nested classes

GWT Designer allows you to quickly create the modules, composites, panels, remote services and other elements that comprise Google Web Tookit applications.

Moderators: Konstantin.Scheglov, gnebling, Alexander.Mitin, jwren, Eric Clayberg

Custom Composite design view and nested classes

Postby peterblazejewicz » Sun Jan 20, 2008 12:08 pm

hi team,

What are D&D or design decisions for custom Composite design class requiremenets in Design view? (when creating and editing class ui in Design view, not when using it in other component context),

for example that works:
Code: Select all
package com.mycompany.project.client;

import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;

public class MyComposite extends Composite {

   static class MyLabel extends Label {
      public MyLabel() {
         super();
         setText("My Label");
      }
   }

   private FlowPanel flowPanel;

   private Label label;

   public MyComposite() {

      flowPanel = new FlowPanel();
      initWidget(flowPanel);

      label = new MyLabel();
      flowPanel.add(label);
   }

}

inner class is static,

that does not:
Code: Select all
package com.mycompany.project.client;

import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;

public class MyComposite extends Composite {

   class MyLabel extends Label {
      public MyLabel() {
         super();
         setText("My Label");
      }
   }

   private FlowPanel flowPanel;

   private Label label;

   public MyComposite() {

      flowPanel = new FlowPanel();
      initWidget(flowPanel);

      label = new MyLabel();
      flowPanel.add(label);
   }

}

non-static inner class,
that throws errors in Design view when designing component:
[quote]!ENTRY com.swtdesigner 4 4 2008-01-20 21:42:28.552
!MESSAGE Designer internal error [6.5.1.20080117125226]: java.lang.reflect.InvocationTargetException
!STACK 0
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
[....]
[...]
Caused by: java.lang.NullPointerException
at com.google.gwt.user.client.ui.ComplexPanel.add(ComplexPanel.java:76)
at com.google.gwt.user.client.ui.FlowPanel.add(FlowPanel.java:43)
... 56 more[/code]
non static member class works fine when custom composite is used in Design view in context of other component (e.g. when using in EntryPoint view),

regards,
Peter
Peter Blazejewicz
GWT groups profile
peterblazejewicz
 
Posts: 153
Joined: Fri Jul 27, 2007 7:09 pm
Location: Europe/Poland/Warsaw

Re: Custom Composite design view and nested classes

Postby Konstantin.Scheglov » Mon Jan 21, 2008 12:02 am

In general it is bad to use inner GUI classes.

1. To create instance of non-static inner class you need to have instance of containing class, but Designer does not have it. Instead Designer just parses source and then evaluates AST. So, non-static inner classes are not supported.

2. Static inner class is not different from top level class.
Konstantin.Scheglov
Moderator
 
Posts: 186
Joined: Tue Oct 18, 2005 8:11 pm
Location: Russian Federation, Lipetsk

Re: Custom Composite design view and nested classes

Postby peterblazejewicz » Fri Jan 25, 2008 2:29 pm

hi Konstantin,
thanks for previous reply,

so does the same apply to custom code added to entry point?

example:

code with static methods which is working in Design view:

Code: Select all
package us.bram.progressbar.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;

import us.bram.progressbar.widget.JSProgressBarOptions;
import us.bram.progressbar.widget.ProgressBar;

/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class ProgressBarDemo implements EntryPoint {

  public void onModuleLoad() {
    RootPanel rootPanel = RootPanel.get();
    // default constructor with default options
    final ProgressBar progressBar = new ProgressBar();
    rootPanel.add(progressBar);
    progressBar.setPercentage(100);
    // default options passed in constructor
    final ProgressBar progressBar2 = new ProgressBar(getDefaultOptions());
    rootPanel.add(progressBar2);
    progressBar2.setPercentage(55);
    // custom bar options passed in constructor
    final ProgressBar progressBar3 = new ProgressBar(getCustomOptions());
    rootPanel.add(progressBar3);
    progressBar3.setPercentage(25);
  }

  private static JSProgressBarOptions getDefaultOptions() {
    JSProgressBarOptions options = new JSProgressBarOptions();
    return options;
  };

  private static JSProgressBarOptions getCustomOptions() {
    JSProgressBarOptions options = new JSProgressBarOptions();
    options.showText = false;
    options.width = 154;
    options.height = 11;
    options.boxImage = "images/bramus/custom1_box.gif";
    options.barImage = "images/bramus/custom1_bar.gif";
    return options;
  };
}


code not working in design view is using instance methods:
Code: Select all
private JSProgressBarOptions getDefaultOptions() {
  JSProgressBarOptions options = new JSProgressBarOptions();
  return options;
};

private JSProgressBarOptions getCustomOptions() {
  JSProgressBarOptions options = new JSProgressBarOptions();
  options.showText = false;
  options.width = 154;
  options.height = 11;
  options.boxImage = "images/bramus/custom1_box.gif";
  options.barImage = "images/bramus/custom1_bar.gif";
  return options;
};


I have to somehow instruct widget about its default properties (background/foregraound iamge/width/hegith, etc) which are not to be set via getters/setters,

regards,
Peter
Peter Blazejewicz
GWT groups profile
peterblazejewicz
 
Posts: 153
Joined: Fri Jul 27, 2007 7:09 pm
Location: Europe/Poland/Warsaw

Re: Custom Composite design view and nested classes

Postby Konstantin.Scheglov » Fri Jan 25, 2008 11:46 pm

Here situation is different, because here Designer need to create pre-configure components.
You can use "static factory", see code examples below.
Unfortunately, right now Designer can not generate such code.
But we are working on this. :-)

Note that there is @wbp.factory JavaDoc comment, I use it to be "forward compatible" with future versions of Designer. When you set this tag for class, you tell Designer that all methods are static factories. Alternatively, you can set it on per-method basis.

Code: Select all
package com.mycompany.project.client;

import com.google.gwt.user.client.ui.CheckBox;

/**
* @wbp.factory
*/
public class StaticFactory {
   public static CheckBox createCheckBox() {
      CheckBox checkBox = new CheckBox();
      checkBox.setText("Default text");
      checkBox.setChecked(true);
      return checkBox;
   }
}



Code: Select all
package com.mycompany.project.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.RootPanel;

/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class ImageViewer implements EntryPoint {
   public void onModuleLoad() {
      RootPanel rootPanel = RootPanel.get();

      CheckBox checkBox = StaticFactory.createCheckBox();
      rootPanel.add(checkBox, 50, 50);
   }
}
Attachments
Screenshot - 26.01.2008 , 11_21_17.png
Screenshot - 26.01.2008 , 11_21_17.png (25.23 KiB) Viewed 2135 times
Konstantin.Scheglov
Moderator
 
Posts: 186
Joined: Tue Oct 18, 2005 8:11 pm
Location: Russian Federation, Lipetsk

Re: Custom Composite design view and nested classes

Postby peterblazejewicz » Sat Jan 26, 2008 3:20 pm

hi Konstantin,
thanks again for help and information,

here is what I've done using your post:

Iv'e written java implementation of ajax progress bar by bramus:
http://www.bram.us/projects/js_bramus/j ... arhandler/
which can be used via D&D in Desinger or in handcoded code and also used as decorator for span elements on web page,

using your information I've modified constructors and factory methods in progress bar class:
Code: Select all
public ProgressBar() {
  this(ProgressBar.options.copy());
}

ProgressBar(ProgressBarOptions options) {
  setElement(DOM.createSpan());
  setStyleName("bramus-JSProgressBar");
  impl = new ProgressBarImpl(getElement(), options);
}

public one is used by Designer via D&D with all default options, second one (default scoped) is used by factory method:
Code: Select all
public static ProgressBar createProgressBar(ProgressBarOptions options) {}


I've also written factory data class that way using your template:
Code: Select all
package us.bram.jsprogressbar.example.client;

import us.bram.jsprogressbar.ProgressBarOptions;
import us.bram.jsprogressbar.ProgressBar;

/**
* @wbp.factory
*/
public class ProgressBarFactory {
  /**
   * static initializer to set default options (here we just reset defaults to
   * configuration)
   */
  static {
    ProgressBarFactory.setDefaultOptions();
  }

  /**
   * @return instance of {@link ProgressBar} with OSX Aqua like progress bar
   */
  public static ProgressBar createAquaProgressBar() {
    ProgressBarOptions options = getAquaBarOptions();
    return ProgressBar.createProgressBar(options);
  }

  /**
   * @return instance of {@link ProgressBar} with 4 color based progress bar
   */
  public static ProgressBar createColoredProgressBar() {
    ProgressBarOptions options = getColoredBarOptions();
    return ProgressBar.createProgressBar(options);
  }

  /**
   * @return instance of {@link ProgressBar} using default configuration
   */
  public static ProgressBar createDefaultProgressBar() {
    ProgressBar pb = new ProgressBar();
    pb.setProgress(70);
    return pb;
  }

  /**
   * @return instance of {@link ProgressBar} with red progress bar
   */
  public static ProgressBar createRedProgressBar() {
    ProgressBarOptions options = getRedBarOptions();
    return ProgressBar.createProgressBar(options);
  }

  /**
   * @return options for custom OSX Aqua like progress bar
   */
  public static ProgressBarOptions getAquaBarOptions() {
    ProgressBarOptions options = ProgressBar.getDefaultOptions();
    options.width = 154;
    options.height = 11;
    options.boxImage = "images/bramus/example/custom1_box.gif";
    options.barImages = new String[] {"images/bramus/example/custom1_bar.gif"};
    return options;
  }

  public static ProgressBarOptions getColoredBarOptions() {
    ProgressBarOptions options = ProgressBar.getDefaultOptions();
    options.animate = false;
    options.percentage = 70;
    options.barImages = new String[] {
        "images/bramus/example/percentImage_back4.png",
        "images/bramus/example/percentImage_back2.png",
        "images/bramus/example/percentImage_back1.png",
        "images/bramus/example/percentImage_back3.png"};
    return options;
  }

  /**
   *
   * @return options for red colored bar
   */
  public static ProgressBarOptions getRedBarOptions() {
    ProgressBarOptions options = ProgressBar.getDefaultOptions();
    options.barImages = new String[] {"images/bramus/example/percentImage_back3.png"};
    return options;
  }

  /**
   * static factory method to reset default configuration option for
   * {@link ProgressBar}
   */
  public static void setDefaultOptions() {
    ProgressBarOptions options = ProgressBar.getDefaultOptions();
    options.animate = true;
    options.barImages = new String[] {"images/bramus/percentImage_back.png"};
    options.boxImage = "images/bramus/percentImage.png";
    options.height = 12;
    options.showText = true;
    options.width = 120;
    options.percentage = 0;
    ProgressBar.setDefaultOptions(options);
  }
}


generated (in Design view) and handcoded code looks like:
Code: Select all
/**
*
*/
public void onModuleLoad() {

  // widgets attached via D&D in Design view
RootPanel rootPanel = RootPanel.get("container");

panel = new VerticalPanel();
rootPanel.add(panel);
panel.setSpacing(10);
final Label label = new Label("Progress bars created in Design view");
panel.add(label);
defaultWidget = new ProgressBar();
panel.add(defaultWidget);
defaultWidget.setAnimated(true);
defaultWidget.setProgress(60);
defaultFromFactory = ProgressBarFactory.createDefaultProgressBar();
panel.add(defaultFromFactory);
defaultFromFactory.setProgress(100);
auqaFromFactory = ProgressBarFactory.createAquaProgressBar();
panel.add(auqaFromFactory);
auqaFromFactory.setProgress(33);
coloredFromFactory = ProgressBarFactory.createColoredProgressBar();
panel.add(coloredFromFactory);
coloredFromFactory.setAnimated(true);
redFromFactory = ProgressBarFactory.createRedProgressBar();
panel.add(redFromFactory);
redFromFactory.setProgress(10);
//
// progress bars attached to existing span elements manually
//
// default widget
ProgressBar.fromElement($("progress1")).setProgress(60);
// default widget from options
ProgressBar.fromElement($("progress2"), ProgressBar.getDefaultOptions()).setProgress(
    100);
// aqua OSX like style configuration
ProgressBar.fromElement($("progress3"),
    ProgressBarFactory.getAquaBarOptions()).setProgress(33);
// colored progress bar
ProgressBar.fromElement($("progress4"),
    ProgressBarFactory.getColoredBarOptions());
// red colored progress bar
ProgressBar.fromElement($("progress5"),
      ProgressBarFactory.getRedBarOptions()).setProgress(10);
}

private static Element $(String id) {
  return DOM.getElementById(id);
}


and here are screenshots:

designView.jpg
Design view in IDE
designView.jpg (69.59 KiB) Viewed 2123 times


hostedModeView.jpg
hosted mode view
hostedModeView.jpg (42.79 KiB) Viewed 2123 times



I hope you'll find it usefull with your futher work you've mentioned,
as you could see I had implementation design issue with public parametrized constructor, It does not work in Design view, so it should be defaulted and instead accessed via static factories,
If we could have public parametrized constructor with non-statically created params that would be nice, but I guess most people could live without that for now :)


regards,
Peter
Peter Blazejewicz
GWT groups profile
peterblazejewicz
 
Posts: 153
Joined: Fri Jul 27, 2007 7:09 pm
Location: Europe/Poland/Warsaw

Re: Custom Composite design view and nested classes

Postby Eric Clayberg » Sun Jan 27, 2008 12:44 pm

That looks really good.

We do plan to add much more sophisticated factory support. You can read about what he have planned here.

This new factory support is curently in beta test with our new eRCP Designer product and will be rolled out to our SWT, Swing and GWT Designer products over the next few months.
Eric Clayberg
Software Engineering Manager
Google
http://code.google.com/webtoolkit/download.html

Author: "Eclipse Plug-ins"
http://www.qualityeclipse.com
Eric Clayberg
Moderator
 
Posts: 4503
Joined: Tue Sep 30, 2003 6:39 am
Location: Boston, MA USA

Re: Custom Composite design view and nested classes

Postby peterblazejewicz » Mon Jan 28, 2008 11:30 am

thx Eric for udpates!
regards,
Peter
peterblazejewicz
 
Posts: 153
Joined: Fri Jul 27, 2007 7:09 pm
Location: Europe/Poland/Warsaw

Re: Custom Composite design view and nested classes

Postby Eric Clayberg » Mon Jan 28, 2008 7:50 pm

I'll let you know when the same support is available for GWT as well.
Eric Clayberg
Software Engineering Manager
Google
http://code.google.com/webtoolkit/download.html

Author: "Eclipse Plug-ins"
http://www.qualityeclipse.com
Eric Clayberg
Moderator
 
Posts: 4503
Joined: Tue Sep 30, 2003 6:39 am
Location: Boston, MA USA

Re: Custom Composite design view and nested classes

Postby peterblazejewicz » Tue Jan 29, 2008 5:48 pm

hi Eric & Konstantin,

Factories apply to generated classes as well:

Code: Select all
package com.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;

/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class GenerateButtonTest implements EntryPoint {
  /**
   * @wbp.factory
   */
  static public MyButton getButton() {
    MyButton b = (MyButton) GWT.create(MyButton.class);
    return b;
  }

  /**
   * @wbp.factory
   */
  static public Image getHomeImage() {
    MyImageBundle bundle = (MyImageBundle) GWT.create(MyImageBundle.class);
    return bundle.home().createImage();
  }

  public void onModuleLoad() {
    RootPanel rootPanel = RootPanel.get();
    Button b = GenerateButtonTest.getButton();
    rootPanel.add(b);
    b.setText("Welcome");
    Image home = GenerateButtonTest.getHomeImage();
    rootPanel.add(home);
  }
}


Code: Select all
<module>
   <inherits name="com.google.gwt.user.User" />
   <entry-point class="com.client.GenerateButtonTest" />
   <generate-with class="com.rebind.ButtonGenerator">
      <when-type-is class="com.client.MyButton" />
   </generate-with>
</module>


com.client.MyButton can be abstract but needs default constructor, etc for Design view,

Am I correct that you have already hooked ImageBundle (and similiar) generators to provide instant "Design" view updates while custom created (generated) wigets are not updated until code is compiled (e.g. in hosted mode)?
Using factory method(s) I can see constant update for image bundle while my class is not updated to what is to be compiled by generator,

thanks,
regards,
Peter
Peter Blazejewicz
GWT groups profile
peterblazejewicz
 
Posts: 153
Joined: Fri Jul 27, 2007 7:09 pm
Location: Europe/Poland/Warsaw

Re: Custom Composite design view and nested classes

Postby Eric Clayberg » Wed Jan 30, 2008 3:54 am

peterblazejewicz wrote:Am I correct that you have already hooked ImageBundle (and similiar) generators to provide instant "Design" view updates while custom created (generated) wigets are not updated until code is compiled (e.g. in hosted mode)?

Yes. GWT Designer has special (parsing) support for important, known GWT generators like ImageBundle, Constants and Messages.

GWT Designer does not provide any special support for generic, unknown GWT generators. Custom widgets are simply instantiated like any other built-in GWT widget, so they do need to be compiled.
Eric Clayberg
Software Engineering Manager
Google
http://code.google.com/webtoolkit/download.html

Author: "Eclipse Plug-ins"
http://www.qualityeclipse.com
Eric Clayberg
Moderator
 
Posts: 4503
Joined: Tue Sep 30, 2003 6:39 am
Location: Boston, MA USA


Return to GWT Designer

Who is online

Users browsing this forum: No registered users and 3 guests