Package blackberry.ui.dialog.color

Source Code of blackberry.ui.dialog.color.ColorPickerPopup

/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/
package blackberry.ui.dialog.color;

import blackberry.ui.dialog.IWebWorksDialog;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Characters;
import net.rim.device.api.system.KeypadListener;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.PopupScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.util.MathUtilities;
import net.rim.device.api.util.NumberUtilities;

/**
* Implementation of color picker dialog
*
* @author jachoi
*
*/
public class ColorPickerDialog extends Field implements IWebWorksDialog {
    private int _selectedColor;

    public ColorPickerDialog( int initialColor ) {
        super( Field.FOCUSABLE );
        _selectedColor = initialColor;
        setPadding( 0, 0, 0, 0 );
    }

    public void setColor( int color ) {
        _selectedColor = color;
    }

    public int getPreferredWidth() {
        return (int) Math.ceil( getFont().getHeight() * 1.618 );
    }

    public int getPreferredHeight() {
        return getFont().getHeight();
    }

    protected void layout( int width, int height ) {
        setExtent( getPreferredWidth(), getPreferredHeight() );
    }

    protected void paint( Graphics g ) {
        int oldColor = g.getColor();
        try {
            // Color
            g.setColor( _selectedColor );
            g.fillRect( 0, 0, getWidth(), getHeight() );

            // Border
            g.setStrokeWidth( 1 );
            g.setColor( 0x000000 );
            g.drawRect( 0, 0, getWidth(), getHeight() );
        } finally {
            g.setColor( oldColor );
        }
    }

    protected void drawFocus( Graphics g, boolean on ) {
        int oldColor = g.getColor();
        try {
            g.setColor( 0x0000FF );
            g.drawRect( 0, 0, getWidth(), getHeight() );
            g.drawRect( 1, 1, getWidth() - 2, getHeight() - 2 );
        } finally {
            g.setColor( oldColor );
        }
    }

    private String colorToString( int color ) throws IllegalArgumentException {
        StringBuffer sb = new StringBuffer( 7 );
        sb.append( "#" );
        NumberUtilities.appendNumber( sb, color & 0x00FFFFFF, 16, 6 );
        return sb.toString();
    }

    public boolean show() {
        ColorPickerPopup picker = new ColorPickerPopup( _selectedColor );
        boolean result = picker.doModal();
        if( result ) {
            _selectedColor = picker.getSelectedColor();
            invalidate();
            fieldChangeNotify( 0 );
        }
        return result;
    }

    public Object getSelectedValue() {
        return colorToString( _selectedColor );
    }

    protected void paintBackground( Graphics g ) {
    }

    public void setDirty( boolean dirty ) {
        // We never want to be dirty or muddy
    }

    public void setMuddy( boolean muddy ) {
        // We never want to be dirty or muddy
    }
}

class BaseColorChooser extends Field {
    private static final int FIELD_HEIGHT = 100;
    private static final int FIELD_WIDTH = 40;
    private static final int NUM_COLOURS = 7;
    private static final int FRAME_THICKNESS = 2;
    private static final int FRAME_HEIGHT = 10;

    private int _selectedColor;

    private int[] _xcoords;
    private int[] _ycoords;
    private int[] _colors;
    private Bitmap _rainbow;

    private boolean _editing;
    private int _y;

    BaseColorChooser() {
        _y = FRAME_THICKNESS;
        int yStep = FIELD_HEIGHT / ( NUM_COLOURS - 1 );

        _xcoords = new int[] { 0, 0, 0, 0, 0, 0, 0, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH,
                FIELD_WIDTH };
        _ycoords = new int[] { 0, yStep, 2 * yStep, 3 * yStep, 4 * yStep, 5 * yStep, FIELD_HEIGHT, FIELD_HEIGHT, 5 * yStep,
                4 * yStep, 3 * yStep, 2 * yStep, yStep, 0 };
        _colors = new int[] { 0xff0000, 0xff00ff, 0x0000ff, 0x00ffff, 0x00ff00, 0xffff00, 0xff0000, 0xff0000, 0xffff00, 0x00ff00,
                0x00ffff, 0x0000ff, 0xff00ff, 0xff0000 };
    }

    public int getPreferredWidth() {
        return FIELD_WIDTH;
    }

    public int getPreferredHeight() {
        return FIELD_HEIGHT;
    }

    public int getSelectedColor() {
        return _selectedColor;
    }

    protected void layout( int width, int height ) {
        width = getPreferredWidth();
        height = getPreferredHeight();

        _rainbow = new Bitmap( width, height );
        Graphics rainbowGraphics = Graphics.create( _rainbow );
        rainbowGraphics.drawShadedFilledPath( _xcoords, _ycoords, null, _colors, null );

        setExtent( width, height );
    }

    protected void paint( Graphics g ) {
        int oldColor = g.getColor();
        try {
            // Rainbow
            g.drawBitmap( 0, 0, _rainbow.getWidth(), _rainbow.getHeight(), _rainbow, 0, 0 );

            // Border
            g.setColor( 0x000000 );
            g.drawRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT );
            if( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ) {
                g.setColor( Color.WHITE );
                g.drawRect( 1, 1, FIELD_WIDTH - 2, FIELD_HEIGHT - 2 );
            }

            int frameY = _y - ( FRAME_HEIGHT >> 1 );

            // draw the selector shadow
            frameY++;
            g.setColor( 0x000000 );
            g.fillRect( 0, frameY, FIELD_WIDTH, FRAME_THICKNESS ); // top
            g.fillRect( 0, frameY + FRAME_HEIGHT - FRAME_THICKNESS, FIELD_WIDTH, FRAME_THICKNESS ); // bottom
            frameY--;

            // draw selector foreground
            g.setColor( Color.WHITE );
            g.fillRect( 0, frameY, FIELD_WIDTH, FRAME_THICKNESS ); // top
            g.fillRect( 0, frameY + FRAME_HEIGHT - FRAME_THICKNESS, FIELD_WIDTH, FRAME_THICKNESS ); // bottom
            g.fillRect( 0, frameY, FRAME_THICKNESS, FRAME_HEIGHT ); // left
            g.fillRect( FIELD_WIDTH - FRAME_THICKNESS, frameY, FRAME_THICKNESS, FRAME_HEIGHT ); // right
        } finally {
            g.setColor( oldColor );
        }
    }

    protected void paintBackground( Graphics g ) {
    }

    protected void drawFocus( Graphics g, boolean on ) {
        boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
        try {
            g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
            paint( g );
        } finally {
            g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
        }
    }

    public boolean isFocusable() {
        return true;
    }

    protected boolean keyChar( char key, int status, int time ) {
        if( key == Characters.ESCAPE ) {
            if( _editing ) {
                return handleClick();
            }
        } else if( key == Characters.ENTER ) {
            return handleClick();
        }
        return super.keyChar( key, status, time );
    }

    protected boolean navigationMovement( int dx, int dy, int status, int time ) {
        return handleMovement( dx, dy );
    }

    protected boolean trackwheelRoll( int amount, int status, int time ) {
        if( ( status & KeypadListener.STATUS_ALT ) != 0 ) {
            return handleMovement( amount, 0 );
        } else {
            return handleMovement( 0, amount );
        }
    }

    private boolean handleMovement( int dx, int dy ) {
        if( _editing ) {
            int yMovement = dy * FIELD_HEIGHT / 20;

            _y = MathUtilities.clamp( 0, _y + yMovement, FIELD_HEIGHT - 1 );

            int[] argbData = new int[ 1 ];
            _rainbow.getARGB( argbData, 0, 1, 0, _y, 1, 1 );
            _selectedColor = argbData[ 0 ];

            invalidate( 0, 0, getWidth(), getHeight() );
            fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
            return true;
        }
        return false;
    }

    protected boolean navigationClick( int status, int time ) {
        return handleClick();
    }

    protected boolean trackwheelClick( int status, int time ) {
        return handleClick();
    }

    private boolean handleClick() {
        _editing = !_editing;
        invalidate( 0, 0, getWidth(), getHeight() );
        return true;
    }

    protected boolean touchEvent( TouchEvent message ) {
        if( message == null ) {
            throw new IllegalArgumentException( "ColorPickerField.touchEvent: TouchEvent message is null." );
        }
        boolean isConsumed = false;
        boolean isOutOfBounds = false;
        int x = message.getX( 1 );
        int y = message.getY( 1 );
        int[] argbData = new int[ 1 ];
        // Check to ensure point is within this field
        if( x <= 0 || y <= 0 || x > ( FIELD_WIDTH - 1 ) || y > ( FIELD_HEIGHT - 1 ) ) {
            isOutOfBounds = true;
        }
        switch( message.getEvent() ) {
            case TouchEvent.CLICK:
            case TouchEvent.MOVE:
                if( isOutOfBounds ) {
                    return true; // consume
                }
                _editing = true; // Pressed effect
                // update color
                _y = y;
                _rainbow.getARGB( argbData, 0, 1, 0, _y, 1, 1 );
                _selectedColor = argbData[ 0 ];
                invalidate( 0, 0, getWidth(), getHeight() );
                fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
                isConsumed = true;
                break;
            case TouchEvent.UNCLICK:
                if( isOutOfBounds ) {
                    _editing = false; // Reset presssed effect
                    return true;
                }

                // A field change notification is only sent on UNCLICK to allow for recovery
                // should the user cancel, i.e. click and move off the button

                _editing = false; // Reset pressed effect

                // update color
                _y = y;
                _rainbow.getARGB( argbData, 0, 1, 0, _y, 1, 1 );
                _selectedColor = argbData[ 0 ];
                invalidate( 0, 0, getWidth(), getHeight() );
                fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
                isConsumed = true;

                break;
        }
        return isConsumed;
    }

}

class TintChooser extends Field {
    private static final int FIELD_HEIGHT = 100;
    private static final int FIELD_WIDTH = 100;
    private static final int FRAME_SIZE = 10;
    private static final int FRAME_THICKNESS = 2;

    private int _baseColor;
    private int _selectedColor;

    private int[] _xcoords;
    private int[] _ycoords;
    private int[] _colors;
    private Bitmap _backgroundBitmap;

    private boolean _editing;

    private int _x;
    private int _y;

    TintChooser( int baseColor ) {
        _baseColor = baseColor;

        // init cursor position
        _x = FIELD_WIDTH - FRAME_SIZE / 2;
        _y = FRAME_SIZE;
    }

    public int getPreferredWidth() {
        return FIELD_WIDTH;
    }

    public int getPreferredHeight() {
        return FIELD_HEIGHT;
    }

    protected void layout( int width, int height ) {
        width = getPreferredWidth();
        height = getPreferredHeight();

        updateBitmap();

        setExtent( width, height );
    }

    public void setColor( int newColor ) {
        _baseColor = newColor;
        updateBitmap();
        invalidate();
    }

    private void updateBitmap() {
        int width = getPreferredWidth();
        int height = getPreferredHeight();

        _xcoords = new int[] { 0, 0, width, width };
        _ycoords = new int[] { 0, height, height, 0 };
        _colors = new int[] { 0xFFFFFF, 0x000000, 0x000000, _baseColor };

        // make new bitmap
        _backgroundBitmap = new Bitmap( width, height );// Bitmap.ROWWISE_MONOCHROME , width, height);// Bitmap.DEFAULT_TYPE,
                                                        // width, height );
        Graphics bitmapGraphics = Graphics.create( _backgroundBitmap );
        bitmapGraphics.drawShadedFilledPath( _xcoords, _ycoords, null, _colors, null );

        // Update selected color
        int[] argbData = new int[ 1 ];
        _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 );
        _selectedColor = argbData[ 0 ];
    }

    protected void paint( Graphics g ) {
        // Rainbow
        g.drawBitmap( 0, 0, _backgroundBitmap.getWidth(), _backgroundBitmap.getHeight(), _backgroundBitmap, 0, 0 );

        // Border
        g.setColor( 0x000000 );
        g.drawRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT );
        if( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ) {
            g.setColor( Color.WHITE );
            g.drawRect( 1, 1, FIELD_WIDTH - 2, FIELD_HEIGHT - 2 );
        }

        // Selector
        int frameX = _x;
        int frameY = _y;

        int oldColor = g.getColor();
        try {
            // draw the selector
            g.setColor( 0x000000 );
            frameX++;
            frameY++;

            // Shadow Left, Right, Top, Bottom
            g.fillRect( frameX - FRAME_SIZE / 2, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS );
            g.fillRect( frameX + FRAME_THICKNESS, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS );
            g.fillRect( frameX - FRAME_THICKNESS / 2, frameY - FRAME_SIZE / 2, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS );
            g.fillRect( frameX - FRAME_THICKNESS / 2, frameY + FRAME_THICKNESS, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS );

            frameX--;
            frameY--;

            g.setColor( Color.WHITE );
            // Left, Right, Top, Bottom
            g.fillRect( frameX - FRAME_SIZE / 2, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS );
            g.fillRect( frameX + FRAME_THICKNESS, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS );
            g.fillRect( frameX - FRAME_THICKNESS / 2, frameY - FRAME_SIZE / 2, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS );
            g.fillRect( frameX - FRAME_THICKNESS / 2, frameY + FRAME_THICKNESS, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS );
        } finally {
            g.setColor( oldColor );
        }
    }

    protected void paintBackground( Graphics g ) {
    }

    protected void drawFocus( Graphics g, boolean on ) {
        boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
        try {
            g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
            paint( g );
        } finally {
            g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
        }
    }

    public boolean isFocusable() {
        return true;
    }

    protected boolean keyChar( char key, int status, int time ) {
        if( key == Characters.ESCAPE ) {
            if( _editing ) {
                return handleClick();
            }
        } else if( key == Characters.ENTER ) {
            return handleClick();
        }
        return super.keyChar( key, status, time );
    }

    protected boolean navigationMovement( int dx, int dy, int status, int time ) {
        return handleMovement( dx, dy );
    }

    protected boolean trackwheelRoll( int amount, int status, int time ) {
        if( ( status & KeypadListener.STATUS_ALT ) != 0 ) {
            return handleMovement( amount, 0 );
        } else {
            return handleMovement( 0, amount );
        }
    }

    private boolean handleMovement( int dx, int dy ) {
        if( _editing ) {
            int xMovement = dx * FIELD_WIDTH / 20;
            int yMovement = dy * FIELD_HEIGHT / 20;

            _x = MathUtilities.clamp( 0, _x + xMovement, FIELD_WIDTH - 1 );
            _y = MathUtilities.clamp( 0, _y + yMovement, FIELD_HEIGHT - 1 );

            int[] argbData = new int[ 1 ];
            _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 );
            _selectedColor = argbData[ 0 ];

            invalidate( 0, 0, getWidth(), getHeight() );
            fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
            return true;
        }
        return false;
    }

    public int getSelectedColor() {
        return _selectedColor;
    }

    protected boolean navigationClick( int status, int time ) {
        return handleClick();
    }

    protected boolean trackwheelClick( int status, int time ) {
        return handleClick();
    }

    private boolean handleClick() {
        _editing = !_editing;
        invalidate( 0, 0, getWidth(), getHeight() );
        return true;
    }

    protected boolean touchEvent( TouchEvent message ) {
        if( message == null ) {
            throw new IllegalArgumentException( "ButtonField.touchEvent: TouchEvent message is null." );
        }
        boolean isConsumed = false;
        boolean isOutOfBounds = false;
        int x = message.getX( 1 );
        int y = message.getY( 1 );
        // Check to ensure point is within this field
        if( x <= 0 || y <= 0 || x > ( FIELD_WIDTH - 1 ) || y > ( FIELD_HEIGHT - 1 ) ) {
            isOutOfBounds = true;
        }
        int[] argbData = new int[ 1 ];
        switch( message.getEvent() ) {
            case TouchEvent.CLICK:
            case TouchEvent.MOVE:
                if( isOutOfBounds ) {
                    return true; // consume
                }
                _editing = true; // Pressed effect
                // update color
                _x = x;
                _y = y;
                _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 );
                _selectedColor = argbData[ 0 ];
                invalidate( 0, 0, getWidth(), getHeight() );
                fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
                isConsumed = true;
                break;
            case TouchEvent.UNCLICK:
                if( isOutOfBounds ) {
                    _editing = false; // Reset presssed effect
                    return true;
                }

                // A field change notification is only sent on UNCLICK to allow for recovery
                // should the user cancel, i.e. click and move off the button

                _editing = false; // Reset pressed effect

                // update state
                _x = x;
                _y = y;
                _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 );
                _selectedColor = argbData[ 0 ];
                invalidate( 0, 0, getWidth(), getHeight() );
                fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
                isConsumed = true;
                break;
        }
        return isConsumed;
    }
}

class ColorPreviewField extends Field {
    private static final int FIELD_WIDTH = 40;
    private static final int FIELD_HEIGHT = 30;

    private int _color;

    ColorPreviewField( int color ) {
        _color = color;
    }

    public int getPreferredWidth() {
        return FIELD_WIDTH;
    }

    public int getPreferredHeight() {
        return FIELD_HEIGHT;
    }

    protected void layout( int width, int height ) {
        setExtent( getPreferredWidth(), getPreferredHeight() );
    }

    public void setColor( int color ) {
        _color = color;
        invalidate();
    }

    protected void paint( Graphics g ) {
        int oldColor = g.getColor();
        try {
            g.setColor( _color );
            g.fillRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT );

            g.setColor( 0x000000 );
            g.drawRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT );
        } finally {
            g.setColor( oldColor );
        }
    }
}

class ColorPickerPopup extends PopupScreen implements FieldChangeListener {
    private BaseColorChooser _baseColorChooser;
    private TintChooser _tintChooser;
    private ColorPreviewField _previewField;
    private ButtonField _okButton;

    private final int PADDING = 4;
    private final int PADDING_BOTTOM = 39;
    private final String OK = "OK";

    public ColorPickerPopup( int initialColor ) {
        super( new HorizontalFieldManager() );
        setPadding( PADDING, PADDING, PADDING, PADDING );
        _baseColorChooser = new BaseColorChooser();
        _baseColorChooser.setPadding( PADDING, PADDING, PADDING, PADDING );
        _baseColorChooser.setChangeListener( this );
        add( _baseColorChooser );

        _tintChooser = new TintChooser( initialColor );
        _tintChooser.setPadding( PADDING, PADDING, PADDING, PADDING );
        _tintChooser.setChangeListener( this );
        add( _tintChooser );

        VerticalFieldManager previewPane = new VerticalFieldManager();

        _previewField = new ColorPreviewField( initialColor );
        _previewField.setPadding( PADDING, PADDING, PADDING + PADDING_BOTTOM, PADDING );
        previewPane.add( _previewField );

        _okButton = new ButtonField( OK );
        _okButton.setChangeListener( this );
        previewPane.add( _okButton );

        add( previewPane );
    }

    public void fieldChanged( Field field, int context ) {
        field.setDirty( false ); // don't want the save dialog
        if( field == _baseColorChooser ) {
            // Get color from base chooser
            // Update the tint chooser
            // Update the result color
            _tintChooser.setColor( _baseColorChooser.getSelectedColor() );
            _previewField.setColor( _tintChooser.getSelectedColor() );
        } else if( field == _tintChooser ) {
            // Update the result color
            _previewField.setColor( _tintChooser.getSelectedColor() );
        } else if( field == _okButton ) {
            close();
        }
    }

    protected boolean keyChar( char key, int status, int time ) {
        if( key == Characters.ESCAPE ) {
            close();
            return true;
        } else if( key == Characters.ENTER ) {
            close();
            return true;
        }
        return super.keyChar( key, status, time );
    }

    public int getSelectedColor() {
        return _tintChooser.getSelectedColor();
    }

    public boolean doModal() {
        UiApplication.getUiApplication().pushModalScreen( this );
        return true;
    }
}
TOP

Related Classes of blackberry.ui.dialog.color.ColorPickerPopup

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.