martes, 20 de diciembre de 2011

Example on how easily a javascript native component can be embedded natively in an gwt widget

I needed to use a wysiwyg editor in my gwt application. Tried some sollutions, but none worked, so I decided to develop a gwt widget with ckeditor inside, and with support for gwt editor framework.

In the following example, I will create an html file that loads ckeditor javascript before the gwt application javascript is loaded:


<!doctype html>

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<title>Web Application Starter Project</title>

<script type="text/javascript" language="javascript"
src="js/ckeditor/ckeditor.js"></script>

</head>

<body>

<script type="text/javascript" language="javascript"
src="circulares2/circulares2.nocache.js"></script>

<div id="uniqueID"></div>

</body>
</html>



Then the following is the code for the ckeditor gwt widget, with support for gwt editor framework:


package com.beeblos.portlet.circulares2.gwt.client.util;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.TextAreaElement;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextArea;

/**
* ckeditor.js must be already loaded, put it in .
* @author sg
*
*/
public class CKEditor extends SimplePanel implements LeafValueEditor {

String _id=null;
private String text;
private TextAreaElement ta;
static Integer idCounter=0;

public CKEditor(String text) {
idCounter++;
_id="ckEditorWidget_"+idCounter;
this.text=text;

initGui();
}

private void initGui() {
ta = Document.get().createTextAreaElement();
ta.getStyle().setWidth(100, Unit.PCT);
ta.getStyle().setHeight(100, Unit.PCT);
ta.setId(_id);
getElement().appendChild(ta);
}

@Override
public void setValue(String value) {
this.text=value;
this._setText(_id, value);
}
@Override
public String getValue() {
return _getText(_id)+"";
}
protected native void _setText(String id, String value)/*-{
if($wnd.CKEDITOR && $wnd.CKEDITOR.instances && $wnd.CKEDITOR.instances[id])
$wnd.CKEDITOR.instances[id].setData(value);
}-*/;
protected native Object _getText(String id) /*-{
if(!$wnd.CKEDITOR || !$wnd.CKEDITOR.instances || !$wnd.CKEDITOR.instances[id])
return "";
else
return $wnd.CKEDITOR.instances[id].getData();
}-*/;

@Override
protected void onLoad() {
super.onLoad();
_loadCKEditor(_id, getCkEditorConfig());
ta.getStyle().setDisplay(Display.NONE);
if(Util.notNull(text))
this._setText(_id, text);
}

protected native Object getCkEditorConfig() /*-{
return {
toolbar : 'Basic',
uiColor : '#9AB8F3'
};
}-*/;

private static native void _loadCKEditor(String id, Object config) /*-{
$wnd.CKEDITOR.replace(id, config);
}-*/;
}



Note how I use the gwt widget's onLoad for loading native ckeditor inside the widget, because I need gwt to be fully loaded before adding native ckeditor. Also, note that you can extend this class for indicating a custom ckeditor configuration, for example:


public class CkEditorNormal extends CKEditor {
public CkEditorNormal(String text) {
super(text);
}

protected native Object getCkEditorConfig() /*-{
return {};
}-*/;
}



Hope this helps somebody to develop / integrate its own javascript toolkits as gwt widgets or in gwt projects.

lunes, 19 de diciembre de 2011

gwt editor framework, 100% java example

I'm learning gwt, and found gwt editor framework and it seems very promising technology for doing gui. Nevertheless, there are little documentation available for gwt begginers, and all the examples uses gwt UIBinder, which I'm not.



So, this is a gwt module file, that contains a simple model class, a simple gwt editor for that model class, and a example of using it for displaying and let the user edit the model. No UIBinder, all the GUI was made in java using gwt eclipse editor. Enjoy!





package com.beeblos.portlet.circulares2.gwt.client;

import com.google.gwt.core.client.*;
import com.google.gwt.editor.client.*;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.*;

/**
* entry point testing gwt editor framework. 100% java code, no UIBinder...
* @author: sgurin
*/
public class Circulares2 implements EntryPoint {


public static class Person {
String name;
Integer age;
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}

/**
* the perdon's editor. Note that it has 2 non private attributes with the exact name
* as the Person's attributes.
*
* @author sg
*
*/
public class PersonEditor extends SimplePanel implements Editor {
TextBox name;
IntegerBox age;

public PersonEditor() {
Grid grid = new Grid(2, 2);
setWidget(grid);
grid.setSize("100%", "100%");

Label lblNewLabel = new Label("name");
grid.setWidget(0, 0, lblNewLabel);

name = new TextBox();
grid.setWidget(0, 1, name);

Label lblAge = new Label("age");
grid.setWidget(1, 0, lblAge);

age = new IntegerBox();
grid.setWidget(1, 1, age);
}
}

// Empty interface declaration, similar to UiBinder
interface Driver extends SimpleBeanEditorDriver {}


public void onModuleLoad() {

/* this is the main entry point of our gwt application.
* Here we instance the editor (a gwt panel), a sample
* instance object (a person) and a editor driver, the
* object that will let us link the data with the editor */

RootPanel rootPanel = RootPanel.get("uniqueID");


// Create the editor's Driver
final Driver driver = GWT.create(Driver.class);

//create a sample model object
Person p = new Person("john", 22);

// PersonEditor is a DialogBox that extends Editor
PersonEditor editor = new PersonEditor();
// Initialize the driver with the top-level editor
driver.initialize(editor);
// Copy the data in the object into the UI
driver.edit(p);

//at this point the editor panel is loaded with the person...

VerticalPanel vp = new VerticalPanel();
vp.setSize("100%", "100%");
rootPanel.add(vp);

Button editButton = new Button("edit", new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
//we get the edited person object back
Person editedPerson = driver.flush();
Window.alert("edited person name: "+editedPerson.getName());
}
});
vp.add(editor);
vp.add(editButton);
}
}