/******************************************************************************* * Copyright (c) 2007, 2015 Innoopract Informationssysteme GmbH 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: * Innoopract Informationssysteme GmbH - initial API and implementation * EclipseSource - ongoing development ******************************************************************************/ package org.eclipse.rap.demo.controls; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.rap.rwt.internal.service.ContextProvider; import org.eclipse.rap.rwt.internal.theme.ThemeUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.internal.widgets.IWidgetGraphicsAdapter; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FontDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; @SuppressWarnings("restriction") abstract class ExampleTab implements Serializable { public static final int BG_COLOR_GREEN = 1; public static final int BG_COLOR_BLUE = 2; public static final int BG_COLOR_BROWN = 3; public static final int FG_COLOR_RED = 1; public static final int FG_COLOR_BLUE = 2; public static final int FG_COLOR_ORANGE = 3; public static final int BGG_COLOR_GREEN = 1; public static final int BGG_COLOR_BLUE = 2; protected final List<Control> controls; private Composite exampleComp; protected Composite styleComp; protected Color[] bgColors; protected Color[] fgColors; protected Color[] gradientColors; private Font font; private int fgIndex; private int bgIndex; private int rbIndex; private boolean showBgImage = false; private boolean showBgGradient = false; private boolean visible = true; private boolean enabled = true; private int orientation = SWT.LEFT_TO_RIGHT; private Text text; private final StringBuffer content = new StringBuffer(); private FontDialog fontChooser; private ColorChooser fgColorChooser; private ColorChooser bgColorChooser; private int defaultStyle = SWT.NONE; private int[] horizontalWeights = new int[] { 50, 50 }; private final Set<String> properties = new HashSet<String>(); private Object data; private static final String[] SWT_CURSORS = { "null", "CURSOR_ARROW", "CURSOR_WAIT", "CURSOR_APPSTARTING", "CURSOR_CROSS", "CURSOR_HELP", "CURSOR_NO", "CURSOR_SIZEALL", "CURSOR_SIZENESW", "CURSOR_SIZENS", "CURSOR_SIZENWSE", "CURSOR_SIZEWE", "CURSOR_SIZEN", "CURSOR_SIZES", "CURSOR_SIZEE", "CURSOR_SIZEW", "CURSOR_SIZENE", "CURSOR_SIZESE", "CURSOR_SIZESW", "CURSOR_SIZENW", "CURSOR_IBEAM", "CURSOR_HAND", "CURSOR_UPARROW" }; private final String name; private Shell shell; public ExampleTab( String name ) { this.name = name; controls = new ArrayList<Control>(); } public String getName() { return name; } public String getId() { String id = this.getClass().getSimpleName(); if( id.endsWith( "Tab" ) ) { id = id.substring( 0, id.length() - 3 ); } return id; } public Object getData() { return data; } public void setData( Object data ) { this.data = data; } public void createContents( Composite parent ) { shell = parent.getShell(); createSashForm( parent ); initColors( parent.getDisplay() ); createExampleControls( exampleComp ); createStyleControls( styleComp ); exampleComp.layout(); styleComp.layout(); } protected void createNew() { controls.clear(); destroyExampleControls(); createExampleControls( exampleComp ); updateVisible(); updateEnabled(); updateOrientation(); if( fgColorChooser != null ) { updateFgColor(); } if( bgColorChooser != null ) { updateBgColor(); } updateBgImage(); updateBgGradient(); if( fontChooser != null ) { // Control control = ( Control )controls.get( 0 ); // font = control.getFont(); // if( font != null ) { // fontChooser.setFont( font ); // } updateFont(); } exampleComp.layout(); } private Control createSashForm( Composite parent ) { SashForm vertSashForm = new SashForm( parent, SWT.VERTICAL ); SashForm horSashForm = new SashForm( vertSashForm, SWT.HORIZONTAL ); createLeft( horSashForm ); createRight( horSashForm ); createFoot( vertSashForm ); horSashForm.setWeights( horizontalWeights ); vertSashForm.setWeights( new int[] { 93, 7 } ); return vertSashForm; } private void createLeft( Composite parent ) { Composite composite = new Composite( parent, SWT.NONE ); composite.setBackground( parent.getDisplay().getSystemColor( SWT.COLOR_WHITE ) ); composite.setLayout( new FormLayout() ); Label header = new Label( composite, SWT.CENTER ); header.setFont( getHeaderFont( parent ) ); header.setText( getName() ); header.setLayoutData( createLayoutDataForHeader() ); exampleComp = new Composite( composite, SWT.NONE ); exampleComp.setLayoutData( createLayoutDataForExampleArea( header ) ); } private void createRight( Composite parent ) { Composite composite = new Composite( parent, SWT.NONE ); composite.setBackground( parent.getDisplay().getSystemColor( SWT.COLOR_WHITE ) ); composite.setLayout( new FormLayout() ); Label header = new Label( composite, SWT.LEFT ); header.setText( "Styles and Parameters" ); header.setLayoutData( createLayoutDataForHeader() ); styleComp = new Composite( composite, SWT.NONE ); styleComp.setLayoutData( createLayoutDataForExampleArea( header ) ); styleComp.setLayout( new RowLayout( SWT.VERTICAL ) ); } private void createFoot( Composite parent ) { text = new Text( parent, SWT.READ_ONLY | SWT.MULTI ); text.setText( "---" ); } private static Font getHeaderFont( Composite parent ) { String fontName = parent.getFont().getFontData()[ 0 ].getName(); return new Font( parent.getDisplay(), fontName, 18, SWT.BOLD ); } private static Object createLayoutDataForHeader() { FormData formData = new FormData(); formData.top = new FormAttachment( 0, 5 ); formData.left = new FormAttachment( 0, 10 ); formData.right = new FormAttachment( 100, -10 ); return formData; } private static Object createLayoutDataForExampleArea( Control control ) { FormData formData = new FormData(); formData.top = new FormAttachment( 0, 35 ); formData.left = new FormAttachment( 0, 5 ); formData.right = new FormAttachment( 100, -5 ); formData.bottom = new FormAttachment( 100, -5 ); return formData; } private void initColors( Display display ) { bgColors = new Color[] { null, new Color( display, 154, 205, 50 ), new Color( display, 105, 89, 205 ), new Color( display, 192, 172, 137 ) }; fgColors = new Color[] { null, new Color( display, 194, 0, 23 ), new Color( display, 28, 96, 141 ), new Color( display, 249, 158, 0 ) }; gradientColors = new Color[] { new Color( display, 0, 0, 255 ), new Color( display, 0, 255, 0 ), new Color( display, 0, 0, 255 ), new Color( display, 0, 255, 0 ), new Color( display, 0, 0, 255 ) }; } protected abstract void createStyleControls( Composite parent); protected abstract void createExampleControls( Composite parent ); // TODO [rst] Refactor ExampleTab to evaluate style controls before example controls are created protected void setDefaultStyle( int style ) { defaultStyle = style; } protected void setHorizontalSashFormWeights( int[] weights ) { horizontalWeights = weights; } protected Button createStyleButton( String fieldName, int style ) { return createStyleButton( fieldName, style, false ); } protected Button createStyleButton( String name, int style, boolean checked ) { Button button = new Button( styleComp, SWT.CHECK ); button.setText( name ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { createNew(); } } ); button.setData( "style", new Integer( style ) ); button.setSelection( checked ); return button; } protected Button createPropertyButton( String text ) { return createPropertyButton( text, SWT.CHECK ); } protected Button createPropertyButton( String text, int style ) { Button button = new Button( styleComp, style ); button.setText( text ); return button; } protected Button createPropertyCheckbox( String text, String prop ) { return createPropertyCheckbox( text, prop, false ); } protected Button createPropertyCheckbox( String text, final String prop, boolean checked ) { final Button button = new Button( styleComp, SWT.CHECK ); button.setText( text ); button.setSelection( checked ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent e ) { if( button.getSelection() ) { properties.add( prop ); } else { properties.remove( prop ); } createNew(); } } ); return button; } public final boolean hasCreateProperty( String name ) { return properties.contains( name ); } /** * Creates a checkbutton to show / hide the registered controls. * * @return the created checkbutton */ protected Button createVisibilityButton( ) { final Button button = new Button( styleComp, SWT.CHECK ); button.setText( "Visible" ); button.setSelection( visible ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { visible = button.getSelection(); updateVisible(); } } ); return button; } /** * Creates a checkbutton to enable / disabled the registered controls. * * @return the created checkbutton. */ protected Button createEnablementButton( ) { final Button button = new Button( styleComp, SWT.CHECK ); button.setText( "Enabled" ); button.setSelection( enabled ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { enabled = button.getSelection(); updateEnabled(); } } ); return button; } /** * Creates a button to change the foreground color of all registered * controls. * * @return the created button */ protected Button createFgColorButton() { fgColorChooser = new ColorChooser(); final Button button = new Button( styleComp, SWT.PUSH ); button.setText( "Foreground" ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { fgIndex = ( fgIndex + 1 ) % fgColors.length; updateFgColor(); } } ); return button; } /** * Creates a button to change the background color of all registered * controls. * * @return the created button */ protected Button createBgColorButton() { bgColorChooser = new ColorChooser(); final Button button = new Button( styleComp, SWT.PUSH ); button.setText( "Background" ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { bgIndex = ( bgIndex + 1 ) % fgColors.length; updateBgColor(); } } ); return button; } /** * Creates a button to change the background gradient of all registered * controls. * * @return the created button */ protected Button createBgGradientButton() { final Button button = new Button( styleComp, SWT.CHECK ); button.setText( "Background Gradient" ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { showBgGradient = button.getSelection(); updateBgGradient(); } } ); return button; } /** * Creates a checkbox that controls whether a background image is set on the * registered controls. * * @return the created checkbox */ protected Button createBgImageButton() { final Button button = new Button( styleComp, SWT.CHECK ); button.setText( "Background Image" ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { showBgImage = button.getSelection(); updateBgImage(); } } ); return button; } protected Button createFontChooser() { final Button button = new Button( styleComp, SWT.PUSH ); button.setText( "Font" ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { fontChooser = new FontDialog( getShell(), SWT.NONE ); Control control = controls.get( 0 ); fontChooser.setFontList( control.getFont().getFontData() ); if( fontChooser.open() != null ) { font = new Font( control.getDisplay(), fontChooser.getFontList() ); } updateFont(); } } ); return button; } /** * Experimental. Switching themes at runtime does not yet work properly. */ protected void createThemeSwitcher( final Composite parent ) { final Button button = new Button( parent, SWT.PUSH ); button.setText( "Theme Switcher" ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent e ) { Shell shell = new Shell( parent.getShell(), SWT.DIALOG_TRIM ); shell.setText( "Theme Switcher" ); shell.setLayout( new GridLayout() ); Button themeButton = new Button( shell, SWT.PUSH ); themeButton.setText( "Switch Theme" ); themeButton.addSelectionListener( new SelectionAdapter() { String[] availableThemeIds = ThemeUtil.getAvailableThemeIds(); @Override public void widgetSelected( SelectionEvent e ) { int index = 0; String currThemeId = ThemeUtil.getCurrentThemeId(); for( int i = 0; i < availableThemeIds.length; i++ ) { if( currThemeId.equals( availableThemeIds[ i ] ) ) { index = ( i + 1 ) % availableThemeIds.length; } } String newThemeId = availableThemeIds[ index ]; ThemeUtil.setCurrentThemeId( ContextProvider.getUISession(), newThemeId ); } } ); shell.pack(); shell.open(); } } ); } /** * Creates a combo that controls whether a cursor is set on the * registered controls. * * @return the created combo */ protected Combo createCursorCombo() { Composite group = new Composite( styleComp, SWT.NONE ); group.setLayout( new GridLayout( 2, false ) ); new Label( group, SWT.NONE ).setText( "Cursor" ); final Combo combo = new Combo( group, SWT.READ_ONLY ); combo.setItems( SWT_CURSORS ); combo.select( 0 ); combo.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent e ) { String selection = null; int index = combo.getSelectionIndex(); if( index > 0 ) { selection = combo.getItem( index ); } updateCursor( selection ); } } ); return combo; } /** * Creates a text that controls whether a border radius is set on the * registered controls. */ protected void cteateRoundedBorderGroup() { Group group = new Group( styleComp, SWT.NONE ); group.setText( "Rounded Border" ); group.setLayout( new GridLayout( 2, false ) ); new Label( group, SWT.NONE ).setText( "Width" ); final Text textWidth = new Text( group, SWT.SINGLE | SWT.BORDER ); textWidth.setLayoutData( new GridData( 20, SWT.DEFAULT ) ); new Label( group, SWT.NONE ).setText( "Color" ); final Button buttonColor = new Button( group, SWT.PUSH ); buttonColor.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { rbIndex = ( rbIndex + 1 ) % bgColors.length; if( bgColors[ rbIndex ] == null ) { buttonColor.setText( "" ); } else { buttonColor.setText( "\u2588" ); } buttonColor.setForeground( bgColors[ rbIndex ] ); } } ); new Label( group, SWT.NONE ).setText( "Radius " ); Composite radiusGroup = new Composite( group, SWT.NONE ); radiusGroup.setLayout( new GridLayout( 4, false ) ); new Label( radiusGroup, SWT.NONE ).setText( "T-L" ); final Text textTopLeft = new Text( radiusGroup, SWT.SINGLE | SWT.BORDER ); textTopLeft.setLayoutData( new GridData( 20, SWT.DEFAULT ) ); new Label( radiusGroup, SWT.NONE ).setText( "T-R" ); final Text textTopRight = new Text( radiusGroup, SWT.SINGLE | SWT.BORDER ); textTopRight.setLayoutData( new GridData( 20, SWT.DEFAULT ) ); new Label( radiusGroup, SWT.NONE ).setText( "B-L" ); final Text textBottomLeft = new Text( radiusGroup, SWT.SINGLE | SWT.BORDER ); textBottomLeft.setLayoutData( new GridData( 20, SWT.DEFAULT ) ); new Label( radiusGroup, SWT.NONE ).setText( "B-R" ); final Text textBottomRight = new Text( radiusGroup, SWT.SINGLE | SWT.BORDER ); textBottomRight.setLayoutData( new GridData( 20, SWT.DEFAULT ) ); Button button = new Button( group, SWT.PUSH ); button.setText( "Set" ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent e ) { int width = parseInt( textWidth.getText() ); Color color = buttonColor.getForeground(); int topLeft = parseInt( textTopLeft.getText() ); int topRight = parseInt( textTopRight.getText() ); int bottomRight = parseInt( textBottomRight.getText() ); int bottomLeft = parseInt( textBottomLeft.getText() ); updateRoundedBorder( width, color, topLeft, topRight, bottomRight, bottomLeft ); } } ); } protected Button createOrientationButton() { final Button button = new Button( styleComp, SWT.CHECK ); button.setText( "RIGHT_TO_LEFT orientation" ); button.setSelection( orientation == SWT.RIGHT_TO_LEFT ); button.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { orientation = button.getSelection() ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT; updateOrientation(); } } ); return button; } /** * Adds a control to the list of registered controls. Registered controls can * be hidden and disabled by the checkbuttons in the property area. This * method is to be called within <code>createExampleControls</code>. * * @param control A control that should be remote controlled. */ protected void registerControl( final Control control ) { controls.add( control ); control.addDisposeListener( new DisposeListener() { @Override public void widgetDisposed( DisposeEvent event ) { controls.remove( control ); } } ); } protected void log( String msg ) { content.insert( 0, msg.trim() + text.getLineDelimiter() ); text.setText( content.toString() ); } protected Image loadImage( String name ) { InputStream stream = getClass().getClassLoader().getResourceAsStream( name ); Image result = new Image( shell.getDisplay(), stream ); try { stream.close(); } catch( IOException ioe ) { throw new RuntimeException( ioe ); } return result; } private void destroyExampleControls() { Control[] controls = exampleComp.getChildren(); for( int i = 0; i < controls.length; i++ ) { controls[ i ].dispose(); } } protected int getStyle() { int result = SWT.NONE; Control[] ctrls = styleComp.getChildren(); if( ctrls.length == 0 ) { result = defaultStyle; } else { for( int i = 0; i < ctrls.length; i++ ) { if( ctrls[ i ] instanceof Button ) { Button button = ( Button )ctrls[ i ]; if( button.getSelection() ) { Object data = button.getData( "style" ); if( data instanceof Integer ) { int style = ( ( Integer )data ).intValue(); result |= style; } } } } } return result; } private void updateVisible( ) { Iterator<Control> iter = controls.iterator(); while( iter.hasNext() ) { Control control = iter.next(); control.setVisible( visible ); } } private void updateEnabled() { Iterator<Control> iter = controls.iterator(); while( iter.hasNext() ) { Control control = iter.next(); control.setEnabled( enabled ); } } private void updateOrientation() { Iterator<Control> iter = controls.iterator(); while( iter.hasNext() ) { Control control = iter.next(); control.setOrientation( orientation ); } } private void updateFgColor() { Iterator<Control> iter = controls.iterator(); while( iter.hasNext() ) { Control control = iter.next(); control.setForeground( fgColors[ fgIndex ] ); } } private void updateBgColor() { Iterator<Control> iter = controls.iterator(); while( iter.hasNext() ) { Control control = iter.next(); control.setBackground( bgColors[ bgIndex ] ); } } private void updateBgGradient() { Iterator<Control> iter = controls.iterator(); while( iter.hasNext() ) { Control control = iter.next(); Object adapter = control.getAdapter( IWidgetGraphicsAdapter.class ); IWidgetGraphicsAdapter gfxAdapter = ( IWidgetGraphicsAdapter )adapter; if( showBgGradient ) { int[] percents = new int[] { 0, 25, 50, 75, 100 }; gfxAdapter.setBackgroundGradient( gradientColors, percents, true ); } else { gfxAdapter.setBackgroundGradient( null, null, true ); } } } private void updateBgImage() { for( Control control : controls ) { Image image = Util.loadImage( control.getDisplay(), "resources/pattern.png" ); control.setBackgroundImage( showBgImage ? image : null ); } } private void updateFont() { Iterator<Control> iter = controls.iterator(); while( iter.hasNext() ) { Control control = iter.next(); control.setFont( font ); } // Force layout if( controls.size() > 0 ) { Composite parent = controls.get( 0 ).getParent(); parent.layout( true, true ); } } private void updateCursor( String selection ) { Cursor cursor = null; Class<SWT> swtClass = SWT.class; if( selection != null ) { try { Field field = swtClass.getField( selection ); int cursorStyle = field.getInt( swtClass ); cursor = Display.getCurrent().getSystemCursor( cursorStyle ); } catch( Exception e ) { e.printStackTrace(); } } Iterator<Control> iter = controls.iterator(); while( iter.hasNext() ) { Control control = iter.next(); control.setCursor( cursor ); } } private void updateRoundedBorder( int width, Color color, int topLeft, int topRight, int bottomRight, int bottomLeft ) { Iterator<Control> iter = controls.iterator(); while( iter.hasNext() ) { Control control = iter.next(); Object adapter = control.getAdapter( IWidgetGraphicsAdapter.class ); IWidgetGraphicsAdapter gfxAdapter = ( IWidgetGraphicsAdapter )adapter; gfxAdapter.setRoundedBorder( width, color, topLeft, topRight, bottomRight, bottomLeft ); } } private int parseInt( String text ) { int result; try { result = Integer.parseInt( text ); } catch( NumberFormatException e ) { result = -1; } return result; } protected Shell getShell() { return shell; } protected boolean checkControl( Control control ) { return control != null && !control.isDisposed(); } }