View Javadoc

1   /*
2    * This file is a part of CAST project.
3    * (c) Copyright 2007, AGH University of Science & Technology
4    * https://caribou.iisg.agh.edu.pl/trac/cast
5    *
6    * Licensed under the Eclipse Public License, Version 1.0 (the "License").
7    * You may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    * http://www.eclipse.org/legal/epl-v10.html
10   */
11  /*
12   * File: ButtonTableCreator.java
13   * Created: 2009-04-30
14   * Author: bmilos
15   * $Id$
16   */
17  
18  package pl.edu.agh.cast.importer.wizard.utils;
19  
20  import java.text.SimpleDateFormat;
21  import java.util.Collections;
22  import java.util.Date;
23  import java.util.LinkedList;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Map.Entry;
27  
28  import org.eclipse.swt.SWT;
29  import org.eclipse.swt.custom.TableEditor;
30  import org.eclipse.swt.events.SelectionAdapter;
31  import org.eclipse.swt.events.SelectionEvent;
32  import org.eclipse.swt.graphics.Color;
33  import org.eclipse.swt.layout.GridData;
34  import org.eclipse.swt.widgets.Button;
35  import org.eclipse.swt.widgets.Composite;
36  import org.eclipse.swt.widgets.Table;
37  import org.eclipse.swt.widgets.TableColumn;
38  import org.eclipse.swt.widgets.TableItem;
39  
40  import pl.edu.agh.cast.importer.base.data.DataRow;
41  import pl.edu.agh.cast.importer.base.data.TabularData;
42  import pl.edu.agh.cast.importer.wizard.util.Messages;
43  
44  /**
45   * SWT table creator, which creates tables with "select" buttons as labels.
46   * 
47   * @author AGH CAST Team
48   */
49  public class ButtonTableCreator {
50  
51  	private static final int MAX_ROWS_TO_DISPLAY = 50;
52  
53  	private static final Color GRAY = new Color(null, 200, 200, 200);
54  
55  	private static final Color WHITE = new Color(null, 255, 255, 255);
56  
57  	private static final Color BLUE = new Color(null, 188, 210, 238);
58  
59  	private Table table;
60  
61  	private Button[] selectButtons;
62  
63  	private List<Integer> selectedColumnIndices;
64  
65  	private int maxSelectedColumnsCount;
66  
67  	/**
68  	 * The mapping of dialog tabular data column indices (always increased by 1 because of the row number column) to the
69  	 * indices of columns of the "entire" tabular data (containing only the columns selected at the
70  	 * <code>AnalyzersSelectionPage</code>).
71  	 */
72  	private Map<Integer, Integer> dialogToDataIndices;
73  
74  	/**
75  	 * The default constructor.
76  	 * 
77  	 * @param selectColumnsCount
78  	 *            the maximal number of columns allowed to be selected
79  	 */
80  	public ButtonTableCreator(int selectColumnsCount) {
81  		selectedColumnIndices = new LinkedList<Integer>();
82  		this.maxSelectedColumnsCount = selectColumnsCount;
83  	}
84  
85  	/**
86  	 * Creates table basing on parsed tabular data.
87  	 * 
88  	 * @param container
89  	 *            the table container
90  	 * @param tableLData
91  	 *            the table layout data
92  	 * @param tabData
93  	 *            the data to be inserted into the table
94  	 * @param indicesMap
95  	 *            the mapping of dialog tabular data column indices to the column indices of the entire tabular data
96  	 */
97  	public void createTable(Composite container, GridData tableLData, TabularData tabData,
98  	        Map<Integer, Integer> indicesMap) {
99  		this.dialogToDataIndices = indicesMap;
100 
101 		if (table != null) {
102 			table.dispose();
103 		}
104 		table = new Table(container, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
105 		table.setHeaderVisible(false);
106 		table.setLinesVisible(true);
107 
108 		if (tableLData != null) {
109 			table.setLayoutData(tableLData);
110 		}
111 
112 		if (tabData == null) {
113 			return;
114 		}
115 
116 		prepareTableColumns(tabData);
117 
118 		TableItem tableItem = new TableItem(table, SWT.NONE);
119 		makeFirstTableRowAsSelectButtons(tabData, tableItem);
120 
121 		int size = Math.min(MAX_ROWS_TO_DISPLAY, tabData.size());
122 		fillTableRows(tabData, tableItem, size);
123 	}
124 
125 	/*
126 	 * -----------------------------------------------------------------------------------------------------------
127 	 * --------------------------HELPER METHODS------------------------------------------------------------
128 	 * -----------------------------------------------------------------------------------------------------------
129 	 */
130 
131 	/**
132 	 * Prepares the table columns.
133 	 */
134 	private void prepareTableColumns(TabularData data) {
135 		// add row number column
136 		TableColumn tableColumn = new TableColumn(table, SWT.NONE);
137 		tableColumn.setWidth(100);
138 		tableColumn.setAlignment(SWT.RIGHT);
139 
140 		for (int columnIndex = 1; columnIndex <= data.getColumnsCount(); columnIndex++) {
141 			tableColumn = new TableColumn(table, SWT.NONE);
142 			tableColumn.pack();
143 			tableColumn.setWidth(100);
144 		}
145 	}
146 
147 	/**
148 	 * Makes columns headers as buttons.
149 	 */
150 	private void makeFirstTableRowAsSelectButtons(TabularData data, TableItem tableItem) {
151 		tableItem.setText(0, Messages.TableViewerHelper_Row);
152 		tableItem.setBackground(0, GRAY);
153 		table.getColumn(0).pack();
154 
155 		selectButtons = new Button[data.getColumnsCount()];
156 
157 		for (int columnIndex = 1; columnIndex <= data.getColumnsCount(); columnIndex++) {
158 			TableEditor editor = new TableEditor(table);
159 			Button selectBtn = new Button(table, SWT.PUSH);
160 			selectButtons[columnIndex - 1] = selectBtn;
161 			selectBtn.pack();
162 
163 			final int columnIndexCp = columnIndex; // final variable for anonymous access
164 			selectBtn.addSelectionListener(new SelectionAdapter() {
165 				@Override
166 				public void widgetSelected(SelectionEvent event) {
167 					handleSelectButtonPressed(columnIndexCp);
168 				}
169 			});
170 			editor.grabHorizontal = true;
171 
172 			selectBtn.setText(Messages.ButtonTableCreator_Select);
173 			editor.minimumWidth = selectBtn.getSize().x;
174 			editor.minimumHeight = selectBtn.getSize().y;
175 			editor.horizontalAlignment = SWT.FILL;
176 			editor.verticalAlignment = SWT.FILL;
177 			editor.grabVertical = true;
178 			editor.grabHorizontal = true;
179 			editor.setEditor(selectBtn, tableItem, columnIndex);
180 		}
181 	}
182 
183 	/**
184 	 * Fills table rows to the pointed size.
185 	 */
186 	private void fillTableRows(TabularData data, TableItem tableItem, int size) {
187 		for (int rowIndex = 0; rowIndex < size; rowIndex++) {
188 			final TableItem tabItem = new TableItem(table, SWT.NONE);
189 
190 			tabItem.setText(0, String.valueOf(rowIndex + 1));
191 			tabItem.setBackground(0, GRAY);
192 
193 			for (int columnIndex = 1; columnIndex <= data.getColumnsCount(); columnIndex++) {
194 				Object valueToSet = null;
195 				DataRow row = data.getRowByIndex(rowIndex);
196 				String format = data.getFormatters().get(columnIndex - 1);
197 				if (columnIndex <= row.size()) {
198 					valueToSet = row.get(columnIndex - 1);
199 				}
200 				if (valueToSet == null) {
201 					valueToSet = ""; //$NON-NLS-1$
202 				}
203 				if (format != null && valueToSet instanceof Date) {
204 					SimpleDateFormat sdf = new SimpleDateFormat(format);
205 					tabItem.setText(columnIndex, sdf.format((Date)valueToSet));
206 				} else {
207 					tabItem.setText(columnIndex, valueToSet.toString());
208 				}
209 			}
210 		}
211 	}
212 
213 	/*----------------------------------------------------------------------------------------------------------*/
214 
215 	/*
216 	 * -----------------------------------------------------------------------------------------------------------
217 	 * --------------------------ACTION METHODS------------------------------------------------------------
218 	 * -----------------------------------------------------------------------------------------------------------
219 	 */
220 
221 	private void handleSelectButtonPressed(int columnIndex) {
222 		if (selectedColumnIndices.contains(columnIndex)) {
223 			for (int rowIndex = 1; rowIndex < table.getItemCount(); rowIndex++) {
224 				TableItem tableItem = table.getItem(rowIndex);
225 				tableItem.setBackground(columnIndex, WHITE);
226 			}
227 			selectedColumnIndices.remove(new Integer(columnIndex));
228 			selectButtons[columnIndex - 1].setText(Messages.ButtonTableCreator_Select);
229 			return;
230 		}
231 
232 		Integer colIdxToDeselect = null;
233 		if (selectedColumnIndices != null && !selectedColumnIndices.isEmpty()
234 		        && selectedColumnIndices.size() >= maxSelectedColumnsCount) {
235 			colIdxToDeselect = selectedColumnIndices.get(0);
236 		}
237 
238 		for (int rowIndex = 1; rowIndex < table.getItemCount(); rowIndex++) {
239 			TableItem tableItem = table.getItem(rowIndex);
240 			tableItem.setBackground(columnIndex, BLUE);
241 
242 			// deselect first selected column if no more column selection is allowed
243 			if (colIdxToDeselect != null) {
244 				tableItem.setBackground(colIdxToDeselect, WHITE);
245 			}
246 		}
247 
248 		selectedColumnIndices.add(columnIndex);
249 		selectButtons[columnIndex - 1].setText(Messages.ButtonTableCreator_Deselect);
250 
251 		if (colIdxToDeselect != null) {
252 			selectedColumnIndices.remove(new Integer(colIdxToDeselect));
253 			selectButtons[colIdxToDeselect - 1].setText(Messages.ButtonTableCreator_Select);
254 		}
255 	}
256 
257 	/**
258 	 * Method called by the mediating conversion rules configuration dialog in order to set the previously chosen table
259 	 * columns selection.
260 	 * 
261 	 * @param columnIndices
262 	 *            the indices of the columns that are to be selected
263 	 */
264 	public void selectTableColumns(List<Integer> columnIndices) {
265 		// int dialogColIdx = columnIndices;
266 		List<Integer> dialogColIndices = new LinkedList<Integer>();
267 
268 		if (columnIndices != null && !columnIndices.isEmpty()) {
269 			for (Integer colIdx : columnIndices) {
270 				for (Entry<Integer, Integer> entry : dialogToDataIndices.entrySet()) {
271 					if (entry.getValue() != null && entry.getValue().equals(colIdx - 1)) {
272 						dialogColIndices.add(entry.getKey());
273 					}
274 				}
275 			}
276 		}
277 
278 		for (int rowIndex = 1; rowIndex < table.getItemCount(); rowIndex++) {
279 			for (Integer dialogColIdx : dialogColIndices) {
280 				TableItem tableItem = table.getItem(rowIndex);
281 				tableItem.setBackground(dialogColIdx, BLUE);
282 			}
283 		}
284 
285 		for (Integer dialogColIdx : dialogColIndices) {
286 			selectButtons[dialogColIdx - 1].setText(Messages.ButtonTableCreator_Deselect);
287 			if (!selectedColumnIndices.contains(dialogColIdx)) {
288 				selectedColumnIndices.add(dialogColIdx);
289 			}
290 		}
291 	}
292 
293 	/**
294 	 * Selects a specified column index in table.
295 	 * 
296 	 * @param columnIndex
297 	 *            the column index to select
298 	 */
299 	public void selectTableColumn(int columnIndex) {
300 		List<Integer> colIndices = new LinkedList<Integer>();
301 		colIndices.add(columnIndex);
302 		selectTableColumns(colIndices);
303 	}
304 
305 	/*----------------------------------------------------------------------------------------------------------*/
306 
307 	/*
308 	 * -----------------------------------------------------------------------------------------------------------
309 	 * --------------------------GETTERS AND SETTERS------------------------------------------------------
310 	 * -----------------------------------------------------------------------------------------------------------
311 	 */
312 
313 	/**
314 	 * Retrieves the selected column index of the entire tabular data (basing on the indices mapping).
315 	 * 
316 	 * @return selected column index
317 	 */
318 	public List<Integer> getSelectedColumnIndices() {
319 		if (dialogToDataIndices == null || selectedColumnIndices == null || selectedColumnIndices.isEmpty()) {
320 			// The column index is decreased by 1 for the row column should not be counted
321 			return selectedColumnIndices;
322 		}
323 
324 		// The dialogToDataIndices mapping already considers the row number column
325 		List<Integer> result = new LinkedList<Integer>();
326 		for (Integer colIdx : selectedColumnIndices) {
327 			result.add(dialogToDataIndices.get(colIdx));
328 		}
329 		Collections.sort(result);
330 		return result;
331 	}
332 
333 	/*----------------------------------------------------------------------------------------------------------*/
334 }