/*******************************************************************************
* Copyright (c) 2002, 2009 Innoopract Informationssysteme GmbH.
* 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:
* Innoopract Informationssysteme GmbH - initial API and implementation
* EclipseSource - ongoing development
******************************************************************************/
package org.eclipse.swt.internal.widgets.treeitemkit;
import java.io.IOException;
import org.eclipse.rwt.internal.lifecycle.JSConst;
import org.eclipse.rwt.lifecycle.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.TreeEvent;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.graphics.ResourceFactory;
import org.eclipse.swt.internal.widgets.*;
import org.eclipse.swt.widgets.*;
public final class TreeItemLCA extends AbstractWidgetLCA {
public static final String PROP_CHECKED = "checked";
public static final String PROP_EXPANDED = "expanded";
public static final String PROP_SELECTION = "selection";
public static final String PROP_BACKGROUND = "background";
public static final String PROP_FOREGROUND = "foreground";
public static final String PROP_FONT = "font";
public static final String PROP_CELL_BACKGROUNDS = "backgrounds";
public static final String PROP_CELL_FOREGROUNDS = "foregrounds";
public static final String PROP_CELL_FONTS = "fonts";
public static final String PROP_GRAYED = "grayed";
public static final String PROP_TEXTS = "texts";
public static final String PROP_IMAGES = "images";
public static final String PROP_MATERIALIZED = "materialized";
public void preserveValues( final Widget widget ) {
TreeItem treeItem = ( TreeItem )widget;
Tree tree = treeItem.getParent();
ITreeAdapter treeAdapter
= ( ITreeAdapter )tree.getAdapter( ITreeAdapter.class );
ITreeItemAdapter itemAdapter
= ( ITreeItemAdapter )treeItem.getAdapter( ITreeItemAdapter.class );
IWidgetColorAdapter colorAdapter
= ( IWidgetColorAdapter )treeItem.getAdapter( IWidgetColorAdapter.class );
IWidgetFontAdapter fontAdapter
= ( IWidgetFontAdapter )treeItem.getAdapter( IWidgetFontAdapter.class );
IWidgetAdapter adapter = WidgetUtil.getAdapter( treeItem );
if( treeAdapter.isCached( treeItem ) ) {
preserveFont( treeItem );
adapter.preserve( PROP_CHECKED,
Boolean.valueOf( treeItem.getChecked() ) );
adapter.preserve( TreeItemLCA.PROP_EXPANDED,
Boolean.valueOf( treeItem.getExpanded() ) );
adapter.preserve( PROP_TEXTS, getTexts( treeItem ) );
adapter.preserve( PROP_IMAGES, getImages( treeItem ) );
boolean selection = isSelected( treeItem );
adapter.preserve( PROP_SELECTION, Boolean.valueOf( selection ) );
adapter.preserve( PROP_BACKGROUND, colorAdapter.getUserBackgound() );
adapter.preserve( PROP_FOREGROUND, colorAdapter.getUserForegound() );
adapter.preserve( PROP_FONT, fontAdapter.getUserFont() );
adapter.preserve( PROP_CELL_BACKGROUNDS,
itemAdapter.getCellBackgrounds() );
adapter.preserve( PROP_CELL_FOREGROUNDS,
itemAdapter.getCellForegrounds() );
adapter.preserve( PROP_CELL_FONTS, itemAdapter.getCellFonts() );
adapter.preserve( PROP_GRAYED, Boolean.valueOf( treeItem.getGrayed() ) );
}
adapter.preserve( PROP_MATERIALIZED,
Boolean.valueOf( treeAdapter.isCached( treeItem ) ) );
WidgetLCAUtil.preserveCustomVariant( treeItem );
}
public void readData( final Widget widget ) {
final TreeItem treeItem = ( TreeItem )widget;
String value = WidgetLCAUtil.readPropertyValue( widget, "checked" );
if( value != null ) {
treeItem.setChecked( Boolean.valueOf( value ).booleanValue() );
}
if( WidgetLCAUtil.wasEventSent( treeItem, JSConst.EVENT_TREE_EXPANDED ) ) {
processTreeExpandedEvent( treeItem );
ProcessActionRunner.add( new Runnable() {
public void run() {
treeItem.setExpanded( true );
}
} );
}
if( WidgetLCAUtil.wasEventSent( treeItem, JSConst.EVENT_TREE_COLLAPSED ) ) {
processTreeCollapsedEvent( treeItem );
ProcessActionRunner.add( new Runnable() {
public void run() {
treeItem.setExpanded( false );
}
} );
}
}
public void renderInitialization( final Widget widget ) throws IOException {
TreeItem treeItem = ( TreeItem )widget;
JSWriter writer = JSWriter.getWriterFor( widget );
Object parent;
Integer index = null;
if( treeItem.getParentItem() == null ) {
parent = treeItem.getParent();
index = new Integer( treeItem.getParent().indexOf( treeItem ) );
} else {
parent = treeItem.getParentItem();
index = new Integer( treeItem.getParentItem().indexOf( treeItem ) );
}
Object[] args = new Object[]{
WidgetUtil.getId( treeItem ), parent, treeItem.getParent(), index
};
writer.callStatic( "org.eclipse.swt.TreeItemUtil.createTreeItem", args );
}
public void renderChanges( final Widget widget ) throws IOException {
TreeItem treeItem = ( TreeItem )widget;
// [bm] order is important, images needs to be written before texts
Tree tree = treeItem.getParent();
ITreeAdapter adapter = ( ITreeAdapter )tree.getAdapter( ITreeAdapter.class );
if( adapter.isCached( treeItem ) ) {
writeImages( treeItem );
writeTexts( treeItem );
writeBackground( treeItem );
writeForeground( treeItem );
writeFont( treeItem );
writeCellBackgrounds( treeItem );
writeCellForegrounds( treeItem );
writeCellFonts( treeItem );
writeSelection( treeItem );
writeExpanded( treeItem );
writeChecked( treeItem );
writeGrayed( treeItem );
writeShowItem( treeItem );
}
writeMaterialized( treeItem );
WidgetLCAUtil.writeCustomVariant( treeItem );
}
private void writeMaterialized( final TreeItem treeItem ) throws IOException {
final Tree tree = treeItem.getParent();
if( ( tree.getStyle() & SWT.VIRTUAL ) != 0 ) {
JSWriter writer = JSWriter.getWriterFor( treeItem );
ITreeAdapter adapter
= ( ITreeAdapter )tree.getAdapter( ITreeAdapter.class );
writer.set( PROP_MATERIALIZED,
"materialized",
Boolean.valueOf( adapter.isCached( treeItem ) ) );
}
}
public void renderDispose( final Widget widget ) throws IOException {
JSWriter writer = JSWriter.getWriterFor( widget );
// safely remove tree item from tree
writer.call( "destroy", null );
writer.dispose();
}
////////////////////////////////////
// Helping methods to write changes
private void writeShowItem( final TreeItem item ) throws IOException {
Tree tree = item.getParent();
ITreeAdapter adapter
= ( ITreeAdapter )tree.getAdapter( ITreeAdapter.class );
Item showItem = adapter.getShowItem();
if( showItem != null && showItem == item ) {
JSWriter writer = JSWriter.getWriterFor( tree );
writer.call( tree, "showItem", new Object[]{
showItem
} );
adapter.clearShowItem();
}
}
private static void writeImages( final TreeItem item ) throws IOException {
JSWriter writer = JSWriter.getWriterFor( item );
// TODO [rh] optimize when !isInitialized: for all images != null: setImg
Image[] images = getImages( item );
Integer[] imageWidths = new Integer[ images.length ];
if( WidgetLCAUtil.hasChanged( item, PROP_IMAGES, images ) ) {
String[] imagePaths = new String[ images.length ];
for( int i = 0; i < imagePaths.length; i++ ) {
imagePaths[ i ] = ResourceFactory.getImagePath( images[ i ] );
imageWidths[ i ] = new Integer( item.getImageBounds( i ).width );
}
// writer.set( "images", new Object[] { imagePaths, imageWidths } );
writer.set( "images", new Object[]{
imagePaths
} );
}
}
private static void preserveFont( final TreeItem treeItem ) {
IWidgetFontAdapter fontAdapter
= ( IWidgetFontAdapter )treeItem.getAdapter( IWidgetFontAdapter.class );
Font font = fontAdapter.getUserFont();
WidgetLCAUtil.preserveFont( treeItem, font );
}
private static void writeExpanded( final TreeItem item ) throws IOException {
JSWriter writer = JSWriter.getWriterFor( item );
Boolean newValue = Boolean.valueOf( item.getExpanded() );
writer.set( PROP_EXPANDED, "open", newValue, Boolean.FALSE );
}
private static void writeChecked( final TreeItem item ) throws IOException {
JSWriter writer = JSWriter.getWriterFor( item );
Boolean newValue = Boolean.valueOf( item.getChecked() );
writer.set( PROP_CHECKED, "checked", newValue, Boolean.FALSE );
}
private static void writeSelection( final TreeItem item ) throws IOException {
Boolean newValue = Boolean.valueOf( isSelected( item ) );
Boolean defValue = Boolean.FALSE;
if( WidgetLCAUtil.hasChanged( item, PROP_SELECTION, newValue, defValue ) ) {
JSWriter writer = JSWriter.getWriterFor( item );
Boolean focused = Boolean.valueOf( isFocused( item ) );
writer.set( "selection", new Object[]{
newValue, focused
} );
}
}
private static void writeFont( final TreeItem treeItem ) throws IOException {
Object adapter = treeItem.getAdapter( IWidgetFontAdapter.class );
IWidgetFontAdapter fontAdapter = ( IWidgetFontAdapter )adapter;
Font font = fontAdapter.getUserFont();
WidgetLCAUtil.writeFont( treeItem, font );
}
private static void writeCellFonts( final TreeItem item ) throws IOException {
ITreeItemAdapter itemAdapter
= ( ITreeItemAdapter )item.getAdapter( ITreeItemAdapter.class );
Font[] fonts = itemAdapter.getCellFonts();
JSWriter writer = JSWriter.getWriterFor( item );
// TODO [rst] Revise when properly implemented in TreeItem.js
// writer.set( PROP_CELL_FONTS, "fonts", fonts, null );
if( WidgetLCAUtil.hasChanged( item, PROP_CELL_FONTS, fonts, null ) ) {
String[] css = null;
if( fonts != null ) {
css = new String[ fonts.length ];
for( int i = 0; i < fonts.length; i++ ) {
css[ i ] = toCss( fonts[ i ] );
}
}
writer.set( "fonts", new Object[]{ css } );
}
}
private static void writeBackground( final TreeItem item ) throws IOException
{
IWidgetColorAdapter colorAdapter
= ( IWidgetColorAdapter )item.getAdapter( IWidgetColorAdapter.class );
Color background = colorAdapter.getUserBackgound();
if( WidgetLCAUtil.hasChanged( item, PROP_BACKGROUND, background, null ) ) {
WidgetLCAUtil.writeBackground( item, background );
}
}
private static void writeForeground( final TreeItem item ) throws IOException
{
IWidgetColorAdapter colorAdapter
= ( IWidgetColorAdapter )item.getAdapter( IWidgetColorAdapter.class );
Color foreground = colorAdapter.getUserForegound();
if( WidgetLCAUtil.hasChanged( item, PROP_FOREGROUND, foreground, null ) ) {
WidgetLCAUtil.writeForeground( item, foreground );
}
}
private static void writeCellBackgrounds( final TreeItem item )
throws IOException
{
ITreeItemAdapter itemAdapter
= ( ITreeItemAdapter )item.getAdapter( ITreeItemAdapter.class );
Color[] backgrounds = itemAdapter.getCellBackgrounds();
JSWriter writer = JSWriter.getWriterFor( item );
writer.set( PROP_CELL_BACKGROUNDS, "backgrounds", backgrounds, null );
}
private static void writeCellForegrounds( final TreeItem item )
throws IOException
{
ITreeItemAdapter itemAdapter
= ( ITreeItemAdapter )item.getAdapter( ITreeItemAdapter.class );
Color[] foregrounds = itemAdapter.getCellForegrounds();
JSWriter writer = JSWriter.getWriterFor( item );
writer.set( PROP_CELL_FOREGROUNDS, "foregrounds", foregrounds, null );
}
private static void writeTexts( final TreeItem item ) throws IOException {
JSWriter writer = JSWriter.getWriterFor( item );
String[] texts = getTexts( item );
if( WidgetLCAUtil.hasChanged( item, PROP_TEXTS, texts ) ) {
for( int i = 0; i < texts.length; i++ ) {
texts[ i ] = WidgetLCAUtil.escapeText( texts[ i ], false );
texts[ i ] = texts[ i ].replaceAll( " ", " " );
}
writer.set( "texts", new Object[]{
texts
} );
}
}
private static String[] getTexts( final TreeItem item ) {
int columnCount = getColumnCount( item );
String[] texts = new String[ columnCount ];
for( int i = 0; i < columnCount; i++ ) {
texts[ i ] = item.getText( i );
}
return texts;
}
private static Image[] getImages( final TreeItem item ) {
int columnCount = getColumnCount( item );
Image[] images = new Image[ columnCount ];
for( int i = 0; i < columnCount; i++ ) {
images[ i ] = item.getImage( i );
}
return images;
}
private static int getColumnCount( final TreeItem item ) {
return Math.max( 1, item.getParent().getColumnCount() );
}
private static void writeGrayed( final TreeItem item ) throws IOException {
JSWriter writer = JSWriter.getWriterFor( item );
Boolean newValue = Boolean.valueOf( item.getGrayed() );
writer.set( PROP_GRAYED, "grayed", newValue, Boolean.FALSE );
}
private static boolean isFocused( final TreeItem item ) {
Tree tree = item.getParent();
return tree.getSelectionCount() > 0 && tree.getSelection()[ 0 ] == item;
}
private static boolean isSelected( final TreeItem item ) {
boolean result = false;
Tree tree = item.getParent();
TreeItem[] selectedItems = tree.getSelection();
for( int i = 0; !result && i < selectedItems.length; i++ ) {
if( item == selectedItems[ i ] ) {
result = true;
}
}
return result;
}
private static String toCss( final Font font ) {
StringBuffer result = new StringBuffer();
if( font != null ) {
FontData fontData = font.getFontData()[ 0 ];
if( ( fontData.getStyle() & SWT.ITALIC ) != 0 ) {
result.append( "italic " );
}
if( ( fontData.getStyle() & SWT.BOLD ) != 0 ) {
result.append( "bold " );
}
result.append( fontData.getHeight() );
result.append( "px " );
// TODO [rh] preliminary: low budget font-name-escaping
String escapedName = fontData.getName().replaceAll( "\"", "" );
result.append( escapedName );
} else {
// TODO [if] Revise when properly implemented in TreeItem.js
result.append( "" );
}
return result.toString();
}
/////////////////////////////////
// Process expand/collapse events
private static void processTreeExpandedEvent( final TreeItem treeItem ) {
if( TreeEvent.hasListener( treeItem.getParent() ) ) {
TreeEvent event = new TreeEvent( treeItem.getParent(),
treeItem,
TreeEvent.TREE_EXPANDED );
event.processEvent();
}
}
private static void processTreeCollapsedEvent( final TreeItem treeItem ) {
if( TreeEvent.hasListener( treeItem.getParent() ) ) {
TreeEvent event = new TreeEvent( treeItem.getParent(),
treeItem,
TreeEvent.TREE_COLLAPSED );
event.processEvent();
}
}
}