- add sources.
[platform/framework/web/crosswalk.git] / src / ui / android / java / src / org / chromium / ui / ColorPickerSimple.java
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 package org.chromium.ui;
5
6 import android.content.Context;
7 import android.graphics.Canvas;
8 import android.graphics.Color;
9 import android.graphics.Paint;
10 import android.graphics.Rect;
11 import android.util.AttributeSet;
12 import android.view.MotionEvent;
13 import android.view.View;
14
15
16 /**
17  * Draws a grid of (predefined) colors and allows the user to choose one of
18  * those colors.
19  */
20 public class ColorPickerSimple extends View {
21     private static final int ROW_COUNT = 2;
22
23     private static final int COLUMN_COUNT = 4;
24
25     private static final int GRID_CELL_COUNT = ROW_COUNT * COLUMN_COUNT;
26
27     private static final int[] COLORS = { Color.RED,
28                                           Color.CYAN,
29                                           Color.BLUE,
30                                           Color.GREEN,
31                                           Color.MAGENTA,
32                                           Color.YELLOW,
33                                           Color.BLACK,
34                                           Color.WHITE
35                                         };
36
37     private Paint mBorderPaint;
38
39     private Rect[] mBounds;
40
41     private Paint[] mPaints;
42
43     private OnColorChangedListener mOnColorTouchedListener;
44
45     private int mLastTouchedXPosition;
46
47     private int mLastTouchedYPosition;
48
49     public ColorPickerSimple(Context context) {
50         super(context);
51     }
52
53     public ColorPickerSimple(Context context, AttributeSet attrs) {
54         super(context, attrs);
55     }
56
57     public ColorPickerSimple(Context context, AttributeSet attrs, int defStyle) {
58         super(context, attrs, defStyle);
59     }
60
61     /**
62      * Initializes the listener and precalculates the grid and color positions.
63      *
64      * @param onColorChangedListener The listener that gets notified when the user touches
65      *                               a color.
66      */
67     public void init(OnColorChangedListener onColorChangedListener) {
68         mOnColorTouchedListener = onColorChangedListener;
69
70         // This will get calculated when the layout size is updated.
71         mBounds = null;
72
73         mPaints = new Paint[GRID_CELL_COUNT];
74         for (int i = 0; i < GRID_CELL_COUNT; ++i) {
75             Paint newPaint = new Paint();
76             newPaint.setColor(COLORS[i]);
77             mPaints[i] = newPaint;
78         }
79
80         mBorderPaint = new Paint();
81         int borderColor = getContext().getResources().getColor(R.color.color_picker_border_color);
82         mBorderPaint.setColor(borderColor);
83
84         // Responds to the user touching the grid and works out which color has been chosen as
85         // a result, depending on the X,Y coordinate. Note that we respond to the click event
86         // here, but the onClick() method doesn't provide us with the X,Y coordinates, so we
87         // track them in onTouchEvent() below. This way the grid reacts properly to touch events
88         // whereas if we put this onClick() code in onTouchEvent below then we get some strange
89         // interactions with the ScrollView in the parent ColorPickerDialog.
90         setOnClickListener(new OnClickListener() {
91             @Override
92             public void onClick(View v) {
93                 if (mOnColorTouchedListener != null && getWidth() > 0 && getHeight() > 0) {
94                     int column = mLastTouchedXPosition * COLUMN_COUNT / getWidth();
95                     int row = mLastTouchedYPosition * ROW_COUNT / getHeight();
96
97                     int colorIndex = (row * COLUMN_COUNT) + column;
98                     if (colorIndex >= 0 && colorIndex < COLORS.length) {
99                         mOnColorTouchedListener.onColorChanged(COLORS[colorIndex]);
100                     }
101                 }
102             }
103         });
104     }
105
106     /**
107      * Draws the grid of colors, based on the rectangles calculated in onSizeChanged().
108      * Also draws borders in between the colored rectangles.
109      *
110      * @param canvas The canvas the colors are drawn onto.
111      */
112     @Override
113     public void onDraw(Canvas canvas) {
114         if (mBounds == null || mPaints == null) {
115             return;
116         }
117
118         canvas.drawColor(Color.WHITE);
119
120         // Draw the actual colored rectangles.
121         for (int i = 0; i < GRID_CELL_COUNT; ++i) {
122             canvas.drawRect(mBounds[i], mPaints[i]);
123         }
124
125         // Draw 1px borders between the rows.
126         for (int i = 0; i < ROW_COUNT - 1; ++i) {
127           canvas.drawLine(0,
128                   mBounds[i * COLUMN_COUNT].bottom + 1,
129                   getWidth(),
130                   mBounds[i * COLUMN_COUNT].bottom + 1,
131                   mBorderPaint);
132         }
133
134         // Draw 1px borders between the columns.
135         for (int j = 0; j < COLUMN_COUNT - 1; ++j) {
136           canvas.drawLine(mBounds[j].right + 1,
137                   0,
138                   mBounds[j].right + 1,
139                   getHeight(),
140                   mBorderPaint);
141         }
142     }
143
144     /**
145      * Stores the X,Y coordinates of the touch so that we can use them in the onClick() listener
146      * above to work out where the click was on the grid.
147      *
148      * @param event The MotionEvent the X,Y coordinates are retrieved from.
149      */
150     @Override
151     public boolean onTouchEvent(MotionEvent event) {
152         if (event.getAction() == MotionEvent.ACTION_DOWN) {
153             mLastTouchedXPosition = (int) event.getX();
154             mLastTouchedYPosition = (int) event.getY();
155         }
156         return super.onTouchEvent(event);
157     }
158
159     /**
160      * Recalculates the color grid with the new sizes.
161      */
162     @Override
163     protected void onSizeChanged(int width, int height, int oldw, int oldh) {
164         calculateGrid(width, height);
165     }
166
167     /**
168      * Calculates the sizes and positions of the cells in the grid, splitting
169      * them up as evenly as possible. Leaves 3 pixels between each cell so that
170      * we can draw a border between them as well, and leaves a pixel around the
171      * edge.
172      */
173     private void calculateGrid(final int width, final int height) {
174         mBounds = new Rect[GRID_CELL_COUNT];
175
176         for (int i = 0; i < ROW_COUNT; ++i) {
177             for (int j = 0; j < COLUMN_COUNT; ++j) {
178                 int left = j * (width + 1) / COLUMN_COUNT + 1;
179                 int right = (j + 1) * (width + 1) / COLUMN_COUNT - 2;
180
181                 int top = i * (height + 1) / ROW_COUNT + 1;
182                 int bottom = (i + 1) * (height + 1) / ROW_COUNT - 2;
183
184                 Rect rect = new Rect(left, top, right, bottom);
185                 mBounds[(i * COLUMN_COUNT) + j] = rect;
186             }
187         }
188     }
189 }