blob: 9a901148ff6ca719d4a4f8e3bc16da6f98680e77 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.richtext;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.rap.json.JsonObject;
import org.eclipse.rap.json.JsonValue;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.client.service.JavaScriptLoader;
import org.eclipse.rap.rwt.remote.AbstractOperationHandler;
import org.eclipse.rap.rwt.remote.Connection;
import org.eclipse.rap.rwt.remote.OperationHandler;
import org.eclipse.rap.rwt.remote.RemoteObject;
import org.eclipse.rap.rwt.service.ResourceManager;
import org.eclipse.rap.rwt.widgets.WidgetUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Layout;
public class RichTextEditor extends Composite {
private static final String RESOURCES_PATH = "resources/";
private static final String REGISTER_PATH = "ckeditor/";
private static final String[] RESOURCE_FILES = {
"ckeditor.js",
"config.js",
"styles.js",
"contents.css",
"lang/id.js",
"lang/en.js",
"skins/moono/editor.css",
"skins/moono/editor_ie.css",
"skins/moono/editor_gecko.css",
"skins/moono/dialog.css",
"skins/moono/dialog_ie.css",
"skins/moono/icons.png",
"skins/moono/icons_hidpi.png",
"skins/moono/images/arrow.png",
"skins/moono/images/close.png",
"skins/moono/images/lock-open.png",
"skins/moono/images/lock.png",
"skins/moono/images/refresh.png",
"skins/moono/images/hidpi/close.png",
"skins/moono/images/hidpi/lock-open.png",
"skins/moono/images/hidpi/lock.png",
"skins/moono/images/hidpi/refresh.png",
"RichTextEditor.js",
"RichTextEditorHandler.js"
};
private static final String REMOTE_TYPE = "rwt.widgets.RichTextEditor";
private String text = "";
private boolean editable = true;
private final RemoteObject remoteObject;
private final OperationHandler operationHandler = new AbstractOperationHandler() {
@Override
public void handleSet( JsonObject properties ) {
JsonValue textValue = properties.get( "text" );
if( textValue != null ) {
text = textValue.asString();
}
}
};
public RichTextEditor( Composite parent, int style ) {
super( parent, style );
registerResources();
loadJavaScript();
Connection connection = RWT.getUISession().getConnection();
remoteObject = connection.createRemoteObject( REMOTE_TYPE );
remoteObject.setHandler( operationHandler );
remoteObject.set( "parent", WidgetUtil.getId( this ) );
}
private static void registerResources() {
ResourceManager resourceManager = RWT.getResourceManager();
boolean isRegistered = resourceManager.isRegistered( REGISTER_PATH + RESOURCE_FILES[ 0 ] );
if( !isRegistered ) {
try {
for( String fileName : RESOURCE_FILES ) {
register( resourceManager, fileName );
}
} catch( IOException ioe ) {
throw new IllegalArgumentException( "Failed to load resources", ioe );
}
}
}
private static void loadJavaScript() {
JavaScriptLoader jsLoader = RWT.getClient().getService( JavaScriptLoader.class );
ResourceManager resourceManager = RWT.getResourceManager();
jsLoader.require( resourceManager.getLocation( REGISTER_PATH + "ckeditor.js" ) );
jsLoader.require( resourceManager.getLocation( REGISTER_PATH + "config.js" ) );
jsLoader.require( resourceManager.getLocation( REGISTER_PATH + "RichTextEditor.js" ) );
jsLoader.require( resourceManager.getLocation( REGISTER_PATH + "RichTextEditorHandler.js" ) );
}
private static void register( ResourceManager resourceManager, String fileName ) throws IOException {
ClassLoader classLoader = RichTextEditor.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream( RESOURCES_PATH + fileName );
try {
resourceManager.register( REGISTER_PATH + fileName, inputStream );
} finally {
inputStream.close();
}
}
////////////////////
// overwrite methods
@Override
public void setLayout( Layout layout ) {
throw new UnsupportedOperationException( "Cannot change internal layout of RichTextEditor" );
}
@Override
public void setFont( Font font ) {
super.setFont( font );
remoteObject.set( "font", getCssFont() );
}
@Override
public void dispose() {
if( !isDisposed() ) {
remoteObject.destroy();
}
super.dispose();
}
//////
// API
/**
* Set text to the editing area. Can contain HTML tags for styling.
*
* @param text The text to set to the editing area.
*/
public void setText( String text ) {
checkWidget();
if( text == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
this.text = text;
remoteObject.set( "text", text );
}
/**
* Get the text from the editing area. Contains HTML tags for formatting.
*
* @return The text that is currently set in the editing area.
*/
public String getText() {
checkWidget();
return text;
}
/**
* Returns the editable state.
*
* @return whether or not the receiver is editable
*
*/
public boolean isEditable() {
checkWidget();
return editable;
}
/**
* Sets the editable state.
*
* @param editable the new editable state
*/
public void setEditable( boolean editable ) {
checkWidget();
if( this.editable != editable ) {
this.editable = editable;
remoteObject.set( "editable", editable );
}
}
@Override
public boolean setParent( Composite parent ) {
checkWidget();
// CKEditor can't be reparented
return false;
}
@Override
public boolean isReparentable() {
checkWidget();
// CKEditor can't be reparented
return false;
}
private String getCssFont() {
StringBuilder result = new StringBuilder();
if( getFont() != null ) {
FontData data = getFont().getFontData()[ 0 ];
result.append( data.getHeight() );
result.append( "px " );
result.append( data.getName() );
}
return result.toString();
}
}