blob: 3ce9439b423ccc8f37c644e5a56bdefabd713f14 [file] [log] [blame]
Adrien Béraud04463092013-05-06 14:17:22 +10001package com.savoirfairelinux.sflphone.model;
alisionfe9cf712013-05-03 17:26:08 -04002
3import android.content.Context;
4import android.graphics.Canvas;
5import android.graphics.Color;
Adrien Béraud04463092013-05-06 14:17:22 +10006import android.os.Handler;
7import android.os.Message;
alisionfe9cf712013-05-03 17:26:08 -04008import android.util.AttributeSet;
9import android.util.Log;
10import android.view.MotionEvent;
Adrien Béraud04463092013-05-06 14:17:22 +100011import android.view.SurfaceHolder;
12import android.view.SurfaceView;
alisionfe9cf712013-05-03 17:26:08 -040013import android.view.View;
Adrien Béraud04463092013-05-06 14:17:22 +100014import android.view.View.OnTouchListener;
alisionfe9cf712013-05-03 17:26:08 -040015
Adrien Béraud04463092013-05-06 14:17:22 +100016public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener
17{
18 private static final String TAG = BubblesView.class.getSimpleName();
alisionfe9cf712013-05-03 17:26:08 -040019
Adrien Béraud04463092013-05-06 14:17:22 +100020 private BubblesThread thread = null;
21 private BubbleModel model;
alisionfe9cf712013-05-03 17:26:08 -040022
Adrien Béraud04463092013-05-06 14:17:22 +100023 public BubblesView(Context context, AttributeSet attrs)
24 {
25 super(context, attrs);
alisionfe9cf712013-05-03 17:26:08 -040026
Adrien Béraud04463092013-05-06 14:17:22 +100027 SurfaceHolder holder = getHolder();
28 holder.addCallback(this);
alisionfe9cf712013-05-03 17:26:08 -040029
Adrien Béraud04463092013-05-06 14:17:22 +100030 // create thread only; it's started in surfaceCreated()
31 createThread();
alisionfe9cf712013-05-03 17:26:08 -040032
Adrien Béraud04463092013-05-06 14:17:22 +100033 setOnTouchListener(this);
34 setFocusable(true);
35 }
alisionfe9cf712013-05-03 17:26:08 -040036
Adrien Béraud04463092013-05-06 14:17:22 +100037 private void createThread() {
38 if(thread != null) return;
39 thread = new BubblesThread(getHolder(), getContext(), new Handler() {
40 @Override
41 public void handleMessage(Message m)
42 {
43 /* mStatusText.setVisibility(m.getData().getInt("viz"));
44 mStatusText.setText(m.getData().getString("text"));*/
45 }
46 });
Adrien Béraud65ba5b12013-05-06 15:42:50 +100047 if(model != null)
48 thread.setModel(model);
Adrien Béraud04463092013-05-06 14:17:22 +100049 }
alisionfe9cf712013-05-03 17:26:08 -040050
Adrien Béraud04463092013-05-06 14:17:22 +100051 public void setModel(BubbleModel model)
52 {
53 this.model = model;
54 thread.setModel(model);
55 }
alisionfe9cf712013-05-03 17:26:08 -040056
Adrien Béraud04463092013-05-06 14:17:22 +100057 /*@Override
58 public void onWindowFocusChanged(boolean hasWindowFocus) {
59 if (!hasWindowFocus) {
60 thread.pause();
61 }
62 }*/
alisionfe9cf712013-05-03 17:26:08 -040063
Adrien Béraud04463092013-05-06 14:17:22 +100064 @Override
65 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
66 {
67 Log.w(TAG, "surfaceChanged");
68 thread.setSurfaceSize(width, height);
69 }
alisionfe9cf712013-05-03 17:26:08 -040070
Adrien Béraud04463092013-05-06 14:17:22 +100071 /*
72 * Callback invoked when the Surface has been created and is ready to be
73 * used.
74 */
75 @Override
76 public void surfaceCreated(SurfaceHolder holder)
77 {
78 // start the thread here so that we don't busy-wait in run()
79 // waiting for the surface to be created
80 createThread();
alisionfe9cf712013-05-03 17:26:08 -040081
Adrien Béraud04463092013-05-06 14:17:22 +100082 Log.w(TAG, "surfaceCreated");
83 thread.setRunning(true);
84 thread.start();
85 }
alisionfe9cf712013-05-03 17:26:08 -040086
Adrien Béraud04463092013-05-06 14:17:22 +100087 /*
88 * Callback invoked when the Surface has been destroyed and must no longer
89 * be touched. WARNING: after this method returns, the Surface/Canvas must
90 * never be touched again!
91 */
92 @Override
93 public void surfaceDestroyed(SurfaceHolder holder)
94 {
95 // we have to tell thread to shut down & wait for it to finish, or else
96 // it might touch the Surface after we return and explode
97 Log.w(TAG, "surfaceDestroyed");
98 boolean retry = true;
99 thread.setRunning(false);
Adrien Béraud25fc4092013-05-06 15:28:39 +1000100 while (retry) {
Adrien Béraud04463092013-05-06 14:17:22 +1000101 try {
102 thread.join();
103 retry = false;
104 } catch (InterruptedException e) {
105 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000106 }
Adrien Béraud04463092013-05-06 14:17:22 +1000107 thread = null;
108 }
alisionfe9cf712013-05-03 17:26:08 -0400109
Adrien Béraud04463092013-05-06 14:17:22 +1000110 @Override
111 public boolean onTouch(View v, MotionEvent event)
112 {
113 Log.w(TAG, "onTouch " + event.getAction());
Adrien Béraud25fc4092013-05-06 15:28:39 +1000114
115 int action = event.getActionMasked();
116
117 if(action == MotionEvent.ACTION_DOWN) {
Adrien Béraud04463092013-05-06 14:17:22 +1000118 for (Bubble b : model.listBubbles) {
Adrien Béraud25fc4092013-05-06 15:28:39 +1000119 if(b.intersects(event.getX(), event.getY())) {
120 b.dragged = true;
121 }
122 }
123 } else if (action == MotionEvent.ACTION_MOVE) {
124 for (Bubble b : model.listBubbles) {
125 if(b.dragged) {
126 b.setPos(event.getX(), event.getY());
Adrien Béraud04463092013-05-06 14:17:22 +1000127 return true;
128 }
129 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000130 } else if(action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
131 for (Bubble b : model.listBubbles) {
132 if(b.dragged) {
133 b.dragged = false;
134 }
135 }
136 }
Adrien Béraud04463092013-05-06 14:17:22 +1000137 return true;
138 }
alisionfe9cf712013-05-03 17:26:08 -0400139
Adrien Béraud04463092013-05-06 14:17:22 +1000140 class BubblesThread extends Thread
141 {
142 private boolean running = false;
143 private SurfaceHolder surfaceHolder;
alisionfe9cf712013-05-03 17:26:08 -0400144
Adrien Béraud04463092013-05-06 14:17:22 +1000145 BubbleModel model = null;
alisionfe9cf712013-05-03 17:26:08 -0400146
Adrien Béraud04463092013-05-06 14:17:22 +1000147 public BubblesThread(SurfaceHolder holder, Context context, Handler handler)
148 {
149 surfaceHolder = holder;
150 }
alisionfe9cf712013-05-03 17:26:08 -0400151
Adrien Béraud04463092013-05-06 14:17:22 +1000152 public void setModel(BubbleModel model)
153 {
154 this.model = model;
155 }
alisionfe9cf712013-05-03 17:26:08 -0400156
Adrien Béraud04463092013-05-06 14:17:22 +1000157 @Override
158 public void run()
159 {
160 while (running) {
161 Canvas c = null;
162 try {
163 c = surfaceHolder.lockCanvas(null);
Adrien Béraud7ed23dc2013-05-06 16:27:24 +1000164
165 // for the case the surface is destroyed while already in the loop
166 if(c == null || model == null) continue;
167
Adrien Béraud04463092013-05-06 14:17:22 +1000168 synchronized (surfaceHolder) {
Adrien Béraud25fc4092013-05-06 15:28:39 +1000169 //Log.w(TAG, "Thread doDraw");
170 model.update();
Adrien Béraud04463092013-05-06 14:17:22 +1000171 doDraw(c);
172 }
173 } finally {
174 // do this in a finally so that if an exception is thrown
175 // during the above, we don't leave the Surface in an
176 // inconsistent state
177 if (c != null)
178 surfaceHolder.unlockCanvasAndPost(c);
179 }
180 }
181 }
182
183 public void setRunning(boolean b)
184 {
185 running = b;
186 }
187
188 public void setSurfaceSize(int width, int height)
189 {
190 synchronized (surfaceHolder) {
Adrien Béraud25fc4092013-05-06 15:28:39 +1000191 if(model != null) {
192 model.width = width;
193 model.height = height;
194 }
Adrien Béraud04463092013-05-06 14:17:22 +1000195
196 // don't forget to resize the background image
197 // mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, width, height, true);
198 }
199 }
200
Adrien Béraud04463092013-05-06 14:17:22 +1000201 private void doDraw(Canvas canvas)
202 {
203 canvas.drawColor(Color.WHITE);
204
Adrien Béraud25fc4092013-05-06 15:28:39 +1000205 for(int i=0, n=model.listBubbles.size(); i<n; i++) {
206 Bubble b = model.listBubbles.get(i);
207 canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);
208 }
Adrien Béraud04463092013-05-06 14:17:22 +1000209 }
210 }
211
alisionfe9cf712013-05-03 17:26:08 -0400212}