reworked a whole bunch of stuff
moved from assistant to one single activity model with dialogs and navigation drawer as main content holder completed separate threaded queue based service to communicate with daemon(s) added first few elements to the nav drawer
@@ -15,13 +15,13 @@ apply plugin: 'com.jakewharton.hugo'
|
||||
apply plugin: 'com.github.ben-manes.versions'
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
buildToolsVersion "22.0.1"
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion '23.0.0'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.idlegandalf.ledd"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
@@ -34,12 +34,14 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:22.2.1'
|
||||
compile 'com.android.support:support-v4:22.2.1'
|
||||
compile 'com.squareup.okhttp:okhttp:2.4.0'
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
compile 'com.android.support:appcompat-v7:23.0.0'
|
||||
compile 'com.android.support:support-v4:23.0.0'
|
||||
compile 'com.squareup.okhttp:okhttp:2.5.0'
|
||||
compile 'com.google.code.gson:gson:2.3.1'
|
||||
compile 'com.jakewharton:butterknife:7.0.1'
|
||||
compile 'com.koushikdutta.async:androidasync:2.1.6'
|
||||
compile 'com.android.support:design:22.2.1'
|
||||
provided "org.projectlombok:lombok:1.16.4"
|
||||
compile 'com.android.support:design:23.0.0'
|
||||
compile 'com.rarepebble:colorpicker:1.3.0'
|
||||
provided 'org.projectlombok:lombok:1.16.6'
|
||||
}
|
||||
|
@@ -1,13 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.idlegandalf.ledd">
|
||||
<manifest
|
||||
package="com.idlegandalf.ledd"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
|
||||
<application
|
||||
android:name="com.idlegandalf.ledd.ColorApplication"
|
||||
android:name=".ColorApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
@@ -23,7 +24,7 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.idlegandalf.ledd.SettingsActivity"
|
||||
android:name=".SettingsActivity"
|
||||
android:label=""
|
||||
android:parentActivityName="com.idlegandalf.ledd.ColorActivity">
|
||||
|
||||
@@ -33,11 +34,7 @@
|
||||
android:value="com.idlegandalf.ledd.ColorActivity" />
|
||||
</activity>
|
||||
|
||||
<service android:name="com.idlegandalf.ledd.ColorService" />
|
||||
|
||||
<activity
|
||||
android:name="com.idlegandalf.ledd.AssistantActivity"
|
||||
android:label="" />
|
||||
<service android:name=".services.ColorService"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
@@ -1,73 +0,0 @@
|
||||
package com.idlegandalf.ledd;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.idlegandalf.ledd.fragments.WelcomeFragment;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class AssistantActivity extends AppCompatActivity {
|
||||
|
||||
@Bind(R.id.fragmentContainer)
|
||||
FrameLayout container;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_asistent);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
// Check that the activity is using the layout version with
|
||||
// the fragment_container FrameLayout
|
||||
if (container != null) {
|
||||
|
||||
// However, if we're being restored from a previous state,
|
||||
// then we don't need to do anything and should return or else
|
||||
// we could end up with overlapping fragments.
|
||||
if (savedInstanceState != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new Fragment to be placed in the activity layout
|
||||
WelcomeFragment welcomeFragment = new WelcomeFragment();
|
||||
|
||||
// In case this activity was started with special instructions from an
|
||||
// Intent, pass the Intent's extras to the fragment as arguments
|
||||
welcomeFragment.setArguments(getIntent().getExtras());
|
||||
|
||||
// Add the fragment to the 'fragment_container' FrameLayout
|
||||
getFragmentManager().beginTransaction()
|
||||
.add(R.id.fragmentContainer, welcomeFragment).commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.welcome, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void switchFragment(Fragment fragment) {
|
||||
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
|
||||
|
||||
fragmentTransaction.replace(R.id.fragmentContainer, fragment);
|
||||
fragmentTransaction.addToBackStack(null);
|
||||
|
||||
fragmentTransaction.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (getFragmentManager().getBackStackEntryCount() > 0) {
|
||||
getFragmentManager().popBackStack();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,37 +1,36 @@
|
||||
package com.idlegandalf.ledd;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import com.idlegandalf.ledd.components.LEDDHelper;
|
||||
import com.idlegandalf.ledd.components.RGBStripe;
|
||||
import com.idlegandalf.ledd.components.StripeGroup;
|
||||
import com.idlegandalf.ledd.utils.ColorPicker;
|
||||
import com.idlegandalf.ledd.helper.LedDHelper;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import hugo.weaving.DebugLog;
|
||||
|
||||
public class ColorActivity extends AppCompatActivity {
|
||||
|
||||
@Bind(R.id.colorPicker)
|
||||
ColorPicker mWheel;
|
||||
@Bind(R.id.drawer_layout)
|
||||
DrawerLayout mDrawerLayout;
|
||||
@Bind(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
private ActionBarDrawerToggle mDrawerToggle;
|
||||
private LEDDHelper mAPI;
|
||||
private LedDHelper mAPI;
|
||||
private RGBStripe mActiveStripe;
|
||||
private StripeGroup mActiveGroup;
|
||||
private boolean firstRun = false;
|
||||
@@ -49,6 +48,9 @@ public class ColorActivity extends AppCompatActivity {
|
||||
// TODO: Display error
|
||||
}
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
toolbar.setTitle("LedD");
|
||||
|
||||
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.app_name, R.string.app_name) {
|
||||
|
||||
/** Called when a drawer has settled in a completely closed state. */
|
||||
@@ -66,24 +68,9 @@ public class ColorActivity extends AppCompatActivity {
|
||||
mDrawerLayout.setDrawerListener(mDrawerToggle);
|
||||
|
||||
// enable Homebutton navigation to drawer
|
||||
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
//getSupportActionBar().setHomeButtonEnabled(true);
|
||||
// getSupportActionBar().setIcon(R.drawable.ic_bar);
|
||||
|
||||
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(
|
||||
"firstRun", true)) {
|
||||
System.out.println("first run!");
|
||||
firstRun = true;
|
||||
Intent intent = new Intent(this, AssistantActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
if (ColorApplication.getInstance().isAPIActive()) {
|
||||
this.mAPI = ColorApplication.getInstance().getAPI();
|
||||
System.out.println("API active!");
|
||||
} else {
|
||||
System.out.println("API not active :(");
|
||||
this.finish();
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,12 +103,6 @@ public class ColorActivity extends AppCompatActivity {
|
||||
}
|
||||
// Handle your other action bar items...
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_settings:
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@@ -140,8 +121,17 @@ public class ColorActivity extends AppCompatActivity {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@DebugLog
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
ColorApplication.getInstance().teardown();
|
||||
}
|
||||
|
||||
@DebugLog
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
ColorApplication.getInstance().teardown();
|
||||
}
|
||||
}
|
||||
|
@@ -3,14 +3,20 @@ package com.idlegandalf.ledd;
|
||||
import android.app.Application;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.idlegandalf.ledd.components.LEDDHelper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.idlegandalf.ledd.components.Host;
|
||||
import com.idlegandalf.ledd.helper.LedDHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
import hugo.weaving.DebugLog;
|
||||
|
||||
public class ColorApplication extends Application {
|
||||
private static ColorApplication singleton;
|
||||
private LEDDHelper mAPI = null;
|
||||
private boolean mAPIActive = false;
|
||||
private HashMap<Host, LedDHelper> ledDHelpers;
|
||||
|
||||
public static ColorApplication getInstance() {
|
||||
return singleton;
|
||||
@@ -20,36 +26,43 @@ public class ColorApplication extends Application {
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
singleton = this;
|
||||
|
||||
ledDHelpers = new HashMap<>();
|
||||
|
||||
if (PreferenceManager.getDefaultSharedPreferences(this).contains("hosts")) {
|
||||
Set<Host> hosts = new Gson().fromJson(PreferenceManager.getDefaultSharedPreferences(this).getString("hosts", ""), new
|
||||
TypeToken<Set<Host>>() {
|
||||
}.getType());
|
||||
|
||||
for (Host host : hosts) {
|
||||
try {
|
||||
initAPI();
|
||||
ledDHelpers.put(host, new LedDHelper(host, getApplicationContext()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public LEDDHelper getAPI() {
|
||||
return this.mAPI;
|
||||
}
|
||||
|
||||
public void initAPI() throws IOException {
|
||||
if (PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.contains("pref_key_host")) {
|
||||
System.out.println("len of hashmap: " + ledDHelpers.size());
|
||||
}
|
||||
|
||||
mAPI = new LEDDHelper(PreferenceManager
|
||||
.getDefaultSharedPreferences(this).getString(
|
||||
"pref_key_host", ""),
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(this).getInt(
|
||||
"pref_key_port", 8825),
|
||||
getApplicationContext()
|
||||
);
|
||||
|
||||
this.mAPIActive = true;
|
||||
System.out.println("api is declared as active now");
|
||||
public LedDHelper getHelperForHost(Host host) throws IOException {
|
||||
System.out.println("host: " + host.toString());
|
||||
if (ledDHelpers.containsKey(host)) {
|
||||
return ledDHelpers.get(host);
|
||||
} else {
|
||||
LedDHelper dHelper = new LedDHelper(host, getApplicationContext());
|
||||
ledDHelpers.put(host, dHelper);
|
||||
return dHelper;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAPIActive() {
|
||||
return mAPIActive;
|
||||
@DebugLog
|
||||
public void teardown() {
|
||||
for (LedDHelper dHelper : ledDHelpers.values()) {
|
||||
dHelper.teardown();
|
||||
}
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("hosts", new Gson().toJson(ledDHelpers.keySet())).commit();
|
||||
}
|
||||
}
|
||||
|
@@ -1,99 +0,0 @@
|
||||
package com.idlegandalf.ledd;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
|
||||
public class ColorService extends Service {
|
||||
private Looper mServiceLooper;
|
||||
private ServiceHandler mServiceHandler;
|
||||
private DatagramSocket socket;
|
||||
|
||||
// Handler that receives messages from the thread
|
||||
private final class ServiceHandler extends Handler {
|
||||
public ServiceHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
Bundle msgdata = msg.getData();
|
||||
|
||||
if (msgdata != null) {
|
||||
try {
|
||||
byte[] data = msgdata.getString("json").getBytes();
|
||||
DatagramPacket packet = new DatagramPacket(data, data.length,
|
||||
InetAddress.getByName(msgdata.getString("ip")), msgdata.getInt("port"));
|
||||
socket.send(packet);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the service using the startId, so that we don't stop
|
||||
// the service in the middle of handling another job
|
||||
//stopSelf(msg.arg1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
Toast.makeText(this, "ColorService started", Toast.LENGTH_SHORT).show();
|
||||
|
||||
try {
|
||||
socket = new DatagramSocket();
|
||||
} catch (SocketException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Start up the thread running the service. Note that we create a
|
||||
// separate thread because the service normally runs in the process's
|
||||
// main thread, which we don't want to block. We also make it
|
||||
// background priority so CPU-intensive work will not disrupt our UI.
|
||||
HandlerThread thread = new HandlerThread("ServiceStartArguments",
|
||||
Process.THREAD_PRIORITY_BACKGROUND);
|
||||
thread.start();
|
||||
|
||||
// Get the HandlerThread's Looper and use it for our Handler
|
||||
mServiceLooper = thread.getLooper();
|
||||
mServiceHandler = new ServiceHandler(mServiceLooper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
// For each start request, send a message to start a job and deliver the
|
||||
// start ID so we know which request we're stopping when we finish the
|
||||
// job
|
||||
Message msg = mServiceHandler.obtainMessage();
|
||||
msg.arg1 = startId;
|
||||
msg.setData(intent.getExtras());
|
||||
mServiceHandler.sendMessage(msg);
|
||||
|
||||
// If we get killed, after returning from here, restart
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
// We don't provide binding, so return null
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
socket.close();
|
||||
Toast.makeText(this, "ColorService stopped", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
@@ -5,12 +5,26 @@ import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class DrawerFragment extends Fragment {
|
||||
@Bind(R.id.lay_add_host)
|
||||
LinearLayout addHost;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.drawer_fragment, container, false);
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.drawer_fragment, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@OnClick(R.id.lay_add_host)
|
||||
public void addHost() {
|
||||
// TODO: add dialog with selection and input things
|
||||
}
|
||||
}
|
||||
|
@@ -1,32 +0,0 @@
|
||||
package com.idlegandalf.ledd;
|
||||
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
public abstract class ProgressBarActionBarActivity extends AppCompatActivity {
|
||||
private ProgressBar mProgressBar;
|
||||
|
||||
public void setContentView(View view) {
|
||||
init().addView(view);
|
||||
}
|
||||
|
||||
public void setContentView(int layoutResID) {
|
||||
getLayoutInflater().inflate(layoutResID, init(), true);
|
||||
}
|
||||
|
||||
public void setContentView(View view, ViewGroup.LayoutParams params) {
|
||||
init().addView(view, params);
|
||||
}
|
||||
|
||||
private ViewGroup init() {
|
||||
super.setContentView(R.layout.progress);
|
||||
mProgressBar = (ProgressBar) findViewById(R.id.activity_bar);
|
||||
return (ViewGroup) findViewById(R.id.activity_frame);
|
||||
}
|
||||
|
||||
protected ProgressBar getProgressBar() {
|
||||
return mProgressBar;
|
||||
}
|
||||
}
|
@@ -8,10 +8,11 @@ public class SettingsActivity extends ActionBarActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
// Display the fragment as the main content.
|
||||
getFragmentManager().beginTransaction()
|
||||
.replace(android.R.id.content, new SettingsFragment())
|
||||
.commit();
|
||||
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,13 @@
|
||||
package com.idlegandalf.ledd.callbacks;
|
||||
|
||||
public interface AddControllerCallback {
|
||||
/**
|
||||
* Returns when a controller was added successfully
|
||||
*
|
||||
* @param cid the new controller's id
|
||||
*/
|
||||
void onControllerAdded(int cid);
|
||||
|
||||
void onAddFailed(String msg, String detail);
|
||||
}
|
||||
|
@@ -0,0 +1,9 @@
|
||||
package com.idlegandalf.ledd.callbacks;
|
||||
|
||||
import com.idlegandalf.ledd.components.HSV;
|
||||
|
||||
public interface RecieveColorCallback {
|
||||
void onColorRecieved(HSV color);
|
||||
|
||||
void onRecievFailed(String msg);
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
package com.idlegandalf.ledd.components;
|
||||
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public abstract class AnswerTask implements Runnable {
|
||||
|
||||
public JSONObject response;
|
||||
}
|
||||
|
@@ -9,5 +9,8 @@ import lombok.Setter;
|
||||
@Getter
|
||||
@Setter
|
||||
public class Controller {
|
||||
private int channels;
|
||||
private String address;
|
||||
private int i2c_device;
|
||||
private ArrayList<RGBStripe> stripes;
|
||||
}
|
||||
|
@@ -6,7 +6,17 @@ import lombok.Setter;
|
||||
@Getter
|
||||
@Setter
|
||||
public class HSV {
|
||||
private float hue;
|
||||
private float saturation;
|
||||
private float value;
|
||||
private double hue;
|
||||
private double saturation;
|
||||
private double value;
|
||||
|
||||
public HSV(double h, double s, double v) {
|
||||
this.hue = h;
|
||||
this.saturation = s;
|
||||
this.value = v;
|
||||
}
|
||||
|
||||
public HSV() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -24,4 +24,22 @@ public class Host {
|
||||
public String toString() {
|
||||
return address + ":" + port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Host) {
|
||||
if (address.equals(((Host) o).address) && port == ((Host) o).port) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 23;
|
||||
|
||||
result = 45 * result + port;
|
||||
result = 45 * result + address.hashCode();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@@ -1,68 +0,0 @@
|
||||
package com.idlegandalf.ledd.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.idlegandalf.ledd.ColorService;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
public class LEDDHelper {
|
||||
private String mAddr;
|
||||
private int mPort;
|
||||
private Context context;
|
||||
|
||||
final String ACTION_SETCOLOR = "set_color";
|
||||
final String ACTION_GETCOLOR = "get_color";
|
||||
|
||||
public LEDDHelper(String ip, int port, Context appl) throws UnsupportedEncodingException,
|
||||
IOException {
|
||||
this.mAddr = ip;
|
||||
this.mPort = port;
|
||||
this.context = appl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send RGB values to dameon using the stripeid
|
||||
* @param sid Stripeid
|
||||
* @param color Color in HSV format
|
||||
* @throws JSONException not valid json
|
||||
* @throws IOException socket error
|
||||
*/
|
||||
public void sendColor(int sid, HSV color)
|
||||
throws JSONException, IOException {
|
||||
JSONObject jnson = new JSONObject();
|
||||
JSONArray hsv = new JSONArray();
|
||||
|
||||
hsv.put(color.getHue());
|
||||
hsv.put(color.getSaturation());
|
||||
hsv.put(color.getValue());
|
||||
|
||||
jnson.put("action", ACTION_SETCOLOR);
|
||||
jnson.put("sid", sid);
|
||||
jnson.put("color", hsv);
|
||||
|
||||
sendJSON(jnson.toString());
|
||||
}
|
||||
|
||||
private void sendJSON(String json) throws IOException {
|
||||
Intent intent = new Intent(context, ColorService.class);
|
||||
Bundle bndl = new Bundle();
|
||||
bndl.putString("json", json);
|
||||
bndl.putString("host", this.mAddr);
|
||||
bndl.putInt("port", mPort);
|
||||
intent.putExtras(bndl);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
Intent intent = new Intent(context, ColorService.class);
|
||||
context.stopService(intent);
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package com.idlegandalf.ledd.components;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class Sendable {
|
||||
private Host recipient;
|
||||
private JSONObject message;
|
||||
private String ref;
|
||||
private AnswerTask onAnswer;
|
||||
|
||||
public Sendable(JSONObject msg, AnswerTask task, Host host) throws JSONException {
|
||||
this(msg, UUID.randomUUID().toString(), task, host);
|
||||
}
|
||||
|
||||
public Sendable(JSONObject msg, String ref, AnswerTask task, Host recipient) throws JSONException {
|
||||
this.message = msg;
|
||||
this.ref = ref;
|
||||
this.message.put("ref", ref);
|
||||
this.onAnswer = task;
|
||||
this.recipient = recipient;
|
||||
}
|
||||
|
||||
public void onResponse(JSONObject object) {
|
||||
if (onAnswer != null) {
|
||||
onAnswer.response = object;
|
||||
onAnswer.run();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,8 @@
|
||||
package com.idlegandalf.ledd.components;
|
||||
|
||||
|
||||
import com.idlegandalf.ledd.helper.LedDHelper;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -40,7 +42,7 @@ public class StripeGroup {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setRGB(int r, int g, int b, LEDDHelper api) throws JSONException, IOException {
|
||||
public void setRGB(int r, int g, int b, LedDHelper api) throws JSONException, IOException {
|
||||
for (int i = 0; i < mStripes.size(); i++) {
|
||||
//mStripes.get(i).setRGB(r, g, b, api);
|
||||
}
|
||||
|
@@ -1,233 +0,0 @@
|
||||
package com.idlegandalf.ledd.fragments;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.idlegandalf.ledd.R;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class StepOneFragment extends Fragment {
|
||||
@Bind(R.id.step2_back)
|
||||
Button mBack;
|
||||
@Bind(R.id.ipSelect)
|
||||
EditText mAutoIP;
|
||||
@Bind(R.id.step2_next)
|
||||
Button mTest;
|
||||
@Bind(R.id.portSelect)
|
||||
EditText mAutoPort;
|
||||
ArrayList<String> mIPList = new ArrayList<>();
|
||||
boolean isAutoDetected = false;
|
||||
|
||||
|
||||
public static StepOneFragment newInstance(String addrs) {
|
||||
Bundle args = new Bundle();
|
||||
|
||||
args.putString("ips", addrs);
|
||||
|
||||
StepOneFragment fragment = new StepOneFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_step1, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
String ips = getArguments().getString("ips");
|
||||
|
||||
if (ips != null) {
|
||||
if (!ips.isEmpty()) {
|
||||
for (String string : ips.split(";")) {
|
||||
if (string.isEmpty()) {
|
||||
System.out.println("added addr " + string);
|
||||
mIPList.add(string);
|
||||
}
|
||||
}
|
||||
if (mIPList.size() > 0) isAutoDetected = true;
|
||||
}
|
||||
}
|
||||
|
||||
mBack.setOnClickListener(nextClickListener);
|
||||
mTest.setOnClickListener(nextClickListener);
|
||||
}
|
||||
|
||||
private OnClickListener nextClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.step2_back:
|
||||
getActivity().onBackPressed();
|
||||
break;
|
||||
case R.id.step2_next:
|
||||
System.out.println("forward calling!");
|
||||
testController();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void testController() {
|
||||
ConnectivityManager connManager = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||
|
||||
if (mWifi.isConnected()) {
|
||||
setInputState(false);
|
||||
if (!isValidAddrInput(mAutoIP, mAutoPort)) {
|
||||
setInputState(true);
|
||||
return;
|
||||
}
|
||||
getActivity().setProgressBarIndeterminateVisibility(true);
|
||||
getActivity().setProgressBarVisibility(true);
|
||||
new pokeController().execute(mAutoIP.toString(), mAutoPort.toString());
|
||||
} else {
|
||||
Toast.makeText(getActivity().getApplicationContext(), "please connect WiFi", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private class pokeController extends AsyncTask<String, Void, Boolean> {
|
||||
protected Boolean doInBackground(String... ippo) {
|
||||
try {
|
||||
InetAddress controller = InetAddress.getByName(ippo[0]);
|
||||
int port = Integer.parseInt(ippo[1]);
|
||||
|
||||
DatagramSocket socket = new DatagramSocket();
|
||||
String hstr = new JSONObject().put("action", 5).toString();
|
||||
|
||||
DatagramPacket hello = new DatagramPacket(hstr.getBytes(), hstr.getBytes().length);
|
||||
|
||||
hello.setPort(port);
|
||||
socket.setSoTimeout(100);
|
||||
|
||||
if (!controller.isReachable(50)) {
|
||||
socket.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
hello.setAddress(controller);
|
||||
socket.send(hello);
|
||||
|
||||
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
|
||||
try {
|
||||
socket.receive(packet);
|
||||
} catch (SocketTimeoutException e) {
|
||||
socket.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
Toast.makeText(getActivity().getApplicationContext(), new String(packet.getData(), 0, packet.getLength()), Toast.LENGTH_LONG).show();
|
||||
|
||||
JSONObject resjson = new JSONObject(new String(packet.getData(), 0, packet.getLength()));
|
||||
|
||||
if (resjson.getInt("action") != 5) {
|
||||
socket.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
socket.close();
|
||||
} catch (SocketException e1) {
|
||||
return false;
|
||||
} catch (IOException e1) {
|
||||
return false;
|
||||
} catch (JSONException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void onProgressUpdate(Void... progress) {
|
||||
|
||||
}
|
||||
|
||||
protected void onPostExecute(Boolean result) {
|
||||
getActivity().setProgressBarIndeterminateVisibility(false);
|
||||
getActivity().setProgressBarVisibility(false);
|
||||
setInputState(true);
|
||||
if (result) {
|
||||
Snackbar.make(getActivity().findViewById(R.id.linlayp), "found daemon running on " +
|
||||
"address " + mAutoIP.toString() + ":" + mAutoPort.toString(), Snackbar.LENGTH_LONG).show();
|
||||
} else {
|
||||
Snackbar.make(getActivity().findViewById(R.id.linlayp), "No running daemon " + "found", Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidIPFromEditText(EditText atv) {
|
||||
String exip[] = atv.toString().trim().split("\\.");
|
||||
if (exip.length != 4) return false;
|
||||
|
||||
for (String string : exip) {
|
||||
if (!string.isEmpty()) {
|
||||
try {
|
||||
if (Integer.parseInt(string) < 0 || Integer.parseInt(string) > 255) return false;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidPortFromEditText(EditText atv) {
|
||||
return !atv.toString().isEmpty() && Integer.parseInt(atv.toString()) > 1023 && Integer.parseInt(atv.toString()) <= 65535;
|
||||
}
|
||||
|
||||
private boolean isValidAddrInput(EditText ipatv, EditText portatv) {
|
||||
if (!isValidIPFromEditText(ipatv)) {
|
||||
Snackbar.make(getActivity().findViewById(R.id.linlayp), "Please enter valid IP " + "address", Snackbar.LENGTH_LONG).show();
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!isValidPortFromEditText(portatv)) {
|
||||
Snackbar.make(getActivity().findViewById(R.id.linlayp), "Please enter valid port " + "(1024-65535)", Snackbar.LENGTH_LONG).show();
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setInputState(boolean state) {
|
||||
mAutoIP.setEnabled(state);
|
||||
mAutoPort.setEnabled(state);
|
||||
mBack.setEnabled(state);
|
||||
mTest.setEnabled(state);
|
||||
}
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
package com.idlegandalf.ledd.fragments;
|
||||
|
||||
import android.app.Fragment;
|
||||
|
||||
public class StepStripesFragment extends Fragment {
|
||||
|
||||
}
|
@@ -1,218 +0,0 @@
|
||||
package com.idlegandalf.ledd.fragments;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.net.nsd.NsdManager;
|
||||
import android.net.nsd.NsdServiceInfo;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.idlegandalf.ledd.AssistantActivity;
|
||||
import com.idlegandalf.ledd.R;
|
||||
import com.idlegandalf.ledd.components.Host;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class WelcomeFragment extends Fragment {
|
||||
|
||||
@Bind(R.id.step1_auto)
|
||||
Button mAuto;
|
||||
@Bind(R.id.step1_manual)
|
||||
Button mManual;
|
||||
@Bind(R.id.host_container)
|
||||
LinearLayout hostContainer;
|
||||
@Bind(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
|
||||
NsdManager mNsdManager;
|
||||
final String TAG = "ColorD";
|
||||
NsdManager.DiscoveryListener mDiscoveryListener;
|
||||
NsdManager.ResolveListener mResolveListener;
|
||||
ArrayList<Host> hosts;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_welcome, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
mAuto.setOnClickListener(nextClickListener);
|
||||
mManual.setOnClickListener(nextClickListener);
|
||||
|
||||
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
|
||||
|
||||
hosts = new ArrayList<>();
|
||||
|
||||
mResolveListener = new NsdManager.ResolveListener() {
|
||||
|
||||
@Override
|
||||
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
|
||||
// Called when the resolve fails. Use the error code to debug.
|
||||
Log.e(TAG, "Resolve failed" + errorCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceResolved(final NsdServiceInfo serviceInfo) {
|
||||
Log.e(TAG, "Resolve Succeeded. " + serviceInfo);
|
||||
|
||||
if (serviceInfo.getHost() instanceof Inet4Address) {
|
||||
Log.d(TAG, "Found IPv4! Yay!");
|
||||
|
||||
final Host fHost = new Host(serviceInfo.getHost().getHostAddress(), serviceInfo.getPort());
|
||||
|
||||
if (!hosts.contains(fHost)) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
View v = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout
|
||||
.host_row, hostContainer, false);
|
||||
|
||||
TextView host = (TextView) v.findViewById(R.id.welcome_host);
|
||||
|
||||
host.setText(serviceInfo.getHost().getHostAddress() + ":" + serviceInfo.getPort());
|
||||
host.setTag(serviceInfo);
|
||||
|
||||
View.OnClickListener listener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
StepOneFragment stepOneFragment = StepOneFragment.newInstance(hosts.get((int) v.getTag()).toString());
|
||||
((AssistantActivity) getActivity()).switchFragment(stepOneFragment);
|
||||
}
|
||||
};
|
||||
|
||||
v.setOnClickListener(listener);
|
||||
host.setOnClickListener(listener);
|
||||
|
||||
v.setTag(hosts.size());
|
||||
host.setTag(hosts.size());
|
||||
|
||||
hostContainer.addView(v);
|
||||
hosts.add(fHost);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mDiscoveryListener = new NsdManager.DiscoveryListener() {
|
||||
|
||||
// Called as soon as service discovery begins.
|
||||
@Override
|
||||
public void onDiscoveryStarted(String regType) {
|
||||
Log.d(TAG, "Service discovery started");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceFound(NsdServiceInfo service) {
|
||||
// A service was found! Do something with it.
|
||||
Log.d(TAG, "Service discovery success " + service);
|
||||
if (!service.getServiceType().equals("_ledd._tcp.")) {
|
||||
// Service type is the string containing the protocol and
|
||||
// transport layer for this service.
|
||||
Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
|
||||
} else {
|
||||
mNsdManager.resolveService(service, mResolveListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceLost(NsdServiceInfo service) {
|
||||
// When the network service is no longer available.
|
||||
// Internal bookkeeping code goes here.
|
||||
Log.e(TAG, "service lost" + service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDiscoveryStopped(String serviceType) {
|
||||
Log.i(TAG, "Discovery stopped: " + serviceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
|
||||
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
|
||||
mNsdManager.stopServiceDiscovery(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
|
||||
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
|
||||
mNsdManager.stopServiceDiscovery(this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View.OnClickListener nextClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.step1_auto:
|
||||
System.out.println("auto pressed");
|
||||
//getProgressBar().setIndeterminate(true);
|
||||
//setProgressBarIndeterminateVisibility(true);
|
||||
//setProgressBarVisibility(true);
|
||||
//setProgressBarIndeterminate(true);
|
||||
setButtonState(false);
|
||||
|
||||
mNsdManager = (NsdManager) getActivity().getSystemService(Context.NSD_SERVICE);
|
||||
mNsdManager.discoverServices("_ledd._tcp", NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
|
||||
|
||||
break;
|
||||
case R.id.step1_manual:
|
||||
System.out.println("manual pressed");
|
||||
setButtonState(false);
|
||||
StepOneFragment stepOneFragment = StepOneFragment.newInstance(null);
|
||||
((AssistantActivity) getActivity()).switchFragment(stepOneFragment);
|
||||
setButtonState(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void setButtonState(boolean state) {
|
||||
mAuto.setEnabled(state);
|
||||
mManual.setEnabled(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mNsdManager != null) {
|
||||
tearDown();
|
||||
setButtonState(true);
|
||||
}
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (mNsdManager != null) tearDown();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
// NsdHelper's tearDown method
|
||||
public void tearDown() {
|
||||
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
|
||||
}
|
||||
}
|
155
app/src/main/java/com/idlegandalf/ledd/helper/LedDHelper.java
Normal file
@@ -0,0 +1,155 @@
|
||||
package com.idlegandalf.ledd.helper;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
|
||||
import com.idlegandalf.ledd.callbacks.AddControllerCallback;
|
||||
import com.idlegandalf.ledd.callbacks.RecieveColorCallback;
|
||||
import com.idlegandalf.ledd.components.AnswerTask;
|
||||
import com.idlegandalf.ledd.components.HSV;
|
||||
import com.idlegandalf.ledd.components.Host;
|
||||
import com.idlegandalf.ledd.services.ColorService;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import hugo.weaving.DebugLog;
|
||||
|
||||
public class LedDHelper {
|
||||
final String ACTION_SETCOLOR = "set_color";
|
||||
final String ACTION_GETCOLOR = "get_color";
|
||||
final String ACTION_ADDCONTROLLER = "add_controller";
|
||||
final String ACTION_GETCONTROLLER = "get_controller";
|
||||
final String ACTION_ADDSTRIPES = "add_stripes";
|
||||
private Host host;
|
||||
private Context context;
|
||||
private ColorService.ColorBinder binderService;
|
||||
private boolean mBound = false;
|
||||
ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
System.out.println("service bound!");
|
||||
binderService = (ColorService.ColorBinder) service;
|
||||
mBound = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName arg0) {
|
||||
mBound = false;
|
||||
}
|
||||
};
|
||||
|
||||
public LedDHelper(Host host, Context appl) throws IOException {
|
||||
this.host = host;
|
||||
this.context = appl;
|
||||
|
||||
Intent intent = new Intent(appl, ColorService.class);
|
||||
appl.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add controller to ledd daemon
|
||||
*
|
||||
* @param channels channel amount that this controller holds
|
||||
* @param i2c_dev number of i2c device, e.g. /dev/i2c-1 would be 1
|
||||
* @throws JSONException no valid json
|
||||
* @throws IOException socket error
|
||||
*/
|
||||
public void addController(int channels, int i2c_dev, String address, final AddControllerCallback callback) throws JSONException, IOException {
|
||||
JSONObject jnson = new JSONObject();
|
||||
|
||||
jnson.put("action", ACTION_ADDCONTROLLER);
|
||||
jnson.put("channels", channels);
|
||||
jnson.put("i2c_dev", i2c_dev);
|
||||
jnson.put("address", address);
|
||||
|
||||
sendJSON(jnson, new AnswerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (response.getBoolean("success")) {
|
||||
callback.onControllerAdded(response.getInt("cid"));
|
||||
} else {
|
||||
callback.onAddFailed(response.getString("message"), response.getString("message_detail"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color using the stripeid
|
||||
*
|
||||
* @param sid Stripeid
|
||||
* @param color Color in HSV format
|
||||
* @throws JSONException no valid json
|
||||
* @throws IOException socket error
|
||||
*/
|
||||
public void setColor(int sid, HSV color) throws JSONException, IOException {
|
||||
JSONObject jnson = new JSONObject();
|
||||
JSONObject hsv = new JSONObject();
|
||||
|
||||
hsv.put("h", color.getHue());
|
||||
hsv.put("s", color.getSaturation());
|
||||
hsv.put("v", color.getValue());
|
||||
|
||||
jnson.put("action", ACTION_SETCOLOR);
|
||||
jnson.put("sid", sid);
|
||||
jnson.put("color", hsv);
|
||||
|
||||
sendJSON(jnson, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color using the stripeid
|
||||
*
|
||||
* @param sid Stripeid
|
||||
* @throws JSONException no valid json
|
||||
* @throws IOException socket error
|
||||
*/
|
||||
public void getColor(int sid, final RecieveColorCallback callback) throws JSONException, IOException {
|
||||
JSONObject jnson = new JSONObject();
|
||||
|
||||
jnson.put("action", ACTION_GETCOLOR);
|
||||
jnson.put("sid", sid);
|
||||
|
||||
sendJSON(jnson, new AnswerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (response.getBoolean("success")) {
|
||||
|
||||
JSONObject hsv = null;
|
||||
|
||||
hsv = response.getJSONObject("hsv");
|
||||
callback.onColorRecieved(new HSV(hsv.getDouble("h"), hsv.getDouble("s"), hsv.getDouble("v")));
|
||||
} else {
|
||||
callback.onRecievFailed(response.getString("message"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendJSON(JSONObject json, AnswerTask task) throws IOException, JSONException {
|
||||
if (mBound) binderService.queueSend(host, json, task);
|
||||
}
|
||||
|
||||
@DebugLog
|
||||
public void teardown() {
|
||||
if (mBound) {
|
||||
context.unbindService(mConnection);
|
||||
mBound = false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,143 @@
|
||||
package com.idlegandalf.ledd.services;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
|
||||
import com.idlegandalf.ledd.components.AnswerTask;
|
||||
import com.idlegandalf.ledd.components.Host;
|
||||
import com.idlegandalf.ledd.components.Sendable;
|
||||
import com.koushikdutta.async.AsyncServer;
|
||||
import com.koushikdutta.async.AsyncSocket;
|
||||
import com.koushikdutta.async.ByteBufferList;
|
||||
import com.koushikdutta.async.DataEmitter;
|
||||
import com.koushikdutta.async.Util;
|
||||
import com.koushikdutta.async.callback.ConnectCallback;
|
||||
import com.koushikdutta.async.callback.DataCallback;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import hugo.weaving.DebugLog;
|
||||
|
||||
public class ColorService extends Service {
|
||||
private final IBinder mBinder = new ColorBinder();
|
||||
private LinkedBlockingQueue<Sendable> queue;
|
||||
private Worker<Sendable> worker;
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
queue = new LinkedBlockingQueue<>();
|
||||
worker = new Worker<>(queue);
|
||||
new Thread(worker).start();
|
||||
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
worker.stop();
|
||||
}
|
||||
|
||||
private static class Worker<T> implements Runnable {
|
||||
private final LinkedBlockingQueue<T> workQueue;
|
||||
private HashMap<Host, AsyncSocket> socketHashMap;
|
||||
private HashMap<String, Sendable> sendableHashMap;
|
||||
|
||||
DataCallback dataCallback = new DataCallback() {
|
||||
@Override
|
||||
public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
|
||||
JSONObject resp = null;
|
||||
try {
|
||||
resp = new JSONObject(new String(bb.getAllByteArray()));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (resp != null) {
|
||||
try {
|
||||
if (sendableHashMap.containsKey(resp.getString("ref"))) {
|
||||
sendableHashMap.get(resp.getString("ref")).onResponse(resp);
|
||||
sendableHashMap.remove(resp.getString("ref"));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Worker(LinkedBlockingQueue<T> workQueue) {
|
||||
this.workQueue = workQueue;
|
||||
this.socketHashMap = new HashMap<>();
|
||||
this.sendableHashMap = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DebugLog
|
||||
public void run() {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
final T item = workQueue.take();
|
||||
|
||||
if (item instanceof Sendable) {
|
||||
if (socketHashMap.containsKey(((Sendable) item).getRecipient()) && socketHashMap.get(((Sendable) item).getRecipient())
|
||||
.getServer().isRunning()) {
|
||||
|
||||
Util.writeAll(socketHashMap.get(((Sendable) item).getRecipient()), ((Sendable) item).getMessage().toString().getBytes
|
||||
("UTF-8"), null);
|
||||
sendableHashMap.put(((Sendable) item).getRef(), (Sendable) item);
|
||||
} else {
|
||||
AsyncServer.getDefault().connectSocket(new InetSocketAddress(((Sendable) item).getRecipient().getAddress(), ((Sendable)
|
||||
item).getRecipient().getPort()), new ConnectCallback() {
|
||||
@Override
|
||||
public void onConnectCompleted(Exception ex, final AsyncSocket socket) {
|
||||
if (ex == null) {
|
||||
socket.setDataCallback(dataCallback);
|
||||
|
||||
socketHashMap.put(((Sendable) item).getRecipient(), socket);
|
||||
|
||||
if (!workQueue.contains(item)) {
|
||||
workQueue.add(item);
|
||||
}
|
||||
} else {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public class ColorBinder extends Binder {
|
||||
public String queueSend(Host rec, JSONObject msg, AnswerTask answerTask) throws JSONException {
|
||||
Sendable sendable = new Sendable(msg, answerTask, rec);
|
||||
queue.add(sendable);
|
||||
System.out.println("qlen: " + queue.size());
|
||||
return sendable.getRef();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,352 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Piotr Adamus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.idlegandalf.ledd.utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ComposeShader;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Join;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.RadialGradient;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader.TileMode;
|
||||
import android.graphics.SweepGradient;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
public class ColorPicker extends View {
|
||||
|
||||
/**
|
||||
* Customizable display parameters (in percents)
|
||||
*/
|
||||
private final int paramOuterPadding = 2; // outer padding of the whole color picker view
|
||||
private final int paramInnerPadding = 5; // distance between value slider wheel and inner color wheel
|
||||
private final int paramValueSliderWidth = 10; // width of the value slider
|
||||
private final int paramArrowPointerSize = 4; // size of the arrow pointer; set to 0 to hide the pointer
|
||||
|
||||
private Paint colorWheelPaint;
|
||||
private Paint valueSliderPaint;
|
||||
|
||||
private Paint colorViewPaint;
|
||||
|
||||
private Paint colorPointerPaint;
|
||||
private RectF colorPointerCoords;
|
||||
|
||||
private Paint valuePointerPaint;
|
||||
private Paint valuePointerArrowPaint;
|
||||
|
||||
private RectF outerWheelRect;
|
||||
private RectF innerWheelRect;
|
||||
|
||||
private Path colorViewPath;
|
||||
private Path valueSliderPath;
|
||||
private Path arrowPointerPath;
|
||||
|
||||
private Bitmap colorWheelBitmap;
|
||||
|
||||
private int valueSliderWidth;
|
||||
private int innerPadding;
|
||||
private int outerPadding;
|
||||
|
||||
private int arrowPointerSize;
|
||||
private int outerWheelRadius;
|
||||
private int innerWheelRadius;
|
||||
private int colorWheelRadius;
|
||||
|
||||
private Matrix gradientRotationMatrix;
|
||||
|
||||
/** Currently selected color */
|
||||
private float[] colorHSV = new float[] { 0f, 0f, 1f };
|
||||
|
||||
public ColorPicker(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
public ColorPicker(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public ColorPicker(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
|
||||
colorPointerPaint = new Paint();
|
||||
colorPointerPaint.setStyle(Style.STROKE);
|
||||
colorPointerPaint.setStrokeWidth(2f);
|
||||
colorPointerPaint.setARGB(128, 0, 0, 0);
|
||||
|
||||
valuePointerPaint = new Paint();
|
||||
valuePointerPaint.setStyle(Style.STROKE);
|
||||
valuePointerPaint.setStrokeWidth(2f);
|
||||
|
||||
valuePointerArrowPaint = new Paint();
|
||||
|
||||
colorWheelPaint = new Paint();
|
||||
colorWheelPaint.setAntiAlias(true);
|
||||
colorWheelPaint.setDither(true);
|
||||
|
||||
valueSliderPaint = new Paint();
|
||||
valueSliderPaint.setAntiAlias(true);
|
||||
valueSliderPaint.setDither(true);
|
||||
|
||||
colorViewPaint = new Paint();
|
||||
colorViewPaint.setAntiAlias(true);
|
||||
|
||||
colorViewPath = new Path();
|
||||
valueSliderPath = new Path();
|
||||
arrowPointerPath = new Path();
|
||||
|
||||
outerWheelRect = new RectF();
|
||||
innerWheelRect = new RectF();
|
||||
|
||||
colorPointerCoords = new RectF();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
int size = Math.min(widthSize, heightSize);
|
||||
setMeasuredDimension(size, size);
|
||||
}
|
||||
|
||||
@SuppressLint("DrawAllocation")
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
|
||||
int centerX = getWidth() / 2;
|
||||
int centerY = getHeight() / 2;
|
||||
|
||||
// drawing color wheel
|
||||
|
||||
canvas.drawBitmap(colorWheelBitmap, centerX - colorWheelRadius, centerY - colorWheelRadius, null);
|
||||
|
||||
// drawing color view
|
||||
|
||||
colorViewPaint.setColor(Color.HSVToColor(colorHSV));
|
||||
canvas.drawPath(colorViewPath, colorViewPaint);
|
||||
|
||||
// drawing value slider
|
||||
|
||||
float[] hsv = new float[] { colorHSV[0], colorHSV[1], 1f };
|
||||
|
||||
SweepGradient sweepGradient = new SweepGradient(centerX, centerY, new int[] { Color.BLACK, Color.HSVToColor(hsv), Color.WHITE }, null);
|
||||
sweepGradient.setLocalMatrix(gradientRotationMatrix);
|
||||
valueSliderPaint.setShader(sweepGradient);
|
||||
|
||||
canvas.drawPath(valueSliderPath, valueSliderPaint);
|
||||
|
||||
// drawing color wheel pointer
|
||||
|
||||
float hueAngle = (float) Math.toRadians(colorHSV[0]);
|
||||
int colorPointX = (int) (-Math.cos(hueAngle) * colorHSV[1] * colorWheelRadius) + centerX;
|
||||
int colorPointY = (int) (-Math.sin(hueAngle) * colorHSV[1] * colorWheelRadius) + centerY;
|
||||
|
||||
float pointerRadius = 0.075f * colorWheelRadius;
|
||||
int pointerX = (int) (colorPointX - pointerRadius / 2);
|
||||
int pointerY = (int) (colorPointY - pointerRadius / 2);
|
||||
|
||||
colorPointerCoords.set(pointerX, pointerY, pointerX + pointerRadius, pointerY + pointerRadius);
|
||||
canvas.drawOval(colorPointerCoords, colorPointerPaint);
|
||||
|
||||
// drawing value pointer
|
||||
|
||||
valuePointerPaint.setColor(Color.HSVToColor(new float[] { 0f, 0f, 1f - colorHSV[2] }));
|
||||
|
||||
double valueAngle = (colorHSV[2] - 0.5f) * Math.PI;
|
||||
float valueAngleX = (float) Math.cos(valueAngle);
|
||||
float valueAngleY = (float) Math.sin(valueAngle);
|
||||
|
||||
canvas.drawLine(valueAngleX * innerWheelRadius + centerX, valueAngleY * innerWheelRadius + centerY, valueAngleX * outerWheelRadius + centerX,
|
||||
valueAngleY * outerWheelRadius + centerY, valuePointerPaint);
|
||||
|
||||
// drawing pointer arrow
|
||||
|
||||
if (arrowPointerSize > 0) {
|
||||
drawPointerArrow(canvas);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void drawPointerArrow(Canvas canvas) {
|
||||
|
||||
int centerX = getWidth() / 2;
|
||||
int centerY = getHeight() / 2;
|
||||
|
||||
double tipAngle = (colorHSV[2] - 0.5f) * Math.PI;
|
||||
double leftAngle = tipAngle + Math.PI / 96;
|
||||
double rightAngle = tipAngle - Math.PI / 96;
|
||||
|
||||
double tipAngleX = Math.cos(tipAngle) * outerWheelRadius;
|
||||
double tipAngleY = Math.sin(tipAngle) * outerWheelRadius;
|
||||
double leftAngleX = Math.cos(leftAngle) * (outerWheelRadius + arrowPointerSize);
|
||||
double leftAngleY = Math.sin(leftAngle) * (outerWheelRadius + arrowPointerSize);
|
||||
double rightAngleX = Math.cos(rightAngle) * (outerWheelRadius + arrowPointerSize);
|
||||
double rightAngleY = Math.sin(rightAngle) * (outerWheelRadius + arrowPointerSize);
|
||||
|
||||
arrowPointerPath.reset();
|
||||
arrowPointerPath.moveTo((float) tipAngleX + centerX, (float) tipAngleY + centerY);
|
||||
arrowPointerPath.lineTo((float) leftAngleX + centerX, (float) leftAngleY + centerY);
|
||||
arrowPointerPath.lineTo((float) rightAngleX + centerX, (float) rightAngleY + centerY);
|
||||
arrowPointerPath.lineTo((float) tipAngleX + centerX, (float) tipAngleY + centerY);
|
||||
|
||||
valuePointerArrowPaint.setColor(Color.HSVToColor(colorHSV));
|
||||
valuePointerArrowPaint.setStyle(Style.FILL);
|
||||
canvas.drawPath(arrowPointerPath, valuePointerArrowPaint);
|
||||
|
||||
valuePointerArrowPaint.setStyle(Style.STROKE);
|
||||
valuePointerArrowPaint.setStrokeJoin(Join.ROUND);
|
||||
valuePointerArrowPaint.setColor(Color.BLACK);
|
||||
canvas.drawPath(arrowPointerPath, valuePointerArrowPaint);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int width, int height, int oldw, int oldh) {
|
||||
|
||||
int centerX = width / 2;
|
||||
int centerY = height / 2;
|
||||
|
||||
innerPadding = (int) (paramInnerPadding * width / 100);
|
||||
outerPadding = (int) (paramOuterPadding * width / 100);
|
||||
arrowPointerSize = (int) (paramArrowPointerSize * width / 100);
|
||||
valueSliderWidth = (int) (paramValueSliderWidth * width / 100);
|
||||
|
||||
outerWheelRadius = width / 2 - outerPadding - arrowPointerSize;
|
||||
innerWheelRadius = outerWheelRadius - valueSliderWidth;
|
||||
colorWheelRadius = innerWheelRadius - innerPadding;
|
||||
|
||||
outerWheelRect.set(centerX - outerWheelRadius, centerY - outerWheelRadius, centerX + outerWheelRadius, centerY + outerWheelRadius);
|
||||
innerWheelRect.set(centerX - innerWheelRadius, centerY - innerWheelRadius, centerX + innerWheelRadius, centerY + innerWheelRadius);
|
||||
|
||||
colorWheelBitmap = createColorWheelBitmap(colorWheelRadius * 2, colorWheelRadius * 2);
|
||||
|
||||
gradientRotationMatrix = new Matrix();
|
||||
gradientRotationMatrix.preRotate(270, width / 2, height / 2);
|
||||
|
||||
colorViewPath.arcTo(outerWheelRect, 270, -180);
|
||||
colorViewPath.arcTo(innerWheelRect, 90, 180);
|
||||
|
||||
valueSliderPath.arcTo(outerWheelRect, 270, 180);
|
||||
valueSliderPath.arcTo(innerWheelRect, 90, -180);
|
||||
|
||||
}
|
||||
|
||||
private Bitmap createColorWheelBitmap(int width, int height) {
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
|
||||
|
||||
int colorCount = 12;
|
||||
int colorAngleStep = 360 / 12;
|
||||
int colors[] = new int[colorCount + 1];
|
||||
float hsv[] = new float[] { 0f, 1f, 1f };
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
hsv[0] = (i * colorAngleStep + 180) % 360;
|
||||
colors[i] = Color.HSVToColor(hsv);
|
||||
}
|
||||
colors[colorCount] = colors[0];
|
||||
|
||||
SweepGradient sweepGradient = new SweepGradient(width / 2, height / 2, colors, null);
|
||||
RadialGradient radialGradient = new RadialGradient(width / 2, height / 2, colorWheelRadius, 0xFFFFFFFF, 0x00FFFFFF, TileMode.CLAMP);
|
||||
ComposeShader composeShader = new ComposeShader(sweepGradient, radialGradient, PorterDuff.Mode.SRC_OVER);
|
||||
|
||||
colorWheelPaint.setShader(composeShader);
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
canvas.drawCircle(width / 2, height / 2, colorWheelRadius, colorWheelPaint);
|
||||
|
||||
return bitmap;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
int action = event.getAction();
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
int cx = x - getWidth() / 2;
|
||||
int cy = y - getHeight() / 2;
|
||||
double d = Math.sqrt(cx * cx + cy * cy);
|
||||
|
||||
if (d <= colorWheelRadius) {
|
||||
|
||||
colorHSV[0] = (float) (Math.toDegrees(Math.atan2(cy, cx)) + 180f);
|
||||
colorHSV[1] = Math.max(0f, Math.min(1f, (float) (d / colorWheelRadius)));
|
||||
|
||||
invalidate();
|
||||
|
||||
} else if (x >= getWidth() / 2 && d >= innerWheelRadius) {
|
||||
|
||||
colorHSV[2] = (float) Math.max(0, Math.min(1, Math.atan2(cy, cx) / Math.PI + 0.5f));
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
Color.colorToHSV(color, colorHSV);
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return Color.HSVToColor(colorHSV);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
Bundle state = new Bundle();
|
||||
state.putFloatArray("color", colorHSV);
|
||||
state.putParcelable("super", super.onSaveInstanceState());
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof Bundle) {
|
||||
Bundle bundle = (Bundle) state;
|
||||
colorHSV = bundle.getFloatArray("color");
|
||||
super.onRestoreInstanceState(bundle.getParcelable("super"));
|
||||
} else {
|
||||
super.onRestoreInstanceState(state);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,54 +0,0 @@
|
||||
package com.idlegandalf.ledd.utils;
|
||||
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.RelativeLayout.LayoutParams;
|
||||
|
||||
public class ColorPickerDialog extends AlertDialog {
|
||||
|
||||
private ColorPicker colorPickerView;
|
||||
private final OnColorSelectedListener onColorSelectedListener;
|
||||
|
||||
public ColorPickerDialog(Context context, int initialColor, OnColorSelectedListener onColorSelectedListener) {
|
||||
super(context);
|
||||
|
||||
this.onColorSelectedListener = onColorSelectedListener;
|
||||
|
||||
RelativeLayout relativeLayout = new RelativeLayout(context);
|
||||
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
|
||||
|
||||
colorPickerView = new ColorPicker(context);
|
||||
colorPickerView.setColor(initialColor);
|
||||
|
||||
relativeLayout.addView(colorPickerView, layoutParams);
|
||||
|
||||
setButton(BUTTON_POSITIVE, context.getString(android.R.string.ok), onClickListener);
|
||||
setButton(BUTTON_NEGATIVE, context.getString(android.R.string.cancel), onClickListener);
|
||||
|
||||
setView(relativeLayout);
|
||||
|
||||
}
|
||||
|
||||
private OnClickListener onClickListener = new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case BUTTON_POSITIVE:
|
||||
int selectedColor = colorPickerView.getColor();
|
||||
onColorSelectedListener.onColorSelected(selectedColor);
|
||||
break;
|
||||
case BUTTON_NEGATIVE:
|
||||
dialog.dismiss();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public interface OnColorSelectedListener {
|
||||
public void onColorSelected(int color);
|
||||
}
|
||||
|
||||
}
|
@@ -1,73 +0,0 @@
|
||||
package com.idlegandalf.ledd.utils;
|
||||
|
||||
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.preference.DialogPreference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.RelativeLayout.LayoutParams;
|
||||
|
||||
public class ColorPickerPreference extends DialogPreference {
|
||||
|
||||
public static final int DEFAULT_COLOR = Color.WHITE;
|
||||
|
||||
private int selectedColor;
|
||||
private ColorPicker colorPickerView;
|
||||
|
||||
public ColorPickerPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onCreateDialogView() {
|
||||
|
||||
RelativeLayout relativeLayout = new RelativeLayout(getContext());
|
||||
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
|
||||
|
||||
colorPickerView = new ColorPicker(getContext());
|
||||
colorPickerView.setId(1);
|
||||
|
||||
relativeLayout.addView(colorPickerView, layoutParams);
|
||||
|
||||
return relativeLayout;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindDialogView(View view) {
|
||||
super.onBindDialogView(view);
|
||||
colorPickerView.setColor(selectedColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(Builder builder) {
|
||||
super.onPrepareDialogBuilder(builder);
|
||||
builder.setTitle(null); // remove dialog title to get more space for color picker
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult) {
|
||||
if (positiveResult && shouldPersist()) {
|
||||
if (callChangeListener(colorPickerView.getColor())) {
|
||||
selectedColor = colorPickerView.getColor();
|
||||
persistInt(selectedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
|
||||
selectedColor = restoreValue ? getPersistedInt(DEFAULT_COLOR) : (Integer) defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object onGetDefaultValue(TypedArray a, int index) {
|
||||
return a.getInt(index, DEFAULT_COLOR);
|
||||
}
|
||||
|
||||
}
|
@@ -1,401 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Piotr Adamus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.idlegandalf.ledd.utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ComposeShader;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Join;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.RadialGradient;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader.TileMode;
|
||||
import android.graphics.SweepGradient;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
public class MultiColorPicker extends View {
|
||||
|
||||
/**
|
||||
* Customizable display parameters (in percents)
|
||||
*/
|
||||
private final int paramOuterPadding = 2; // outer padding of the whole color picker view
|
||||
private final int paramInnerPadding = 5; // distance between value slider wheel and inner color wheel
|
||||
private final int paramValueSliderWidth = 10; // width of the value slider
|
||||
private final int paramArrowPointerSize = 4; // size of the arrow pointer; set to 0 to hide the pointer
|
||||
|
||||
private final int paramColorCount = 5;
|
||||
private final float paramHueSpreadAngle = 30f; // in degrees
|
||||
|
||||
private Paint colorWheelPaint;
|
||||
private Paint valueSliderPaint;
|
||||
|
||||
private Paint colorViewPaint;
|
||||
|
||||
private Paint colorPointerPaint;
|
||||
private RectF colorPointerCoords;
|
||||
|
||||
private Paint valuePointerPaint;
|
||||
private Paint valuePointerArrowPaint;
|
||||
|
||||
private RectF outerWheelRect;
|
||||
private RectF innerWheelRect;
|
||||
|
||||
private Path colorViewPath;
|
||||
private Path valueSliderPath;
|
||||
private Path arrowPointerPath;
|
||||
|
||||
private Bitmap colorWheelBitmap;
|
||||
|
||||
private int valueSliderWidth;
|
||||
private int innerPadding;
|
||||
private int outerPadding;
|
||||
|
||||
private int arrowPointerSize;
|
||||
private int outerWheelRadius;
|
||||
private int innerWheelRadius;
|
||||
private int colorWheelRadius;
|
||||
|
||||
private Matrix gradientRotationMatrix;
|
||||
|
||||
/** Currently selected color */
|
||||
private float[] colorHSV = new float[] { 0f, 0f, 1f };
|
||||
private float[] adjacentHue = new float[paramColorCount];
|
||||
|
||||
public MultiColorPicker(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
public MultiColorPicker(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public MultiColorPicker(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
|
||||
colorPointerPaint = new Paint();
|
||||
colorPointerPaint.setStyle(Style.STROKE);
|
||||
colorPointerPaint.setStrokeWidth(2f);
|
||||
colorPointerPaint.setARGB(128, 0, 0, 0);
|
||||
|
||||
valuePointerPaint = new Paint();
|
||||
valuePointerPaint.setStyle(Style.STROKE);
|
||||
valuePointerPaint.setStrokeWidth(2f);
|
||||
|
||||
valuePointerArrowPaint = new Paint();
|
||||
|
||||
colorWheelPaint = new Paint();
|
||||
colorWheelPaint.setAntiAlias(true);
|
||||
colorWheelPaint.setDither(true);
|
||||
|
||||
valueSliderPaint = new Paint();
|
||||
valueSliderPaint.setAntiAlias(true);
|
||||
valueSliderPaint.setDither(true);
|
||||
|
||||
colorViewPaint = new Paint();
|
||||
colorViewPaint.setAntiAlias(true);
|
||||
|
||||
colorViewPath = new Path();
|
||||
valueSliderPath = new Path();
|
||||
arrowPointerPath = new Path();
|
||||
|
||||
outerWheelRect = new RectF();
|
||||
innerWheelRect = new RectF();
|
||||
|
||||
colorPointerCoords = new RectF();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
int size = Math.min(widthSize, heightSize);
|
||||
setMeasuredDimension(size, size);
|
||||
}
|
||||
|
||||
@SuppressLint("DrawAllocation")
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
|
||||
int centerX = getWidth() / 2;
|
||||
int centerY = getHeight() / 2;
|
||||
|
||||
// drawing color wheel
|
||||
|
||||
canvas.drawBitmap(colorWheelBitmap, centerX - colorWheelRadius, centerY - colorWheelRadius, null);
|
||||
|
||||
// drawing color view
|
||||
|
||||
int[] segmentColors = getColors();
|
||||
float sweepAngleStep = 180f / paramColorCount;
|
||||
for (int i = 0; i < paramColorCount; i++) {
|
||||
|
||||
colorViewPath.reset();
|
||||
colorViewPath.arcTo(outerWheelRect, 270 - i * sweepAngleStep, -sweepAngleStep);
|
||||
colorViewPath.arcTo(innerWheelRect, 90 + (paramColorCount - i - 1) * sweepAngleStep, sweepAngleStep);
|
||||
|
||||
colorViewPaint.setColor(segmentColors[i]);
|
||||
|
||||
canvas.drawPath(colorViewPath, colorViewPaint);
|
||||
|
||||
}
|
||||
|
||||
// drawing value slider
|
||||
|
||||
float[] hsv = new float[] { colorHSV[0], colorHSV[1], 1f };
|
||||
|
||||
SweepGradient sweepGradient = new SweepGradient(centerX, centerY, new int[] { Color.BLACK, Color.HSVToColor(hsv), Color.WHITE }, null);
|
||||
sweepGradient.setLocalMatrix(gradientRotationMatrix);
|
||||
valueSliderPaint.setShader(sweepGradient);
|
||||
|
||||
canvas.drawPath(valueSliderPath, valueSliderPaint);
|
||||
|
||||
// drawing color wheel pointer
|
||||
|
||||
for (int i = 0; i < paramColorCount; i++) {
|
||||
drawColorWheelPointer(canvas, (float) Math.toRadians(adjacentHue[i]));
|
||||
}
|
||||
|
||||
// drawing value pointer
|
||||
|
||||
valuePointerPaint.setColor(Color.HSVToColor(new float[] { 0f, 0f, 1f - colorHSV[2] }));
|
||||
|
||||
double valueAngle = (colorHSV[2] - 0.5f) * Math.PI;
|
||||
float valueAngleX = (float) Math.cos(valueAngle);
|
||||
float valueAngleY = (float) Math.sin(valueAngle);
|
||||
|
||||
canvas.drawLine(valueAngleX * innerWheelRadius + centerX, valueAngleY * innerWheelRadius + centerY, valueAngleX * outerWheelRadius + centerX,
|
||||
valueAngleY * outerWheelRadius + centerY, valuePointerPaint);
|
||||
|
||||
// drawing pointer arrow
|
||||
|
||||
if (arrowPointerSize > 0) {
|
||||
drawPointerArrow(canvas);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void drawColorWheelPointer(Canvas canvas, float hueAngle) {
|
||||
|
||||
int centerX = getWidth() / 2;
|
||||
int centerY = getHeight() / 2;
|
||||
|
||||
int colorPointX = (int) (-Math.cos(hueAngle) * colorHSV[1] * colorWheelRadius) + centerX;
|
||||
int colorPointY = (int) (-Math.sin(hueAngle) * colorHSV[1] * colorWheelRadius) + centerY;
|
||||
|
||||
float pointerRadius = 0.075f * colorWheelRadius;
|
||||
int pointerX = (int) (colorPointX - pointerRadius / 2);
|
||||
int pointerY = (int) (colorPointY - pointerRadius / 2);
|
||||
|
||||
colorPointerCoords.set(pointerX, pointerY, pointerX + pointerRadius, pointerY + pointerRadius);
|
||||
canvas.drawOval(colorPointerCoords, colorPointerPaint);
|
||||
|
||||
}
|
||||
|
||||
private void drawPointerArrow(Canvas canvas) {
|
||||
|
||||
int centerX = getWidth() / 2;
|
||||
int centerY = getHeight() / 2;
|
||||
|
||||
double tipAngle = (colorHSV[2] - 0.5f) * Math.PI;
|
||||
double leftAngle = tipAngle + Math.PI / 96;
|
||||
double rightAngle = tipAngle - Math.PI / 96;
|
||||
|
||||
double tipAngleX = Math.cos(tipAngle) * outerWheelRadius;
|
||||
double tipAngleY = Math.sin(tipAngle) * outerWheelRadius;
|
||||
double leftAngleX = Math.cos(leftAngle) * (outerWheelRadius + arrowPointerSize);
|
||||
double leftAngleY = Math.sin(leftAngle) * (outerWheelRadius + arrowPointerSize);
|
||||
double rightAngleX = Math.cos(rightAngle) * (outerWheelRadius + arrowPointerSize);
|
||||
double rightAngleY = Math.sin(rightAngle) * (outerWheelRadius + arrowPointerSize);
|
||||
|
||||
arrowPointerPath.reset();
|
||||
arrowPointerPath.moveTo((float) tipAngleX + centerX, (float) tipAngleY + centerY);
|
||||
arrowPointerPath.lineTo((float) leftAngleX + centerX, (float) leftAngleY + centerY);
|
||||
arrowPointerPath.lineTo((float) rightAngleX + centerX, (float) rightAngleY + centerY);
|
||||
arrowPointerPath.lineTo((float) tipAngleX + centerX, (float) tipAngleY + centerY);
|
||||
|
||||
valuePointerArrowPaint.setColor(Color.HSVToColor(colorHSV));
|
||||
valuePointerArrowPaint.setStyle(Style.FILL);
|
||||
canvas.drawPath(arrowPointerPath, valuePointerArrowPaint);
|
||||
|
||||
valuePointerArrowPaint.setStyle(Style.STROKE);
|
||||
valuePointerArrowPaint.setStrokeJoin(Join.ROUND);
|
||||
valuePointerArrowPaint.setColor(Color.BLACK);
|
||||
canvas.drawPath(arrowPointerPath, valuePointerArrowPaint);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int width, int height, int oldw, int oldh) {
|
||||
|
||||
int centerX = width / 2;
|
||||
int centerY = height / 2;
|
||||
|
||||
innerPadding = (int) (paramInnerPadding * width / 100);
|
||||
outerPadding = (int) (paramOuterPadding * width / 100);
|
||||
arrowPointerSize = (int) (paramArrowPointerSize * width / 100);
|
||||
valueSliderWidth = (int) (paramValueSliderWidth * width / 100);
|
||||
|
||||
outerWheelRadius = width / 2 - outerPadding - arrowPointerSize;
|
||||
innerWheelRadius = outerWheelRadius - valueSliderWidth;
|
||||
colorWheelRadius = innerWheelRadius - innerPadding;
|
||||
|
||||
outerWheelRect.set(centerX - outerWheelRadius, centerY - outerWheelRadius, centerX + outerWheelRadius, centerY + outerWheelRadius);
|
||||
innerWheelRect.set(centerX - innerWheelRadius, centerY - innerWheelRadius, centerX + innerWheelRadius, centerY + innerWheelRadius);
|
||||
|
||||
colorWheelBitmap = createColorWheelBitmap(colorWheelRadius * 2, colorWheelRadius * 2);
|
||||
|
||||
gradientRotationMatrix = new Matrix();
|
||||
gradientRotationMatrix.preRotate(270, width / 2, height / 2);
|
||||
|
||||
valueSliderPath.arcTo(outerWheelRect, 270, 180);
|
||||
valueSliderPath.arcTo(innerWheelRect, 90, -180);
|
||||
|
||||
}
|
||||
|
||||
private Bitmap createColorWheelBitmap(int width, int height) {
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
|
||||
|
||||
int colorCount = 12;
|
||||
int colorAngleStep = 360 / 12;
|
||||
int colors[] = new int[colorCount + 1];
|
||||
float hsv[] = new float[] { 0f, 1f, 1f };
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
hsv[0] = (i * colorAngleStep + 180) % 360;
|
||||
colors[i] = Color.HSVToColor(hsv);
|
||||
}
|
||||
colors[colorCount] = colors[0];
|
||||
|
||||
SweepGradient sweepGradient = new SweepGradient(width / 2, height / 2, colors, null);
|
||||
RadialGradient radialGradient = new RadialGradient(width / 2, height / 2, colorWheelRadius, 0xFFFFFFFF, 0x00FFFFFF, TileMode.CLAMP);
|
||||
ComposeShader composeShader = new ComposeShader(sweepGradient, radialGradient, PorterDuff.Mode.SRC_OVER);
|
||||
|
||||
colorWheelPaint.setShader(composeShader);
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
canvas.drawCircle(width / 2, height / 2, colorWheelRadius, colorWheelPaint);
|
||||
|
||||
return bitmap;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
int action = event.getAction();
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
int cx = x - getWidth() / 2;
|
||||
int cy = y - getHeight() / 2;
|
||||
double d = Math.sqrt(cx * cx + cy * cy);
|
||||
|
||||
if (d <= colorWheelRadius) {
|
||||
|
||||
colorHSV[0] = (float) (Math.toDegrees(Math.atan2(cy, cx)) + 180f);
|
||||
colorHSV[1] = Math.max(0f, Math.min(1f, (float) (d / colorWheelRadius)));
|
||||
|
||||
updateAdjacentHue();
|
||||
invalidate();
|
||||
|
||||
} else if (x >= getWidth() / 2 && d >= innerWheelRadius) {
|
||||
|
||||
colorHSV[2] = (float) Math.max(0, Math.min(1, Math.atan2(cy, cx) / Math.PI + 0.5f));
|
||||
|
||||
updateAdjacentHue();
|
||||
invalidate();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
private void updateAdjacentHue() {
|
||||
|
||||
for (int i = 0; i < paramColorCount; i++) {
|
||||
adjacentHue[i] = (colorHSV[0] - paramHueSpreadAngle * (paramColorCount / 2 - i)) % 360.0f;
|
||||
adjacentHue[i] = (adjacentHue[i] < 0) ? adjacentHue[i] + 360f : adjacentHue[i];
|
||||
}
|
||||
adjacentHue[paramColorCount / 2] = colorHSV[0];
|
||||
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
Color.colorToHSV(color, colorHSV);
|
||||
updateAdjacentHue();
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return Color.HSVToColor(colorHSV);
|
||||
}
|
||||
|
||||
public int[] getColors() {
|
||||
int[] colors = new int[paramColorCount];
|
||||
float[] hsv = new float[3];
|
||||
for (int i = 0; i < paramColorCount; i++) {
|
||||
hsv[0] = adjacentHue[i];
|
||||
hsv[1] = colorHSV[1];
|
||||
hsv[2] = colorHSV[2];
|
||||
colors[i] = Color.HSVToColor(hsv);
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
Bundle state = new Bundle();
|
||||
state.putFloatArray("color", colorHSV);
|
||||
state.putParcelable("super", super.onSaveInstanceState());
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof Bundle) {
|
||||
Bundle bundle = (Bundle) state;
|
||||
colorHSV = bundle.getFloatArray("color");
|
||||
updateAdjacentHue();
|
||||
super.onRestoreInstanceState(bundle.getParcelable("super"));
|
||||
} else {
|
||||
super.onRestoreInstanceState(state);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Before Width: | Height: | Size: 161 B |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 142 B |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 174 B |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 202 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" >
|
||||
<solid android:color="#000000" />
|
||||
</shape>
|
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp" >
|
||||
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:drawSelectorOnTop="false" />
|
||||
|
||||
</LinearLayout>
|
@@ -1,21 +0,0 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<com.chiralcode.colorpicker.MultiColorPicker
|
||||
android:id="@+id/multiColorPicker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="0.8" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_weight="0.2"
|
||||
android:text="@string/button_label" />
|
||||
|
||||
</LinearLayout>
|
@@ -1,21 +0,0 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<com.chiralcode.colorpicker.ColorPicker
|
||||
android:id="@+id/colorPicker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="0.8" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_weight="0.2"
|
||||
android:text="@string/button_label" />
|
||||
|
||||
</LinearLayout>
|
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:key="example_preferences" >
|
||||
|
||||
<com.chiralcode.colorpicker.ColorPickerPreference
|
||||
android:defaultValue="0xffffffff"
|
||||
android:key="color"
|
||||
android:title="@string/pref_name"
|
||||
android:summary="@string/pref_summary" />
|
||||
|
||||
</PreferenceScreen>
|
@@ -1,22 +1,37 @@
|
||||
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
<android.support.v4.widget.DrawerLayout
|
||||
android:id="@+id/drawer_layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- The main content view -->
|
||||
|
||||
<com.idlegandalf.ledd.utils.ColorPicker
|
||||
android:id="@+id/colorPicker"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
android:background="?attr/colorPrimary"
|
||||
android:minHeight="?android:attr/actionBarSize"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/stripe_container"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- The navigation drawer -->
|
||||
|
||||
<fragment
|
||||
android:name="com.idlegandalf.ledd.DrawerFragment"
|
||||
android:id="@+id/drawer"
|
||||
android:name="com.idlegandalf.ledd.DrawerFragment"
|
||||
android:layout_width="240dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
|
@@ -1,8 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/white"
|
||||
android:orientation="vertical" >
|
||||
android:background="@android:color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/lay_settings"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="5dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingTop="5dp">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/nd_icon"
|
||||
android:layout_height="@dimen/nd_icon"
|
||||
android:layout_marginLeft="@dimen/space_before_icon"
|
||||
android:src="@drawable/ic_tune_black_48dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:text="Settings"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Button"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/lay_add_host"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/lay_settings"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="5dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingTop="5dp">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/nd_icon"
|
||||
android:layout_height="@dimen/nd_icon"
|
||||
android:layout_marginLeft="@dimen/space_before_icon"
|
||||
android:src="@drawable/ic_add_box_black_48dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:text="Add Host"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Button"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/listview_controller_lay"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/lay_add_host">
|
||||
|
||||
<ExpandableListView
|
||||
android:id="@+id/listview_controller"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
@@ -1,84 +0,0 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/linlayp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
tools:context=".StepOneActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_welcome_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="Step 1.1: Select Controller manually"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/step2_next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:text="test controller" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/step2_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:text="back" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linBox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/text_welcome_title"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="50dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/ipSelect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|left"
|
||||
android:ems="8"
|
||||
android:gravity="center_horizontal"
|
||||
android:hint="IP address"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="phone"
|
||||
android:maxLength="15" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/portSelect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:ems="4"
|
||||
android:gravity="center_horizontal"
|
||||
android:hint="port"
|
||||
android:imeActionLabel="Test"
|
||||
android:inputType="phone"
|
||||
android:maxLength="5" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
@@ -1,93 +0,0 @@
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_welcome_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="Welcome"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/welcome_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/text_welcome_title"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="30dp"
|
||||
android:text="Welcome to the RGB Stripe Control App. This assistent gives you an step-by-step introduction to setup your stripe configuration."
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/step1_auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:text="autosearch"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/step1_manual"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:text="set manual"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_choose"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/step1_auto"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="18dp"
|
||||
android:text="choose way to select contoller"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_above="@id/text_choose"
|
||||
android:layout_below="@id/welcome_text"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:layout_marginTop="20dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/host_container"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"/>
|
||||
</ScrollView>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|enterAlways"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
@@ -1,10 +1,5 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:com.gh.stripecontrol="http://schemas.android.com/apk/res-auto" >
|
||||
<menu
|
||||
>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
com.gh.stripecontrol:showAsAction="always"
|
||||
android:title=""
|
||||
android:icon="@drawable/ic_action_settings" />
|
||||
|
||||
</menu>
|
||||
|
@@ -1,4 +0,0 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
|
||||
</menu>
|
@@ -1,3 +0,0 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
</menu>
|
5
app/src/main/res/values/color.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="primaryColor">#3ae765</color>
|
||||
<color name="primaryColorDark">#69cc59</color>
|
||||
</resources>
|
@@ -3,5 +3,7 @@
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<dimen name="nd_icon">30dp</dimen>
|
||||
<dimen name="space_before_icon">7dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
@@ -15,6 +15,11 @@
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
|
||||
<!-- ...and here we setting appcompat’s color theming attrs -->
|
||||
<item name="colorPrimary">@color/primaryColor</item>
|
||||
<item name="colorPrimaryDark">@color/primaryColorDark</item>
|
||||
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|