1 /***
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are
4 * met :
5 *
6 * . Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 *
9 * . Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * . The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id$
29 */
30
31 package palmed.edit;
32
33 import javax.microedition.lcdui.Graphics;
34 import javax.microedition.lcdui.Item;
35 import palmed.edit.selection.ISelectionView;
36 import palmed.edit.util.Coordinate;
37 import palmed.edit.view.Viewport;
38 import palmed.ui.IComponent;
39
40 /***
41 * This class implements a text area component.
42 *
43 * @author Mathieu Champlon
44 * @version $Revision$ $Date$
45 */
46 public final class TextArea implements IComponent, ISelectionView
47 {
48 /***
49 * The background color.
50 */
51 private static final int BACKGROUND_COLOR = 0xFFFFFF;
52 /***
53 * The cursor color.
54 */
55 private static final int CURSOR_COLOR = 0x000000;
56 /***
57 * The cursor width in pixels.
58 */
59 private static final int CURSOR_WIDTH = 2;
60 /***
61 * Current view size in pixels.
62 */
63 private int width_, height_;
64 /***
65 * The font to display the text.
66 */
67 private IFont font_;
68 /***
69 * The current cursor position.
70 */
71 private final Coordinate cursorPosition_;
72 /***
73 * The viewport.
74 */
75 private final Viewport viewport_;
76
77 /***
78 * Create a text area component.
79 *
80 * @param viewport the viewport
81 */
82 public TextArea( final Viewport viewport )
83 {
84 if( viewport == null )
85 throw new IllegalArgumentException( "parameter 'viewport' is null" );
86 viewport_ = viewport;
87 font_ = new MonospacedFont( "ProFontWindows_12" );
88 cursorPosition_ = new Coordinate();
89 }
90
91 /***
92 * {@inheritDoc}
93 */
94 public void paint( final Graphics g )
95 {
96 paintBackground( g );
97 paintText( g );
98 paintCursor( g );
99 }
100
101 private void paintBackground( final Graphics g )
102 {
103 g.setColor( BACKGROUND_COLOR );
104 g.fillRect( 0, 0, width_, height_ );
105 }
106
107 private void paintText( final Graphics g )
108 {
109 final LineDrawer drawer = new LineDrawer( font_, width_ / font_.getWidth() + 1 );
110 for( int y = 0; y < height_ / font_.getHeight() + 1; ++y )
111 {
112 drawer.configure( g, y );
113 viewport_.accept( drawer, y );
114 }
115 }
116
117 private void paintCursor( final Graphics g )
118 {
119 g.setColor( CURSOR_COLOR );
120 g.fillRect( cursorPosition_.x_, cursorPosition_.y_, CURSOR_WIDTH, font_.getHeight() );
121 }
122
123 /***
124 * {@inheritDoc}
125 */
126 public void resize( final int width, final int height )
127 {
128 width_ = width;
129 height_ = height;
130 viewport_.resize( getColumns(), getLines() );
131 }
132
133 /***
134 * {@inheritDoc}
135 */
136 public int getLayout()
137 {
138 return Item.LAYOUT_EXPAND + Item.LAYOUT_VEXPAND;
139 }
140
141 /***
142 * {@inheritDoc}
143 */
144 public int getWidth()
145 {
146 return width_;
147 }
148
149 /***
150 * {@inheritDoc}
151 */
152 public int getHeight()
153 {
154 return height_;
155 }
156
157 /***
158 * {@inheritDoc}
159 */
160 public boolean click( final int x, final int y )
161 {
162 viewport_.click( pixelToColumn( x ), pixelToLine( y ) );
163 return true;
164 }
165
166 /***
167 * {@inheritDoc}
168 */
169 public void drag( final int x, final int y )
170 {
171 viewport_.drag( pixelToColumn( x ), pixelToLine( y ) );
172 }
173
174 /***
175 * {@inheritDoc}
176 */
177 public void unclick( final int x, final int y )
178 {
179 }
180
181 /***
182 * {@inheritDoc}
183 */
184 public void update( final Coordinate position )
185 {
186 cursorPosition_.x_ = columnToPixel( position.x_ );
187 cursorPosition_.y_ = lineToPixel( position.y_ );
188 }
189
190 private int pixelToColumn( final int x )
191 {
192 return (x + font_.getWidth() / 2) / font_.getWidth();
193 }
194
195 private int pixelToLine( final int y )
196 {
197 if( y == 0 )
198 return -1;
199 return y / font_.getHeight();
200 }
201
202 private int lineToPixel( final int line )
203 {
204 return line * font_.getHeight();
205 }
206
207 private int columnToPixel( final int column )
208 {
209 final int x = column * font_.getWidth() - 1;
210 if( x == -1 )
211 return 0;
212 return x;
213 }
214
215 /***
216 * Retrieve the number of lines.
217 *
218 * @return the number of lines
219 */
220 public int getLines()
221 {
222 return height_ / font_.getHeight();
223 }
224
225 /***
226 * Retrieve the number of columns.
227 *
228 * @return the number of columns
229 */
230 public int getColumns()
231 {
232 return width_ / font_.getWidth();
233 }
234
235 /***
236 * Change the font.
237 *
238 * @param name the font resource name
239 */
240 public void setFont( final String name )
241 {
242 font_ = new MonospacedFont( name );
243 viewport_.resize( getColumns(), getLines() );
244 }
245 }