3 * This file is part of shape_android.
5 * shape_android 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.
10 * shape_android 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.
15 * You should have received a copy of the GNU General Public License
16 * along with shape_android. If not, see <http://www.gnu.org/licenses/>.
19 package org.ocera.orte.shape_android;
21 import java.util.regex.Pattern;
23 import org.ocera.orte.DomainApp;
24 import org.ocera.orte.Manager;
25 import org.ocera.orte.types.NtpTime;
27 import android.annotation.SuppressLint;
28 import android.app.Activity;
29 import android.app.AlertDialog;
30 import android.content.Context;
31 import android.content.DialogInterface;
32 import android.content.Intent;
33 import android.content.SharedPreferences;
34 import android.content.res.Configuration;
35 import android.net.wifi.WifiManager;
36 import android.net.wifi.WifiManager.WifiLock;
37 import android.os.Bundle;
38 import android.os.Handler;
39 import android.preference.PreferenceManager;
40 import android.view.Menu;
41 import android.view.MenuItem;
42 import android.widget.LinearLayout;
43 import android.widget.SeekBar;
44 import android.widget.ViewSwitcher;
47 * Class for object sent and received throw the ORTE middleware.
49 * @author jiri hubacek <jiri.hubacek@gmail.com>
53 public class PublisherActivity extends Activity {
54 //public final static Pattern IP_ADDRESS = Pattern.compile("((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))");
56 private static final int REDRAW_INTERVAL = 50;
57 private static final int STRENGTH_MAX = 5;
58 private static final int MINSEPARATION_MAX = 5;
59 private static final int RESULT_SETTINGS = 1;
61 private WifiManager wifiManager;
62 private WifiLock wifiLock;
64 private Manager orteManager;
65 private DomainApp appDomain;
67 private PublisherView publisherView;
68 private SubscriberView subscriberView;
70 private ViewSwitcher switcher;
71 private boolean actualIsPublisher;
72 private SharedPreferences sp;
74 private Handler handler = new Handler();
75 private Runnable redraw = new Runnable()
80 publisherView.countShapes();
81 publisherView.invalidate();
82 handler.postDelayed(this, REDRAW_INTERVAL);
87 * Setting up main workspace.
92 protected void onCreate(Bundle savedInstanceState) {
93 super.onCreate(savedInstanceState);
94 setContentView(R.layout.activity_publisher);
96 // From Robot_Demo project.
97 wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
98 wifiLock = (WifiLock) wifiManager.createWifiLock((
99 (android.os.Build.VERSION.SDK_INT >= 12)
100 ? WifiManager.WIFI_MODE_FULL_HIGH_PERF
101 : WifiManager.WIFI_MODE_FULL
102 ), getClass().getName());
104 sp = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
107 orteManager = new Manager(sp.getString("prefManagers", ""));
108 appDomain = new DomainApp();
110 this.switcher = (ViewSwitcher) findViewById(R.id.switcher);
111 this.actualIsPublisher = true;
113 this.publisherView = (PublisherView) findViewById(R.id.publisher_view);
114 this.subscriberView = (SubscriberView) findViewById(R.id.subscriber_view);
117 this.subscriberView.addElements(this.appDomain);
118 for (SubscriberElement e : this.subscriberView.elements) {
119 e.setScale(this.getWindowManager().getDefaultDisplay().getWidth(), this.getWindowManager().getDefaultDisplay().getHeight());
120 e.setAllowScaling(sp.getBoolean("prefScaling", true));
125 * When pause activity, release WiFi lock.
130 public void onPause()
138 * When resume activity, acquire WiFi lock.
143 public void onResume()
151 * When switching application off.
156 public void onDestroy()
160 if (appDomain != null) {
164 if (orteManager != null) {
165 orteManager.destroy();
171 * When screen orientation is changed,
172 * scale recalculation is needed.
177 public void onConfigurationChanged(Configuration newConfig)
179 super.onConfigurationChanged(newConfig);
181 for (PublisherShape s : this.publisherView.shapes) {
182 s.setScale(this.getWindowManager().getDefaultDisplay().getWidth(), this.getWindowManager().getDefaultDisplay().getHeight());
184 for (SubscriberElement e : this.subscriberView.elements) {
185 e.setScale(this.getWindowManager().getDefaultDisplay().getWidth(), this.getWindowManager().getDefaultDisplay().getHeight());
188 //TODO When change rotation in Subscriber view,
189 // there is no change in Publisher view, which
190 // leads to misbehavior. For example, there
191 // is Publisher of Black color in Publisher view,
192 // and we are looking at it in Subscriber view,
193 // when rotation is changed, Publisher view remains
194 // in old rotation while Subscriber view is in new
195 // rotation. Therefore Black Publisher thinks that
196 // it's still in old rotation and the problem with
197 // leaving screen is here.
201 * When returning from SettingsActivity, apply settings.
206 protected void onActivityResult(int requestCode, int resultCode, Intent data)
208 super.onActivityResult(requestCode, resultCode, data);
210 switch(requestCode) {
211 case RESULT_SETTINGS:
212 boolean allowScaling = sp.getBoolean("prefScaling", true);
214 for (PublisherShape s : this.publisherView.shapes) {
215 s.box.allowScaling = allowScaling;
217 for (SubscriberElement e : this.subscriberView.elements) {
218 e.setAllowScaling(allowScaling);
221 if (orteManager != null) orteManager.destroy();
222 orteManager = new Manager(sp.getString("prefManagers", ""));
235 public boolean onCreateOptionsMenu(Menu menu) {
236 // Inflate the menu; this adds items to the action bar if it is present.
237 getMenuInflater().inflate(R.menu.publisher, menu);
242 * All created publishers are in menu.
248 public boolean onPrepareOptionsMenu(Menu menu)
252 if (this.actualIsPublisher) {
253 getMenuInflater().inflate(R.menu.publisher, menu);
254 for (PublisherShape shape : this.publisherView.shapes) {
255 menu.add(0, this.publisherView.shapes.indexOf(shape), 20 + this.publisherView.shapes.indexOf(shape), "#" + this.publisherView.shapes.indexOf(shape) + " " + shape.getColorName() + " " + shape.getShapeName());
258 getMenuInflater().inflate(R.menu.subscriber, menu);
261 return super.onPrepareOptionsMenu(menu);
265 * Logic for menu selecting.
267 * Contains switching between Publishers and Subscribers, adding
268 * new Publisher, setting Publishers, setting Subscribers, moving
269 * to SettingsActivity and HelpActivity.
273 @SuppressLint("NewApi")
275 public boolean onOptionsItemSelected(MenuItem item) {
276 // Handle action bar item clicks here. The action bar will
277 // automatically handle clicks on the Home/Up button, so long
278 // as you specify a parent activity in AndroidManifest.xml.
279 final int id = item.getItemId();
280 final Activity me = this;
284 case R.id.action_switch:
285 if (this.actualIsPublisher) {
286 this.switcher.showNext();
287 this.setTitle(R.string.title_activity_subscriber);
289 this.switcher.showPrevious();
290 this.setTitle(R.string.title_activity_publisher);
292 this.actualIsPublisher = !this.actualIsPublisher;
294 if (android.os.Build.VERSION.SDK_INT >= 11) this.invalidateOptionsMenu();
297 case R.id.action_new:
298 String[] colors = new String[5];
304 colors[4] = "Yellow";
306 AlertDialog.Builder builderNew = new AlertDialog.Builder(me);
307 builderNew.setTitle(R.string.dialog_newPublisher)
308 .setItems(colors, new DialogInterface.OnClickListener()
311 public void onClick(DialogInterface dialog, int which)
315 publisherView.addShape(which, appDomain);
317 for (PublisherShape s : publisherView.shapes) {
318 s.setScale(me.getWindowManager().getDefaultDisplay().getWidth(), me.getWindowManager().getDefaultDisplay().getHeight());
319 s.box.allowScaling = sp.getBoolean("prefScaling", true);
322 if (android.os.Build.VERSION.SDK_INT >= 11) me.invalidateOptionsMenu();
325 .setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener()
328 public void onClick(DialogInterface dialog, int which)
333 AlertDialog dialogNew = builderNew.create();
337 case R.id.action_settings:
338 intent = new Intent(this, SettingsActivity.class);
339 startActivityForResult(intent, RESULT_SETTINGS);
341 case R.id.action_help:
342 intent = new Intent(this, HelpActivity.class);
343 startActivity(intent);
346 // For settings of Publisher/Subscriber elements.
347 LinearLayout l = new LinearLayout(me);
348 l.setOrientation(LinearLayout.VERTICAL);
349 AlertDialog.Builder builderSettings = new AlertDialog.Builder(me);
351 if (this.actualIsPublisher) {
353 * Parameters of Publisher shapes.
355 final int shapeStrength = publisherView.shapes.get(id).getStrength();
356 SeekBar seekStrength;
359 seekStrength = new SeekBar(me);
360 seekStrength.setMax(STRENGTH_MAX);
361 seekStrength.setProgress(shapeStrength);
363 seekStrength.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
366 public void onStopTrackingTouch(SeekBar seekBar) {
370 public void onStartTrackingTouch(SeekBar seekBar) {
374 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
376 publisherView.shapes.get(id).setStrength(progress);
380 l.addView(seekStrength);
383 builderSettings.setTitle("#" + id + " " + publisherView.shapes.get(id).getColorName() + " " + publisherView.shapes.get(id).getShapeName() + " strength:")
385 .setPositiveButton(R.string.dialog_OK, new DialogInterface.OnClickListener()
388 public void onClick(DialogInterface dialog, int which)
391 .setNeutralButton(R.string.dialog_delete, new DialogInterface.OnClickListener()
394 public void onClick(DialogInterface dialog, int which) {
395 publisherView.shapes.get(id).killMe();
396 publisherView.shapes.remove(id);
398 if (android.os.Build.VERSION.SDK_INT >= 11) me.invalidateOptionsMenu();
401 .setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener()
404 public void onClick(DialogInterface dialog, int which)
406 publisherView.shapes.get(id).setStrength(shapeStrength);
410 AlertDialog dialogSettings = builderSettings.create();
411 dialogSettings.show();
414 * Parameters of Subscriber shapes.
417 SeekBar seekMinSeparation;
420 case R.id.action_blue:
423 case R.id.action_green:
426 case R.id.action_red:
429 case R.id.action_black:
432 case R.id.action_yellow:
440 seekMinSeparation = new SeekBar(me);
441 seekMinSeparation.setMax(MINSEPARATION_MAX);
442 seekMinSeparation.setProgress(0);
443 subscriberView.elements.get(eId).setMinSeparation(new NtpTime(0));
445 seekMinSeparation.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
448 public void onStopTrackingTouch(SeekBar seekBar) {
452 public void onStartTrackingTouch(SeekBar seekBar) {
456 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
458 subscriberView.elements.get(eId).setMinSeparation(new NtpTime(progress));
459 subscriberView.elements.get(eId).setEnabled(true);
463 l.addView(seekMinSeparation);
466 builderSettings.setTitle(PublisherShape.getColorName(eId) + " settings")
468 .setPositiveButton(R.string.dialog_OK, new DialogInterface.OnClickListener()
471 public void onClick(DialogInterface dialog, int which)
474 .setNeutralButton(subscriberView.elements.get(eId).getEnabled()?R.string.dialog_delete:R.string.dialog_add, new DialogInterface.OnClickListener()
477 public void onClick(DialogInterface dialog, int which) {
478 if (subscriberView.elements.get(eId).getEnabled()) {
479 subscriberView.elements.get(eId).setEnabled(false);
481 subscriberView.elements.get(eId).setMinSeparation(new NtpTime(0));
482 subscriberView.elements.get(eId).setEnabled(true);
487 AlertDialog dialogSettings = builderSettings.create();
488 dialogSettings.show();
492 return super.onOptionsItemSelected(item);