package rocks.inspectit.ui.rcp.handlers; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.expressions.IEvaluationContext; import org.eclipse.swt.widgets.Item; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TreeColumn; import rocks.inspectit.ui.rcp.preferences.PreferencesConstants; import rocks.inspectit.ui.rcp.preferences.PreferencesUtils; /** * This class is a handler for show/hide of columns, but also a cache for saving the state of the * columns. * * @author Ivan Senic * */ public class ShowHideColumnsHandler extends AbstractHandler { /** * Command ID. */ public static final String COMMAND_ID = "rocks.inspectit.ui.rcp.commands.showHideColumn"; /** * Column parameter. */ public static final String COLUMN_PARAM = "rocks.inspectit.ui.rcp.commands.showHideColumn.Column"; /** * Visible parameter. */ public static final String VISIBLE_PARAM = "rocks.inspectit.ui.rcp.commands.showHideColumn.Visible"; /** * Controller class parameter. */ public static final String CONTROLLER_CLASS_PARAM = "rocks.inspectit.ui.rcp.commands.showHideColumn.ControllerClass"; /** * Map for saving columns size. */ private static Map<Integer, Integer> columnSizeCache; /** * Set for saving columns visibility. All columns that are in this cache are not visible. */ private static Set<Integer> hiddenColumnsCache; /** * Column order map. */ private static Map<Integer, int[]> columnOrderCache; static { startUp(); } /** * {@inheritDoc} */ @Override public Object execute(ExecutionEvent event) throws ExecutionException { // Get the input definition out of the context IEvaluationContext context = (IEvaluationContext) event.getApplicationContext(); Item column = (Item) context.getVariable(COLUMN_PARAM); Boolean visible = (Boolean) context.getVariable(VISIBLE_PARAM); Class<?> inputControllerClass = (Class<?>) context.getVariable(CONTROLLER_CLASS_PARAM); showHideColumn(column, column.getText(), visible.booleanValue(), inputControllerClass); return null; } /** * Shows or hides the {@link TreeColumn} or {@link TableColumn}. * * @param column * Column. * @param columnName * name of the column. * @param showColumn * Should column be shown or not. * @param controllerClass * Controller class. */ private void showHideColumn(Item column, String columnName, boolean showColumn, Class<?> controllerClass) { int columnHash = getColumnHash(controllerClass, columnName); if (showColumn) { // update cache data Integer width = columnSizeCache.get(columnHash); hiddenColumnsCache.remove(columnHash); // change appearance if (width != null) { setColumnWidth(column, width.intValue()); } else { setColumnWidth(column, 100); } setColumnResizable(column, true); } else { // update cache data int width = getColumnWidth(column); hiddenColumnsCache.add(columnHash); columnSizeCache.put(columnHash, width); // change appearance setColumnWidth(column, 0); setColumnResizable(column, false); } } /** * Sets the with of {@link TreeColumn} or {@link TableColumn}. * * @param column * Column * @param width * Width */ private void setColumnWidth(Item column, int width) { if (column instanceof TableColumn) { ((TableColumn) column).setWidth(width); } else if (column instanceof TreeColumn) { ((TreeColumn) column).setWidth(width); } } /** * Gets the width of {@link TreeColumn} or {@link TableColumn}. * * @param column * Column. * @return Width of column, or -1 if provided {@link Item} object is not of type * {@link TreeColumn} or {@link TableColumn}. */ private int getColumnWidth(Item column) { if (column instanceof TableColumn) { return ((TableColumn) column).getWidth(); } else if (column instanceof TreeColumn) { return ((TreeColumn) column).getWidth(); } return -1; } /** * Sets the {@link TreeColumn} or {@link TableColumn} resizable. * * @param column * Column * @param resizable * Resizable or not */ private void setColumnResizable(Item column, boolean resizable) { if (column instanceof TableColumn) { ((TableColumn) column).setResizable(resizable); } else if (column instanceof TreeColumn) { ((TreeColumn) column).setResizable(resizable); } } /** * Returns if the cache has any knowledge of the column's width. * * @param controllerClass * {@link rocks.inspectit.ui.rcp.editor.table.input.TableInputController} class where * this column is defined. * @param columnName * Column name. * @return Size of columns width or <code>null</code> if it is unknown. */ public static Integer getRememberedColumnWidth(Class<?> controllerClass, String columnName) { int hash = getColumnHash(controllerClass, columnName); return columnSizeCache.get(hash); } /** * Returns if the cache has any knowledge if the column is hidden. * * @param controllerClass * {@link rocks.inspectit.ui.rcp.editor.table.input.TableInputController} class where * this column is defined. * @param columnName * Column name. * @return True if column should be hidden. */ public static boolean isColumnHidden(Class<?> controllerClass, String columnName) { return hiddenColumnsCache.contains(getColumnHash(controllerClass, columnName)); } /** * Saves the column order for the controller class. * * @param controllerClass * Controller class. * @param order * Array that describes the order of the columns. */ public static void setColumnOrder(Class<?> controllerClass, int[] order) { Integer key = Integer.valueOf(controllerClass.getName().hashCode()); columnOrderCache.remove(key); columnOrderCache.put(key, order); } /** * Gets the column order for the controller class. * * @param controllerClass * Controller class. * @return Array that describes the order of the columns or null if the order was never saved * for the controller class. */ public static int[] getColumnOrder(Class<?> controllerClass) { Integer key = Integer.valueOf(controllerClass.getName().hashCode()); return columnOrderCache.get(key); } /** * Registers new column width to be saved for further use. Only positive column widths will be * saved. * * @param controllerClass * {@link rocks.inspectit.ui.rcp.editor.table.input.TableInputController} class where * this column is defined. * @param columnName * Column name. * @param width * New width */ public static void registerNewColumnWidth(Class<?> controllerClass, String columnName, int width) { // only register positive values, thus keep track of the column size if (width > 0) { int hash = getColumnHash(controllerClass, columnName); columnSizeCache.put(hash, width); } } /** * Creates hash code for column by its name and the * {@link rocks.inspectit.ui.rcp.editor.table.input.TableInputController} class it is located. * * @param controllerClass * {@link rocks.inspectit.ui.rcp.editor.table.input.TableInputController} class where * this column is defined. * @param columnName * Column name. * @return Hash code for caching. */ private static int getColumnHash(Class<?> controllerClass, String columnName) { final int prime = 31; int result = 0; result = (prime * result) + ((controllerClass.getName() == null) ? 0 : controllerClass.getName().hashCode()); result = (prime * result) + ((columnName == null) ? 0 : columnName.hashCode()); return result; } /** * Loads preferences for columns size/visibility. */ private static synchronized void startUp() { columnSizeCache = new HashMap<>(); PreferencesUtils.loadPrimitiveMap(PreferencesConstants.TABLE_COLUMN_SIZE_CACHE, columnSizeCache, Integer.class, Integer.class); hiddenColumnsCache = new HashSet<>(); PreferencesUtils.loadPrimitiveCollection(PreferencesConstants.HIDDEN_TABLE_COLUMN_CACHE, hiddenColumnsCache, Integer.class); columnOrderCache = PreferencesUtils.getObject(PreferencesConstants.TABLE_COLUMN_ORDER_CACHE); if (null == columnOrderCache) { columnOrderCache = new HashMap<>(); } // shut down hook to save the data when closing UI Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { saveChanges(); } }); } /** * Saves the preferences about columns size/visibility. */ private static void saveChanges() { PreferencesUtils.saveObject(PreferencesConstants.TABLE_COLUMN_SIZE_CACHE, columnSizeCache, false); PreferencesUtils.saveObject(PreferencesConstants.HIDDEN_TABLE_COLUMN_CACHE, hiddenColumnsCache, false); PreferencesUtils.saveObject(PreferencesConstants.TABLE_COLUMN_ORDER_CACHE, columnOrderCache, false); } }