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 }