Archive

Posts Tagged ‘GWT’

GWT Toolbar for RichTextArea (a RichTextToolbar with HTML-Editor)

08:13 AM No comments

Due to the lack of a RichTextToolbar including the option to switch between HTML and WYSIWYG-view, I wrote a simple implementation for my own. Here is a screenshot and the complete source-code. The Toolbar is compatible to GWT 2.0, but can be easily downgraded to GWT 1.7.x. If you need a downgraded version, feel free to drop me an email.

Another great thing about my own toolbar is, that it is well-ordered. I hate these unlogical structures of other toolbars (like that one from wordpress).Unstructured usual ToolBar

Bold, Italic, Stikeout; but Underline is in the row below. Then there come the List-Options; but indent left and right is also in the second line. Watch alignment: left, center and right is above. The full alignment is also in the second panel:

Now look at my toolbar: I think it provides much more usability:

RichText Toolbar with HTML and WYSIWYG-view for GWT RichTextArea

And here is the GWT-Code for the Toolbar. To use it in your project, simply instanciate it with a reference to the RichTextArea it refers to and put it onto your panel:

RichTextToolbar toolbar = new RichTextToolbar(yourRichTextArea);
stage.add(toolbar);
stage.add(yourRichTextArea);

Ok – and now finally the Code, which can be downloaded at code.google.com:

/**
/*
 * This software is published under the Apchae 2.0 licenses.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Author: Erik Scholtz 
 * Web: http://blog.elitecoderz.net
 */
 
package net.elitecoderz.blog;
 
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.RichTextArea.Formatter;
 
public class RichTextToolbar extends Composite {
	private static final String HTTP_STATIC_ICONS_GIF = "http://blog.elitecoderz.net/wp-includes/js/tinymce/themes/advanced/img/icons.gif";
 
	/** Private Variables **/
	//The main (Vertical)-Panel and the two inner (Horizontal)-Panels
	private VerticalPanel outer;
	private HorizontalPanel topPanel;
	private HorizontalPanel bottomPanel;
 
	//The RichTextArea this Toolbar referes to and the Interfaces to access the RichTextArea
	private RichTextArea styleText;
	private Formatter styleTextFormatter;
 
	//We use an internal class of the ClickHandler and the KeyUpHandler to be private to others with these events
	private EventHandler evHandler;
 
	//The Buttons of the Menubar
	private ToggleButton bold;
	private ToggleButton italic;
	private ToggleButton underline;
	private ToggleButton stroke;
	private ToggleButton subscript;
	private ToggleButton superscript;
	private PushButton alignleft;
	private PushButton alignmiddle;
	private PushButton alignright;
	private PushButton orderlist;
	private PushButton unorderlist;
	private PushButton indentleft;
	private PushButton indentright;
	private PushButton generatelink;
	private PushButton breaklink;
	private PushButton insertline;
	private PushButton insertimage;
	private PushButton removeformatting;
	private ToggleButton texthtml;
 
	private ListBox fontlist;
	private ListBox colorlist;
 
	/** Constructor of the Toolbar **/
	public RichTextToolbar(RichTextArea richtext) {
		//Initialize the main-panel
		outer = new VerticalPanel();
 
		//Initialize the two inner panels
		topPanel = new HorizontalPanel();
		bottomPanel = new HorizontalPanel();
		topPanel.setStyleName("RichTextToolbar");
		bottomPanel.setStyleName("RichTextToolbar");
 
		//Save the reference to the RichText area we refer to and get the interfaces to the stylings
 
		styleText = richtext;
		styleTextFormatter = styleText.getFormatter();
 
		//Set some graphical options, so this toolbar looks how we like it.
		topPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_LEFT);
		bottomPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_LEFT);
 
		//Add the two inner panels to the main panel
		outer.add(topPanel);
		outer.add(bottomPanel);
 
		//Some graphical stuff to the main panel and the initialisation of the new widget
		outer.setWidth("100%");
		outer.setStyleName("RichTextToolbar");
		initWidget(outer);
 
		//
		evHandler = new EventHandler();
 
		//Add KeyUp and Click-Handler to the RichText, so that we can actualize the toolbar if neccessary
		styleText.addKeyUpHandler(evHandler);
		styleText.addClickHandler(evHandler);
 
		//Now lets fill the new toolbar with life
		buildTools();
	}
 
	/** Click Handler of the Toolbar **/
	private class EventHandler implements ClickHandler,KeyUpHandler, ChangeHandler {
		public void onClick(ClickEvent event) {
			if (event.getSource().equals(bold)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<span style=\"font-weight: bold;\">","</span>");
				} else {
					styleTextFormatter.toggleBold();
				}
			} else if (event.getSource().equals(italic)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<span style=\"font-style: italic;\">","</span>");
				} else {
					styleTextFormatter.toggleItalic();
				}
			} else if (event.getSource().equals(underline)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<span style=\"text-decoration: underline;\">","</span>");
				} else {
					styleTextFormatter.toggleUnderline();
				}
			} else if (event.getSource().equals(stroke)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<span style=\"text-decoration: line-through;\">","</span>");
				} else {
					styleTextFormatter.toggleStrikethrough();
				}
			} else if (event.getSource().equals(subscript)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<sub>","</sub>");
				} else {
					styleTextFormatter.toggleSubscript();
				}
			} else if (event.getSource().equals(superscript)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<sup>","</sup>");
				} else {
					styleTextFormatter.toggleSuperscript();
				}
			} else if (event.getSource().equals(alignleft)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<div style=\"text-align: left;\">","</div>");
				} else {
					styleTextFormatter.setJustification(RichTextArea.Justification.LEFT);
				}
			} else if (event.getSource().equals(alignmiddle)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<div style=\"text-align: center;\">","</div>");
				} else {
					styleTextFormatter.setJustification(RichTextArea.Justification.CENTER);
				}
			} else if (event.getSource().equals(alignright)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<div style=\"text-align: right;\">","</div>");
				} else {
					styleTextFormatter.setJustification(RichTextArea.Justification.RIGHT);
				}
			} else if (event.getSource().equals(orderlist)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<ol><li>","</li></ol>");
				} else {
					styleTextFormatter.insertOrderedList();
				}
			} else if (event.getSource().equals(unorderlist)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<ul><li>","</li></ul>");
				} else {
					styleTextFormatter.insertUnorderedList();
				}
			} else if (event.getSource().equals(indentright)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<div style=\"margin-left: 40px;\">","</div>");
				} else {
					styleTextFormatter.rightIndent();
				}
			} else if (event.getSource().equals(indentleft)) {
				if (isHTMLMode()) {
					//TODO nothing can be done here at the moment
				} else {
					styleTextFormatter.leftIndent();
				}
			} else if (event.getSource().equals(generatelink)) {
				String url = Window.prompt("Enter a link URL:", "http://");
				if (url != null) {
					if (isHTMLMode()) {
						changeHtmlStyle("<a href=\""+url+"\">","</a>");
					} else {
						styleTextFormatter.createLink(url);
					}
				}
			} else if (event.getSource().equals(breaklink)) {
				if (isHTMLMode()) {
					//TODO nothing can be done here at the moment
				} else {
					styleTextFormatter.removeLink();
				}
			} else if (event.getSource().equals(insertimage)) {
				String url = Window.prompt("Enter an image URL:", "http://");
				if (url != null) {
					if (isHTMLMode()) {
						changeHtmlStyle("<img src=\""+url+"\">","");
					} else {
						styleTextFormatter.insertImage(url);
					}
				}
			}  else if (event.getSource().equals(insertline)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<hr style=\"width: 100%; height: 2px;\">","");
				} else {
					styleTextFormatter.insertHorizontalRule();
				}
			} else if (event.getSource().equals(removeformatting)) {
				if (isHTMLMode()) {
					//TODO nothing can be done here at the moment
				} else {
					styleTextFormatter.removeFormat();
				}
			} else if (event.getSource().equals(texthtml)) {
				if (texthtml.isDown()) {
					styleText.setText(styleText.getHTML());
				} else {
					styleText.setHTML(styleText.getText());
				}
			} else if (event.getSource().equals(styleText)) {
				//Change invoked by the richtextArea
			}
			updateStatus();
		}
 
		public void onKeyUp(KeyUpEvent event) {
			updateStatus();
		}
 
		public void onChange(ChangeEvent event) {
			System.out.println("fire");
			if (event.getSource().equals(fontlist)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<span style=\"font-family: "+fontlist.getValue(fontlist.getSelectedIndex())+";\">","</span>");
				} else {
					styleTextFormatter.setFontName(fontlist.getValue(fontlist.getSelectedIndex()));
				}
			} else if (event.getSource().equals(colorlist)) {
				if (isHTMLMode()) {
					changeHtmlStyle("<span style=\"color: "+colorlist.getValue(colorlist.getSelectedIndex())+";\">","</span>");
				} else {
					styleTextFormatter.setForeColor(colorlist.getValue(colorlist.getSelectedIndex()));
				}
			}
		}
	}
 
	/** Native JavaScript that returns the selected text and position of the start **/
	public static native JsArrayString getSelection(Element elem) /*-{
		var txt = "";
		var pos = 0;
  		if (elem.contentWindow.getSelection) {
        	txt = elem.contentWindow.getSelection();
        	pos = elem.contentWindow.getSelection().getRangeAt(0).startOffset;
        } else if (elem.contentWindow.document.getSelection) {
        	txt = elem.contentWindow.document.getSelection();
        	pos = elem.contentWindow.document.getSelection().getRangeAt(0).startOffset;
  		} else if (elem.contentWindow.document.selection) {
        	txt = elem.contentWindow.document.selection.createRange().text;
        	pos = elem.contentWindow.document.selection.getRangeAt(0).startOffset;
        }
  		return [""+txt,""+pos];
	}-*/;
 
	/** Method called to toggle the style in HTML-Mode **/
	private void changeHtmlStyle(String startTag, String stopTag) {
		JsArrayString tx = getSelection(styleText.getElement());
		String txbuffer = styleText.getText();
		Integer startpos = Integer.parseInt(tx.get(1));
		String selectedText = tx.get(0);
		styleText.setText(txbuffer.substring(0, startpos)+startTag+selectedText+stopTag+txbuffer.substring(startpos+selectedText.length()));
	}
 
	/** Private method with a more understandable name to get if HTML mode is on or not **/
	private Boolean isHTMLMode() {
		return  texthtml.isDown();
	}
 
	/** Private method to set the toggle buttons and disable/enable buttons which do not work in html-mode **/
	private void updateStatus() {
		if (styleTextFormatter != null) {
			bold.setDown(styleTextFormatter.isBold());
			italic.setDown(styleTextFormatter.isItalic());
			underline.setDown(styleTextFormatter.isUnderlined());
			subscript.setDown(styleTextFormatter.isSubscript());
			superscript.setDown(styleTextFormatter.isSuperscript());
			stroke.setDown(styleTextFormatter.isStrikethrough());
		}
 
		if (isHTMLMode()) {
			removeformatting.setEnabled(false);
			indentleft.setEnabled(false);
			breaklink.setEnabled(false);
		} else {
			removeformatting.setEnabled(true);
			indentleft.setEnabled(true);
			breaklink.setEnabled(true);
		}
	}
 
	/** Initialize the options on the toolbar **/
	private void buildTools() {
		//Init the TOP Panel forst
		topPanel.add(bold = createToggleButton(HTTP_STATIC_ICONS_GIF,0,0,20,20,"Bold"));
		topPanel.add(italic = createToggleButton(HTTP_STATIC_ICONS_GIF,0,60,20,20,"Italic"));
		topPanel.add(underline = createToggleButton(HTTP_STATIC_ICONS_GIF,0,140,20,20,"Underline"));
		topPanel.add(stroke = createToggleButton(HTTP_STATIC_ICONS_GIF,0,120,20,20,"Stroke"));
		topPanel.add(new HTML("&nbsp;"));
		topPanel.add(subscript = createToggleButton(HTTP_STATIC_ICONS_GIF,0,600,20,20,"Subscript"));
		topPanel.add(superscript = createToggleButton(HTTP_STATIC_ICONS_GIF,0,620,20,20,"Superscript"));
		topPanel.add(new HTML("&nbsp;"));
		topPanel.add(alignleft = createPushButton(HTTP_STATIC_ICONS_GIF,0,460,20,20,"Align Left"));
		topPanel.add(alignmiddle = createPushButton(HTTP_STATIC_ICONS_GIF,0,420,20,20,"Align Center"));
		topPanel.add(alignright = createPushButton(HTTP_STATIC_ICONS_GIF,0,480,20,20,"Align Right"));
		topPanel.add(new HTML("&nbsp;"));
		topPanel.add(orderlist = createPushButton(HTTP_STATIC_ICONS_GIF,0,80,20,20,"Ordered List"));
		topPanel.add(unorderlist = createPushButton(HTTP_STATIC_ICONS_GIF,0,20,20,20,"Unordered List"));
		topPanel.add(indentright = createPushButton(HTTP_STATIC_ICONS_GIF,0,400,20,20,"Ident Right"));
		topPanel.add(indentleft = createPushButton(HTTP_STATIC_ICONS_GIF,0,540,20,20,"Ident Left"));
		topPanel.add(new HTML("&nbsp;"));
		topPanel.add(generatelink = createPushButton(HTTP_STATIC_ICONS_GIF,0,500,20,20,"Generate Link"));
		topPanel.add(breaklink = createPushButton(HTTP_STATIC_ICONS_GIF,0,640,20,20,"Break Link"));
		topPanel.add(new HTML("&nbsp;"));
		topPanel.add(insertline = createPushButton(HTTP_STATIC_ICONS_GIF,0,360,20,20,"Insert Horizontal Line"));
		topPanel.add(insertimage = createPushButton(HTTP_STATIC_ICONS_GIF,0,380,20,20,"Insert Image"));
		topPanel.add(new HTML("&nbsp;"));
		topPanel.add(removeformatting = createPushButton(HTTP_STATIC_ICONS_GIF,20,460,20,20,"Remove Formatting"));
		topPanel.add(new HTML("&nbsp;"));
		topPanel.add(texthtml = createToggleButton(HTTP_STATIC_ICONS_GIF,0,260,20,20,"Show as HTML"));
 
		//Init the BOTTOM Panel
		bottomPanel.add(fontlist = createFontList());
		bottomPanel.add(new HTML("&nbsp;"));
		bottomPanel.add(colorlist = createColorList());
	}
 
	/** Method to create a Toggle button for the toolbar **/
	private ToggleButton createToggleButton(String url, Integer top, Integer left, Integer width, Integer height, String tip) {
		Image extract = new Image(url, left, top, width, height);
		ToggleButton tb = new ToggleButton(extract);
		tb.setHeight(height+"px");
		tb.setWidth(width+"px");
		tb.addClickHandler(evHandler);
		if (tip != null) {
			tb.setTitle(tip);
		}
		return tb;
	}
 
	/** Method to create a Push button for the toolbar **/
	private PushButton createPushButton(String url, Integer top, Integer left, Integer width, Integer height, String tip) {
		Image extract = new Image(url, left, top, width, height);
		PushButton tb = new PushButton(extract);
		tb.setHeight(height+"px");
		tb.setWidth(width+"px");
		tb.addClickHandler(evHandler);
		if (tip != null) {
			tb.setTitle(tip);
		}
		return tb;
	}
 
	/** Method to create the fontlist for the toolbar **/
	private ListBox createFontList() {
	    ListBox mylistBox = new ListBox();
	    mylistBox.addChangeHandler(evHandler);
	    mylistBox.setVisibleItemCount(1);
 
	    mylistBox.addItem("Fonts", "");
	    mylistBox.addItem("Times New Roman", "Times New Roman");
	    mylistBox.addItem("Arial", "Arial");
	    mylistBox.addItem("Courier New", "Courier New");
	    mylistBox.addItem("Georgia", "Georgia");
	    mylistBox.addItem("Trebuchet", "Trebuchet");
	    mylistBox.addItem("Verdana", "Verdana");
	    return mylistBox;
	}
 
	/** Method to create the colorlist for the toolbar **/
	private ListBox createColorList() {
	    ListBox mylistBox = new ListBox();
	    mylistBox.addChangeHandler(evHandler);
	    mylistBox.setVisibleItemCount(1);
 
	    mylistBox.addItem("Colors");
	    mylistBox.addItem("white", "white");
	    mylistBox.addItem("black", "black");
	    mylistBox.addItem("red", "red");
	    mylistBox.addItem("green", "green");
	    mylistBox.addItem("yellow", "yellow");
	    mylistBox.addItem("blue", "blue");
	    return mylistBox;
	}
 
}

I am using the following icons in this example:
Here is the Link to the icons I am using too

Categories: GWT Tags: , , ,

GWT and tomcat: Create .war using eclipse to deploy .war on tomcat

07:35 PM 7 comments

Howto compfortably build a correct .war from your GWT-project using eclipse to deploy it to a tomcat server.

There are only two simple steps to take, to build a .war from your GWT project:

Short version:

The first step is building a .jar from your src-folder and putting the .jar into the lib-folder of the .war-folder of your GWT-project. The second step is building a .war-file from your war-folder and deploying the .war to your tomcat server. To make the second step more compfortable, I wrote a little Ant-script, that will create the .war.

More detailed – Step 1:

right_click_src

1) Right-click your projects src-folder (click for larger view)

1) Right-click the src folder inside your project.

popup_export

2) Select "Export" from the PopUp (click for larger view)

2) The following PopUp-menu will appear.

Select “Export …” from this menu.

Select_export_format

3) Select "JAR File" as export-format (click for larger view)

3) Select “JAR file” from the next window

select_export_source_and_target

3) Select export source and target (click for larger view)

4) Make sure, only the “src”-folder of your project is checked in the next window.

Select the export destination like this: <folder of your project>/war/WEB-INF/lib/<projectname>.jar – then click “Finish”

Now your GWT-project is ready to be packed into a .war, that can be deployed to a tomcat server.

More detailed – Step 2:

1) Create a new ANT-script in your project (Right-click your project folder and select “New” and then select “File” from the submenu. Call the new file “warbuilder.xml” or something like this.).

2) Copy the following content into the newly created file. Replace <projectname> with the name of your project:

<project name="<projectname>" basedir="." default="default">
 
	<target name="default" depends="buildwar,deploy"></target>
 
	<target name="buildwar">
		<war basedir="war" destfile="<projectname>.war" webxml="war/WEB-INF/web.xml">
			<exclude name="WEB-INF/**" />
			<webinf dir="war/WEB-INF/">
				<include name="**/*.jar" />
			</webinf>
		</war>
	</target>
 
	<target name="deploy">
		<copy file="<projectname>.war" todir="." />
	</target>
 
</project>

run_ant_script

5) Run the warbuilder ANT-script (click for larger view)

3) The first two steps must be done only once. You can reuse the warbuilder.xml and do not have to build it every time. Now simply right-click the “warbuilder.xml” and select “Run As” and “Ant Build” from the PopUp-menu.

The .war-File will be created by this ANT-script. You will find the .war-file in your ProjectFolder.

Categories: GWT Tags: , , , , ,

GWT – java.lang.NoClassDefFoundError when using .jars with eclipse

08:55 PM 2 comments

10.12.2009 19:19:19 com.google.apphosting.utils.jetty.JettyLogger warn
WARNUNG: Nested in javax.servlet.ServletException: init:
java.lang.NoClassDefFoundError: org/jibble/pircbot/PircBot
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:675)

project_right_clickThis exception can occure, when you try to use an .jar with GWT on the server side. The error message tells you, that the included path to your .jar (in this case org.jibble.pircbot.PircBot) can not be found. This normally happens, when you have forgotten to put the .jar into your build-path. When running GWT, the normal include into the build-path is not everything you need to do:

The normal way to include the .jar to your build-path is to edit the properties of your project, by right-clicking your project. In the Project Propertiesappearing window, you select “Java Build Path”. There you normally add your external .jars.

When using the GWT-Plugin in eclipse, this isn’t the only thing you have to do. Additionally, you need to copy the .jar into the WAR-directory of your project. The exact path is: YouProject/war/WEB-INF/lib/.

After putting the .jar into this directory, your local GWT-Runtime will work and not throw this error again. The reason is, that the GWT-Runtime of eclipse does not use the eclipse environment. It uses only the files of your “war”, which will be deployed to your application-server later.

Categories: GWT Tags: , , , ,

GWT and XML – First steps with com.google.gwt.xml

02:54 PM 5 comments

Developing web applications and portals using eclipse, GWT (google web toolkit) and apache tomcat is one of the most effective ways to get your work done: The result will always be a very high-performance AJAX application. To exchange data from the AJAX surface to the tomcat-server, I decided to use the GWT RPC, exchanging XML data structures.

Therefor GWT provides a nice package: com.google.gwt.xml.client.*

com.google.gwt.xml.client.* is a complete toolkit to deal with xml data-structures on the JavaScript clientside in a high perfomant way.

After having importing the needed packages as usual, I wrote some code to create a new XMLDom stucture. But when running the new code, the following error occured:

Line 52: No source code is available for type
com.google.gwt.xml.client.Document; did you forget to inherit a
required module?

Up to this point I was used to the fact, that eclipse did everything for me; so I had absolutly no idea what to do, since google returned no hints to this problem. I started to study the documentation and the project in detail and found the solution:

To “inherit” the XML module in GWT, you have to add the following line to the gwt.xml:

<inherits name="com.google.gwt.xml.XML" />

The gwt.xml file can be found under your project in the path: <project>/src/<your domain>/<project>.gwt.xml

After adding this line, dealing with XMLs  is really simple. I’ll post an article here with examples, as soon as I can get a little time for my blog again.

Categories: GWT, Java Tags: , , ,