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;
20  
21  import sk.baka.ambient.AmbientApplication;
22  import android.view.Gravity;
23  import android.view.View;
24  import android.widget.PopupWindow;
25  import android.widget.TextView;
26  
27  /***
28   * A contained pop-up window. This window is contained in and positioned
29   * relative to owning view. Displays a simple string.
30   * 
31   * @author Martin Vysny
32   */
33  public final class ContainedPopupWindow {
34  	/***
35  	 * Computes window placement.
36  	 * 
37  	 * @author Martin Vysny
38  	 */
39  	public static interface IPlaceable {
40  		/***
41  		 * Computes new coordinates for given pop-up window, based on a text
42  		 * value.
43  		 * 
44  		 * @param popup
45  		 *            the pop-up window instance, never <code>null</code>.
46  		 * @param text
47  		 *            the placement text
48  		 * @param textView
49  		 *            the string is set to this text view.
50  		 * @return [x, y] coordinates relative to owner view.
51  		 */
52  		int[] getCoordinates(final ContainedPopupWindow popup,
53  				final CharSequence text, final TextView textView);
54  	}
55  
56  	private final ViewUtils utils = new ViewUtils();
57  	private final View owner;
58  	/***
59  	 * The pop-up window instance. <code>null</code> if not visible.
60  	 */
61  	private PopupWindow popup;
62  	private final IPlaceable coords;
63  
64  	/***
65  	 * Creates new pop-up window instance.
66  	 * 
67  	 * @param owner
68  	 *            the owner window.
69  	 * @param coords
70  	 *            computes coordinates for the pop-up.
71  	 */
72  	public ContainedPopupWindow(final View owner, final IPlaceable coords) {
73  		this.owner = owner;
74  		this.coords = coords;
75  	}
76  
77  	/***
78  	 * Displays given text on the pop-up window, showing it if necessary.
79  	 * 
80  	 * @param text
81  	 *            the text to display.
82  	 */
83  	public void setText(final CharSequence text) {
84  		AmbientApplication.getHandler().removeCallbacks(hintRemover);
85  		final TextView popupContent = createPopup();
86  		popupContent.setText(text);
87  		updatePos();
88  	}
89  
90  	/***
91  	 * Dismisses the pop-up window.
92  	 */
93  	public void dismiss() {
94  		destroyPopup();
95  	}
96  
97  	/***
98  	 * Dismiss the pop-up window after designated time. Canceled when a new text
99  	 * is set.
100 	 * 
101 	 * @param timeMillis
102 	 *            dismiss after this time period.
103 	 */
104 	public void dismissAfter(final long timeMillis) {
105 		AmbientApplication.getHandler().removeCallbacks(hintRemover);
106 		AmbientApplication.getHandler().postDelayed(hintRemover, timeMillis);
107 	}
108 
109 	private final Runnable hintRemover = new Runnable() {
110 		public void run() {
111 			dismiss();
112 		}
113 	};
114 
115 	private TextView createPopup() {
116 		final TextView textView;
117 		if (popup == null) {
118 			popup = new PopupWindow(owner.getContext());
119 			textView = new TextView(owner.getContext());
120 			popup.setContentView(textView);
121 			popup.showAtLocation(owner, Gravity.NO_GRAVITY, 0, 0);
122 		} else {
123 			textView = (TextView) popup.getContentView();
124 		}
125 		return textView;
126 	}
127 
128 	private void destroyPopup() {
129 		AmbientApplication.getHandler().removeCallbacks(hintRemover);
130 		if (popup != null) {
131 			popup.dismiss();
132 			popup = null;
133 		}
134 	}
135 
136 	/***
137 	 * Updates the position of the window if the window is visible.
138 	 */
139 	public void updatePos() {
140 		if (popup != null) {
141 			final TextView popupContent = (TextView) popup.getContentView();
142 			final int[] coords = this.coords.getCoordinates(this, popupContent
143 					.getText(), popupContent);
144 			utils.translated.y = coords[1];
145 			utils.translated.x = coords[0];
146 			utils.translateCoordinates(null, owner, owner.getRootView());
147 			this.popup.update(utils.translated.x, utils.translated.y,
148 					android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
149 					android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
150 			popupContent.requestLayout();
151 		}
152 	}
153 }