1 /*******************************************************************************
2  * Copyright (c) 2006, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
14  *     											 - fix in bug: 195908,198035,215069,215735,227421
15  *******************************************************************************/
16 
17 package org.eclipse.jface.viewers;
18 
19 import java.util.Objects;
20 
21 import org.eclipse.swt.custom.StyleRange;
22 import org.eclipse.swt.graphics.Color;
23 import org.eclipse.swt.graphics.Font;
24 import org.eclipse.swt.graphics.Image;
25 import org.eclipse.swt.graphics.Rectangle;
26 import org.eclipse.swt.widgets.Control;
27 import org.eclipse.swt.widgets.Item;
28 import org.eclipse.swt.widgets.Widget;
29 
30 /**
31  * The ViewerCell is the JFace representation of a cell entry in a ViewerRow.
32  *
33  * @since 3.3
34  *
35  */
36 public class ViewerCell {
37 	private int columnIndex;
38 
39 	private ViewerRow row;
40 
41 	private Object element;
42 
43 	/**
44 	 * Constant denoting the cell above current one (value is 1).
45 	 */
46 	public static int ABOVE = 1;
47 
48 	/**
49 	 * Constant denoting the cell below current one (value is 2).
50 	 */
51 	public static int BELOW = 1 << 1;
52 
53 	/**
54 	 * Constant denoting the cell to the left of the current one (value is 4).
55 	 */
56 	public static int LEFT = 1 << 2;
57 
58 	/**
59 	 * Constant denoting the cell to the right of the current one (value is 8).
60 	 */
61 	public static int RIGHT = 1 << 3;
62 
63 	/**
64 	 * Create a new instance of the receiver on the row.
65 	 *
66 	 * @param row
67 	 * @param columnIndex
68 	 */
ViewerCell(ViewerRow row, int columnIndex, Object element)69 	ViewerCell(ViewerRow row, int columnIndex, Object element) {
70 		this.row = row;
71 		this.columnIndex = columnIndex;
72 		this.element = element;
73 	}
74 
75 	/**
76 	 * Get the index of the cell.
77 	 *
78 	 * @return the index
79 	 */
getColumnIndex()80 	public int getColumnIndex() {
81 		return columnIndex;
82 	}
83 
84 	/**
85 	 * Get the bounds of the cell.
86 	 *
87 	 * @return {@link Rectangle}
88 	 */
getBounds()89 	public Rectangle getBounds() {
90 		return row.getBounds(columnIndex);
91 	}
92 
93 	/**
94 	 * Get the element this row represents.
95 	 *
96 	 * @return {@link Object}
97 	 */
getElement()98 	public Object getElement() {
99 		if (element != null) {
100 			return element;
101 		}
102 
103 		if (row != null) {
104 			return row.getElement();
105 		}
106 
107 		return null;
108 	}
109 
110 	/**
111 	 * Return the text for the cell.
112 	 *
113 	 * @return {@link String}
114 	 */
getText()115 	public String getText() {
116 		return row.getText(columnIndex);
117 	}
118 
119 	/**
120 	 * Return the Image for the cell.
121 	 *
122 	 * @return {@link Image} or <code>null</code>
123 	 */
getImage()124 	public Image getImage() {
125 		return row.getImage(columnIndex);
126 	}
127 
128 	/**
129 	 * Set the background color of the cell.
130 	 *
131 	 * @param background color to set
132 	 */
setBackground(Color background)133 	public void setBackground(Color background) {
134 		row.setBackground(columnIndex, background);
135 
136 	}
137 
138 	/**
139 	 * Set the foreground color of the cell.
140 	 *
141 	 * @param foreground color to set
142 	 */
setForeground(Color foreground)143 	public void setForeground(Color foreground) {
144 		row.setForeground(columnIndex, foreground);
145 
146 	}
147 
148 	/**
149 	 * Set the font of the cell.
150 	 *
151 	 * @param font font to set
152 	 */
setFont(Font font)153 	public void setFont(Font font) {
154 		row.setFont(columnIndex, font);
155 
156 	}
157 
158 	/**
159 	 * Set the text for the cell.
160 	 *
161 	 * @param text text to set
162 	 */
setText(String text)163 	public void setText(String text) {
164 		row.setText(columnIndex, text);
165 
166 	}
167 
168 	/**
169 	 * Set the Image for the cell.
170 	 *
171 	 * @param image image to set
172 	 */
setImage(Image image)173 	public void setImage(Image image) {
174 		row.setImage(columnIndex, image);
175 
176 	}
177 
178 	/**
179 	 * Set the style ranges to be applied on the text label Note: Requires
180 	 * {@link StyledCellLabelProvider} with owner draw enabled.
181 	 *
182 	 * @param styleRanges
183 	 *            the styled ranges
184 	 *
185 	 * @since 3.4
186 	 */
setStyleRanges(StyleRange[] styleRanges)187 	public void setStyleRanges(StyleRange[] styleRanges) {
188 		row.setStyleRanges(columnIndex, styleRanges);
189 	}
190 
191 	/**
192 	 * Returns the style ranges to be applied on the text label or
193 	 * <code>null</code> if no style ranges have been set.
194 	 *
195 	 * @return styleRanges the styled ranges
196 	 *
197 	 * @since 3.4
198 	 */
getStyleRanges()199 	public StyleRange[] getStyleRanges() {
200 		return row.getStyleRanges(columnIndex);
201 	}
202 
203 	/**
204 	 * Set the columnIndex.
205 	 *
206 	 * @param column the column index to set
207 	 */
setColumn(int column)208 	void setColumn(int column) {
209 		columnIndex = column;
210 
211 	}
212 
213 	/**
214 	 * Set the row to rowItem and the columnIndex to column.
215 	 *
216 	 * @param rowItem the row item to set
217 	 * @param column  the column index to set
218 	 * @param element the element to set
219 	 */
update(ViewerRow rowItem, int column, Object element)220 	void update(ViewerRow rowItem, int column, Object element) {
221 		row = rowItem;
222 		columnIndex = column;
223 		this.element = element;
224 	}
225 
226 	/**
227 	 * Return the item for the receiver.
228 	 *
229 	 * @return {@link Item}
230 	 */
getItem()231 	public Widget getItem() {
232 		return row.getItem();
233 	}
234 
235 	/**
236 	 * Get the control for this cell.
237 	 *
238 	 * @return {@link Control}
239 	 */
getControl()240 	public Control getControl() {
241 		return row.getControl();
242 	}
243 
244 	/**
245 	 * Get the current index. This can be different from the original index when
246 	 * columns are reordered
247 	 *
248 	 * @return the current index (as shown in the UI)
249 	 * @since 3.4
250 	 */
getVisualIndex()251 	public int getVisualIndex() {
252 		return row.getVisualIndex(getColumnIndex());
253 	}
254 
255 	/**
256 	 * Returns the specified neighbor of this cell, or <code>null</code> if no
257 	 * neighbor exists in the given direction. Direction constants can be
258 	 * combined by bitwise OR; for example, this method will return the cell to
259 	 * the upper-left of the current cell by passing {@link #ABOVE} |
260 	 * {@link #LEFT}. If <code>sameLevel</code> is <code>true</code>, only cells
261 	 * in sibling rows (under the same parent) will be considered.
262 	 *
263 	 * @param directionMask
264 	 *            the direction mask used to identify the requested neighbor
265 	 *            cell
266 	 * @param sameLevel
267 	 *            if <code>true</code>, only consider cells from sibling rows
268 	 * @return the requested neighbor cell, or <code>null</code> if not found
269 	 */
getNeighbor(int directionMask, boolean sameLevel)270 	public ViewerCell getNeighbor(int directionMask, boolean sameLevel) {
271 		ViewerRow row;
272 
273 		if ((directionMask & ABOVE) == ABOVE) {
274 			row = this.row.getNeighbor(ViewerRow.ABOVE, sameLevel);
275 		} else if ((directionMask & BELOW) == BELOW) {
276 			row = this.row.getNeighbor(ViewerRow.BELOW, sameLevel);
277 		} else {
278 			row = this.row;
279 		}
280 
281 		if (row != null) {
282 			int columnIndex;
283 			columnIndex = getVisualIndex();
284 
285 			int modifier = 0;
286 
287 			if ((directionMask & LEFT) == LEFT) {
288 				modifier = -1;
289 			} else if ((directionMask & RIGHT) == RIGHT) {
290 				modifier = 1;
291 			} else {
292 				return row.getCellAtVisualIndex(columnIndex);
293 			}
294 
295 			columnIndex += modifier;
296 
297 			if (columnIndex >= 0 && columnIndex < row.getColumnCount()) {
298 				ViewerCell cell = row.getCellAtVisualIndex(columnIndex);
299 				while (cell != null && columnIndex < row.getColumnCount() - 1 && columnIndex > 0) {
300 					if (cell.isVisible()) {
301 						break;
302 					}
303 
304 					columnIndex += modifier;
305 					cell = row.getCellAtVisualIndex(columnIndex);
306 				}
307 
308 				return cell;
309 			}
310 		}
311 
312 		return null;
313 	}
314 
315 	/**
316 	 * @return the row
317 	 */
getViewerRow()318 	public ViewerRow getViewerRow() {
319 		return row;
320 	}
321 
322 	/**
323 	 * The location and bounds of the area where the text is drawn depends on
324 	 * various things (image displayed, control with SWT.CHECK)
325 	 *
326 	 * @return The bounds of the of the text area. May return <code>null</code>
327 	 *         if the underlying widget implementation doesn't provide this
328 	 *         information
329 	 * @since 3.4
330 	 */
getTextBounds()331 	public Rectangle getTextBounds() {
332 		return row.getTextBounds(columnIndex);
333 	}
334 
335 	/**
336 	 * Returns the location and bounds of the area where the image is drawn
337 	 *
338 	 * @return The bounds of the of the image area. May return <code>null</code>
339 	 *         if the underlying widget implementation doesn't provide this
340 	 *         information
341 	 * @since 3.4
342 	 */
getImageBounds()343 	public Rectangle getImageBounds() {
344 		return row.getImageBounds(columnIndex);
345 	}
346 
347 	/**
348 	 * Gets the foreground color of the cell.
349 	 *
350 	 * @return the foreground of the cell or <code>null</code> for the default
351 	 *         foreground
352 	 *
353 	 * @since 3.4
354 	 */
getForeground()355 	public Color getForeground() {
356 		return row.getForeground(columnIndex);
357 	}
358 
359 	/**
360 	 * Gets the background color of the cell.
361 	 *
362 	 * @return the background of the cell or <code>null</code> for the default
363 	 *         background
364 	 *
365 	 * @since 3.4
366 	 */
getBackground()367 	public Color getBackground() {
368 		return row.getBackground(columnIndex);
369 	}
370 
371 	/**
372 	 * Gets the font of the cell.
373 	 *
374 	 * @return the font of the cell or <code>null</code> for the default font
375 	 *
376 	 * @since 3.4
377 	 */
getFont()378 	public Font getFont() {
379 		return row.getFont(columnIndex);
380 	}
381 
382 	@Override
hashCode()383 	public int hashCode() {
384 		final int prime = 31;
385 		int result = 1;
386 		result = prime * result + columnIndex;
387 		return prime * result + Objects.hashCode(row);
388 	}
389 
390 	@Override
equals(Object obj)391 	public boolean equals(Object obj) {
392 		if (this == obj)
393 			return true;
394 		if (obj == null)
395 			return false;
396 		if (getClass() != obj.getClass())
397 			return false;
398 		final ViewerCell other = (ViewerCell) obj;
399 		return columnIndex == other.columnIndex && Objects.equals(row, other.row);
400 	}
401 
isVisible()402 	private boolean isVisible() {
403 		return row.isColumnVisible(columnIndex);
404 	}
405 
406 	/**
407 	 * Scroll the cell into view
408 	 *
409 	 * @return true if the cell was scrolled into view
410 	 * @since 3.5
411 	 */
scrollIntoView()412 	public boolean scrollIntoView() {
413 		return row.scrollCellIntoView(columnIndex);
414 	}
415 }
416