View Javadoc

1   /***
2    *     Ambient - A music player for the Android platform
3    Copyright (C) 2007 Martin Vysny
4    
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9    
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14  
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package sk.baka.ambient.views.gesturelist;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import sk.baka.ambient.commons.Interval;
25  import android.view.View;
26  
27  /***
28   * <p>
29   * Manages the model for the {@link GesturesListView}.
30   * </p>
31   * <p>
32   * Handles special End Of Playlist item - this item allows us to insert tracks
33   * at the end of the playlist (and into an empty playlist) using keypad
34   * gestures. The special item is shown only when the list view:
35   * </p>
36   * <ul>
37   * <li>is modifiable</li>
38   * <li>has focus (this property however does not alter the return value of the
39   * function, i.e. the function can return <code>true</code> even if the list
40   * view does not have focus)</li>
41   * <li>is not in the {@link View#isInTouchMode() touch mode}</li>
42   * <li>the clipboard is not empty</li>
43   * </ul>
44   * 
45   * @author Martin Vysny
46   */
47  public final class ModelHolder {
48  	/***
49  	 * The owner.
50  	 */
51  	private final GesturesListView owner;
52  
53  	/***
54  	 * Creates new instance.
55  	 * 
56  	 * @param owner
57  	 *            owner listview.
58  	 */
59  	ModelHolder(final GesturesListView owner) {
60  		super();
61  		this.owner = owner;
62  		// We need to remember this adapter -
63  		// we cannot get it simply from the ListView for it will scroll to
64  		// the first item (WTF?).
65  		adapter = new MutableListAdapter(owner, this);
66  	}
67  
68  	/***
69  	 * The backing array of item data. In the MVC terminology, this is a model
70  	 * for all items. This list will never contain the EOP object - this object
71  	 * is factored by the {@link MutableListAdapter}.
72  	 */
73  	private final List<Object> model = new ArrayList<Object>();
74  
75  	/***
76  	 * The backing adapter.
77  	 */
78  	final MutableListAdapter adapter;
79  
80  	/***
81  	 * <p>
82  	 * Returns a list of items. The backing array of item data. In the MVC
83  	 * terminology, this is a model for all items. If you plan to modify this
84  	 * list, do not forget to call {@link #notifyModified()} after all
85  	 * modifications are made.
86  	 * </p>
87  	 * <p>
88  	 * This model must never contain the
89  	 * {@link MutableListAdapter#EOP_MODEL_MARKER} object!
90  	 * </p>
91  	 * 
92  	 * @return a live list of item data.
93  	 */
94  	public List<Object> getModel() {
95  		return model;
96  	}
97  
98  	/***
99  	 * Redraws items and reflects changes made to the {@link #getModel()} list.
100 	 */
101 	public void notifyModified() {
102 		adapter.notifyModified();
103 	}
104 
105 	/***
106 	 * These items are highlighted.
107 	 */
108 	private Interval highlight = Interval.EMPTY;
109 
110 	/***
111 	 * Highlight given items. Does not update the view - you need to call
112 	 * {@link #notifyModified()} to force the redraw.
113 	 * 
114 	 * @param highlight
115 	 *            items to highlight
116 	 */
117 	public void highlight(final Interval highlight) {
118 		Interval newHighlight = highlight;
119 		if (newHighlight.end >= model.size()) {
120 			newHighlight = new Interval(newHighlight.start, model.size());
121 		}
122 		if (newHighlight.equals(this.highlight))
123 			return;
124 		this.highlight = newHighlight;
125 		owner.listener.highlightChanged(this.highlight);
126 	}
127 
128 	/***
129 	 * Returns current highlight.
130 	 * 
131 	 * @return current highlight, never <code>null</code>.
132 	 */
133 	public Interval getHighlight() {
134 		return highlight;
135 	}
136 
137 	/***
138 	 * Returns current highlight. If no items are highlighted, optionally return
139 	 * current selection.
140 	 * 
141 	 * @param returnSelectionOnEmptyHighlight
142 	 *            if <code>true</code> and no items are currently being
143 	 *            highlighted, return current selection.
144 	 * 
145 	 * @return current highlight, never <code>null</code>.
146 	 */
147 	public Interval getHighlight(final boolean returnSelectionOnEmptyHighlight) {
148 		if (highlight.isEmpty() && returnSelectionOnEmptyHighlight) {
149 			final int sel = owner.getSelectedItemPosition();
150 			return (sel < 0) || (sel >= model.size()) ? Interval.EMPTY
151 					: Interval.fromItem(sel);
152 		}
153 		return getHighlight();
154 	}
155 
156 	/***
157 	 * Returns current highlight. If no items are highlighted, optionally return
158 	 * given item.
159 	 * 
160 	 * @param returnSelectionOnEmptyHighlight
161 	 *            if not negative and no items are currently being highlighted,
162 	 *            return selection consisting of a single item.
163 	 * 
164 	 * @return current highlight, never <code>null</code>.
165 	 */
166 	public Interval getHighlight(final int returnSelectionOnEmptyHighlight) {
167 		if (highlight.isEmpty() && (returnSelectionOnEmptyHighlight >= 0)
168 				&& (returnSelectionOnEmptyHighlight < model.size())) {
169 			return Interval.fromItem(returnSelectionOnEmptyHighlight);
170 		}
171 		return getHighlight();
172 	}
173 
174 	/***
175 	 * Returns interval containing all items.
176 	 * 
177 	 * @return non-<code>null</code> interval.
178 	 */
179 	public Interval getAllItems() {
180 		return new Interval(0, model.size());
181 	}
182 }