/* ********************************************************************** ** ** Copyright notice ** ** ** ** (c) 2005-2009 RSSOwl Development Team ** ** http://www.rssowl.org/ ** ** ** ** All rights reserved ** ** ** ** This program and the accompanying materials are made available under ** ** the terms of the Eclipse Public License v1.0 which accompanies this ** ** distribution, and is available at: ** ** http://www.rssowl.org/legal/epl-v10.html ** ** ** ** A copy is found in the file epl-v10.html and important notices to the ** ** license from the team is found in the textfile LICENSE.txt distributed ** ** in this package. ** ** ** ** This copyright notice MUST APPEAR in all copies of the file! ** ** ** ** Contributors: ** ** RSSOwl Development Team - initial API and implementation ** ** ** ** ********************************************************************** */ package org.rssowl.ui.internal.editors.feed; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.rssowl.core.Owl; import org.rssowl.core.internal.persist.pref.DefaultPreferences; import org.rssowl.core.persist.pref.IPreferenceScope; import org.rssowl.ui.internal.Application; import org.rssowl.ui.internal.OwlUI; import org.rssowl.ui.internal.util.CColumnLayoutData; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * The view model behind the columns of the feed view used in * {@link NewsTableControl}. * * @author bpasero */ public class NewsColumnViewModel { /** ID to associate a Column with its ID */ public static final String COL_ID = "org.rssowl.ui.internal.editors.feed.ColumnIdentifier"; //$NON-NLS-1$ private final List<NewsColumn> fColumns = new ArrayList<NewsColumn>(); private NewsColumn fSortColumn; private boolean fAscending; private NewsColumnViewModel() {} /** * Copy constructor for the model. * * @param copyFrom the model to copy from. */ public NewsColumnViewModel(NewsColumnViewModel copyFrom) { fColumns.addAll(copyFrom.getColumns()); fSortColumn = copyFrom.getSortColumn(); fAscending = copyFrom.isAscending(); } /** * @return a default {@link NewsColumnViewModel} initialized from the global * scope of preferences. */ public static NewsColumnViewModel createGlobal() { return loadFrom(Owl.getPreferenceService().getGlobalScope()); } /** * @param isSearch set to <code>true</code> if column model is for search * results, <code>false</code> otherwise. * @return a default {@link NewsColumnViewModel} initialized from the default * scope of preferences. */ public static NewsColumnViewModel createDefault(boolean isSearch) { return loadFrom(Owl.getPreferenceService().getDefaultScope(), isSearch); } /** * @param preferences the preferences to load the news column model from. * @return the {@link NewsColumnViewModel} from the provided preferences. */ public static NewsColumnViewModel loadFrom(IPreferenceScope preferences) { return loadFrom(preferences, false); } /** * @param preferences the preferences to load the news column model from. * @param isSearch set to <code>true</code> if column model is for search * results, <code>false</code> otherwise. * @return the {@link NewsColumnViewModel} from the provided preferences. */ public static NewsColumnViewModel loadFrom(IPreferenceScope preferences, boolean isSearch) { int[] columns = preferences.getIntegers(isSearch ? DefaultPreferences.SEARCH_DIALOG_NEWS_COLUMNS : DefaultPreferences.BM_NEWS_COLUMNS); int sortColumn = preferences.getInteger(isSearch ? DefaultPreferences.SEARCH_DIALOG_NEWS_SORT_COLUMN : DefaultPreferences.BM_NEWS_SORT_COLUMN); boolean ascending = preferences.getBoolean(isSearch ? DefaultPreferences.SEARCH_DIALOG_NEWS_SORT_ASCENDING : DefaultPreferences.BM_NEWS_SORT_ASCENDING); return createFrom(columns, sortColumn, ascending); } /** * @param columns the selected columns. * @param sortColumn the sorted column. * @param ascending the sort order. * @return the {@link NewsColumnViewModel} from the provided settings. */ public static NewsColumnViewModel createFrom(int[] columns, int sortColumn, boolean ascending) { NewsColumn[] newsColumns = NewsColumn.values(); NewsColumnViewModel model = new NewsColumnViewModel(); /* News Columns */ for (int column : columns) { model.addColumn(newsColumns[column]); } /* Sort Column */ model.setSortColumn(newsColumns[sortColumn]); /* Sort Order */ model.setAscending(ascending); return model; } /** * @param tree the tree to initialize the model from. * @return the {@link NewsColumnViewModel} from the provided tree. */ public static NewsColumnViewModel initializeFrom(Tree tree) { NewsColumnViewModel model = new NewsColumnViewModel(); TreeColumn[] columns = tree.getColumns(); int[] columnOrder = tree.getColumnOrder(); for (int order : columnOrder) { Object data = columns[order].getData(COL_ID); if (data != null) model.addColumn((NewsColumn) data); } return model; } /** * @param table the table to initialize the model from. * @return the {@link NewsColumnViewModel} from the provided table. */ public static NewsColumnViewModel initializeFrom(Table table) { NewsColumnViewModel model = new NewsColumnViewModel(); TableColumn[] columns = table.getColumns(); int[] columnOrder = table.getColumnOrder(); for (int order : columnOrder) { Object data = columns[order].getData(COL_ID); if (data != null) model.addColumn((NewsColumn) data); } return model; } /** * @return the visible columns. */ public List<NewsColumn> getColumns() { return fColumns; } /** * @param column the column to add to the model. */ public void addColumn(NewsColumn column) { if (!fColumns.contains(column)) fColumns.add(column); } /** * @param column the column to remove from the model. */ public void removeColumn(NewsColumn column) { fColumns.remove(column); } /** * @param index the index of the column to return. * @return the {@link NewsColumn} at the given index. */ public NewsColumn getColumn(int index) { return fColumns.get(index); } /** * @param column the column to check if included in this model. * @return <code>true</code> if the column is part of this model and * <code>false</code> otherwise. */ public boolean contains(NewsColumn column) { return fColumns.contains(column); } /** * @return the sorted column. */ public NewsColumn getSortColumn() { return fSortColumn; } /** * @param column the sorted column. */ public void setSortColumn(NewsColumn column) { fSortColumn = column; } /** * @return <code>true</code> if sorting is ascending or <code>false</code> * otherwise. */ public boolean isAscending() { return fAscending; } /** * @param ascending <code>true</code> if sorting is ascending or * <code>false</code> otherwise. */ public void setAscending(boolean ascending) { fAscending = ascending; } /** * @param column the column to get the layout information for. * @return an instance of {@link CColumnLayoutData} describing the layout of * the column. */ public CColumnLayoutData getLayoutData(NewsColumn column) { boolean useLargeColumns = Application.IS_LINUX || Application.IS_MAC; switch (column) { case TITLE: return new CColumnLayoutData(CColumnLayoutData.Size.FILL, 60); case AUTHOR: return new CColumnLayoutData(CColumnLayoutData.Size.FILL, 15); case CATEGORY: return new CColumnLayoutData(CColumnLayoutData.Size.FILL, 15); case LABELS: return new CColumnLayoutData(CColumnLayoutData.Size.FILL, 10); case DATE: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, OwlUI.getDateWidth()); case PUBLISHED: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, OwlUI.getDateWidth()); case MODIFIED: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, OwlUI.getDateWidth()); case RECEIVED: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, OwlUI.getDateWidth()); case ATTACHMENTS: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, useLargeColumns ? 20 : 18); case FEED: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, useLargeColumns ? 20 : 18); case RELEVANCE: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, 24); case STICKY: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, useLargeColumns ? 20 : 18); case STATUS: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, OwlUI.getStateWidth()); case LOCATION: return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, 150); case LINK: return new CColumnLayoutData(CColumnLayoutData.Size.FILL, 25); default: //Never Reached return new CColumnLayoutData(CColumnLayoutData.Size.FIXED, 100); } } /** * @param preferences the preferences to save the news column model into. * @return <code>true</code> in case the settings have changed and * <code>false</code> otherwise. */ public boolean saveTo(IPreferenceScope preferences) { return saveTo(preferences, false); } /** * @param preferences the preferences to save the news column model into. * @param isSearch set to <code>true</code> if column model is for search * results, <code>false</code> otherwise. * @return <code>true</code> in case the settings have changed and * <code>false</code> otherwise. */ public boolean saveTo(IPreferenceScope preferences, boolean isSearch) { return saveTo(preferences, isSearch, true, true, true); } /** * @param preferences the preferences to save the news column model into. * @param isSearch set to <code>true</code> if column model is for search * results, <code>false</code> otherwise. * @param saveColumns if <code>true</code>, saves the columns of the model * @param saveSortColumn if <code>true</code>, saves the sort column of the * model * @param saveSortDirection if <code>true</code>, saves the sort direction of * the model * @return <code>true</code> in case the settings have changed and * <code>false</code> otherwise. */ public boolean saveTo(IPreferenceScope preferences, boolean isSearch, boolean saveColumns, boolean saveSortColumn, boolean saveSortDirection) { boolean changed = true; /* News Columns */ int[] columns = new int[fColumns.size()]; for (int i = 0; i < fColumns.size(); i++) columns[i] = fColumns.get(i).ordinal(); /* Check for Changes */ int[] prefColumns = preferences.getIntegers(isSearch ? DefaultPreferences.SEARCH_DIALOG_NEWS_COLUMNS : DefaultPreferences.BM_NEWS_COLUMNS); int prefSortColumn = preferences.getInteger(isSearch ? DefaultPreferences.SEARCH_DIALOG_NEWS_SORT_COLUMN : DefaultPreferences.BM_NEWS_SORT_COLUMN); boolean prefAscending = preferences.getBoolean(isSearch ? DefaultPreferences.SEARCH_DIALOG_NEWS_SORT_ASCENDING : DefaultPreferences.BM_NEWS_SORT_ASCENDING); changed = !Arrays.equals(prefColumns, columns) || prefSortColumn != fSortColumn.ordinal() || prefAscending != fAscending; /* Save Columns */ if (saveColumns) preferences.putIntegers(isSearch ? DefaultPreferences.SEARCH_DIALOG_NEWS_COLUMNS : DefaultPreferences.BM_NEWS_COLUMNS, columns); /* Save Sorting Column */ if (saveSortColumn) preferences.putInteger(isSearch ? DefaultPreferences.SEARCH_DIALOG_NEWS_SORT_COLUMN : DefaultPreferences.BM_NEWS_SORT_COLUMN, fSortColumn.ordinal()); /* Save Sorting Direction */ if (saveSortDirection) preferences.putBoolean(isSearch ? DefaultPreferences.SEARCH_DIALOG_NEWS_SORT_ASCENDING : DefaultPreferences.BM_NEWS_SORT_ASCENDING, fAscending); return changed; } /* * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (fAscending ? 1231 : 1237); result = prime * result + ((fColumns == null) ? 0 : fColumns.hashCode()); result = prime * result + ((fSortColumn == null) ? 0 : fSortColumn.hashCode()); return result; } /* * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; NewsColumnViewModel other = (NewsColumnViewModel) obj; if (fAscending != other.fAscending) return false; if (fSortColumn == null) { if (other.fSortColumn != null) return false; } else if (!fSortColumn.equals(other.fSortColumn)) return false; if (fColumns == null) { if (other.fColumns != null) return false; } else if (!fColumns.equals(other.fColumns)) return false; return true; } }