package edu.cmsc434.paintdrip.paintdripprototype; import android.app.ActionBar; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Typeface; import android.location.Criteria; import android.location.Location; import android.location.LocationManager; import android.preference.PreferenceManager; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import android.util.Log; import android.util.TypedValue; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import android.widget.ToggleButton; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.FusedLocationProviderApi; import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.PolylineOptions; import com.sothree.slidinguppanel.SlidingUpPanelLayout; import java.io.FileOutputStream; import java.io.IOException; import java.util.LinkedList; import java.util.List; import afzkl.development.colorpickerview.dialog.ColorPickerDialog; import edu.cmsc434.paintdrip.paintdripprototype.Paint.PaintingPath; import edu.cmsc434.paintdrip.paintdripprototype.Paint.Stroke; import edu.cmsc434.paintdrip.paintdripprototype.Share.ShareActivity; public class MapsActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { private final int DEFAULT_ZOOM_LEVEL = 18; private GoogleMap map; // Might be null if Google Play services APK is not available. private GoogleApiClient googleApiClient; private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi; private PaintingPath painting; private List<Polyline> drawnPolylines; private boolean isPainting = false; private Tool selectedTool = Tool.NONE; private boolean isSaving = false; private enum Tool { ERASER, PENCIL, PAINTBRUSH, PEN, NONE } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); googleApiClient = new GoogleApiClient.Builder(getBaseContext()) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); if (googleApiClient != null) { googleApiClient.connect(); } setContentView(R.layout.activity_maps); setUpMapIfNeeded(); map.setMyLocationEnabled(true); map.getUiSettings().setZoomControlsEnabled(false); map.getUiSettings().setMyLocationButtonEnabled(true); SlidingUpPanelLayout slider = (SlidingUpPanelLayout)findViewById(R.id.sliding_layout); slider.setPanelSlideListener(new StyleSlideListener()); SlidingUpPanelLayout saveSlider = (SlidingUpPanelLayout)findViewById(R.id.sliding_layout_save); saveSlider.setPanelSlideListener(new SaveSlideListener()); painting = new PaintingPath(); painting.setColor(getSelectedColor()); drawnPolylines = new LinkedList<Polyline>(); int actionBarTitle = Resources.getSystem().getIdentifier("action_bar_title", "id", "android"); TextView actionBarTitleView = (TextView) getWindow().findViewById(actionBarTitle); Typeface font = Typeface.createFromAsset(getAssets(), "fonts/GrandHotel-Regular.otf"); if(actionBarTitleView != null){ actionBarTitleView.setTypeface(font); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu items for use in the action bar MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.paint, menu); if (isSaving) { menu.findItem(R.id.action_save).setVisible(false); } else { menu.findItem(R.id.action_save).setVisible(true); } return super.onCreateOptionsMenu(menu); } @Override protected void onPause() { if (googleApiClient.isConnected()) { fusedLocationProviderApi.removeLocationUpdates(googleApiClient, this); } super.onPause(); } @Override protected void onResume() { super.onResume(); setUpMapIfNeeded(); if (googleApiClient.isConnected()) { LocationRequest locationRequest = LocationRequest.create(); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this); } } public void onBackPressed() { if (isSaving) { SlidingUpPanelLayout slider = (SlidingUpPanelLayout)findViewById(R.id.sliding_layout_save); slider.setSlidingEnabled(true); slider.collapsePanel(); map.setMyLocationEnabled(true); invalidateOptionsMenu(); isSaving = false; } else { super.onBackPressed(); } } /** * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly * installed) and the map has not already been instantiated.. This will ensure that we only ever * call {@link #setUpMap()} once when {@link #map} is not null. * <p/> * If it isn't installed {@link SupportMapFragment} (and * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to * install/update the Google Play services APK on their device. * <p/> * A user can return to this FragmentActivity after following the prompt and correctly * installing/updating/enabling the Google Play services. Since the FragmentActivity may not * have been completely destroyed during this process (it is likely that it would only be * stopped or paused), {@link #onCreate(Bundle)} may not be called again so we should call this * method in {@link #onResume()} to guarantee that it will be called. */ private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the map. if (map == null) { // Try to obtain the map from the SupportMapFragment. map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) .getMap(); // Check if we were successful in obtaining the map. if (map != null) { setUpMap(); } } } /** * This is where we can add markers or lines, add listeners or move the camera. In this case, we * just add a marker near Africa. * <p/> * This should only be called once and when we are sure that {@link #map} is not null. */ private void setUpMap() { centerMapAtCurrentLocation(); } //region Map Functions private void centerMapAtCurrentLocation() { LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); Location location = locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, false)); if (location != null) { map.animateCamera(CameraUpdateFactory.newLatLngZoom( new LatLng(location.getLatitude(), location.getLongitude()), DEFAULT_ZOOM_LEVEL)); } } //endregion //region Layout Functions private class StyleSlideListener implements SlidingUpPanelLayout.PanelSlideListener { @Override public void onPanelSlide(View view, float v) { ImageView arrow = (ImageView)findViewById(R.id.drawer_arrow); if (v > .5) { arrow.setRotation(180); } else { arrow.setRotation(0); } } @Override public void onPanelCollapsed(View view) { if (isPainting) { ImageView toolSignifer = (ImageView)findViewById(R.id.tool_signifier); Resources r = getResources(); float distance = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, -100, r.getDisplayMetrics()); Animation moveIn = new TranslateAnimation(distance, 0, 0, 0); moveIn.setDuration(500); switch (selectedTool) { case PAINTBRUSH: toolSignifer.setImageResource(R.drawable.paintbrush_tool_right); toolSignifer.startAnimation(moveIn); toolSignifer.invalidate(); break; case PEN: toolSignifer.setImageResource(R.drawable.pen_tool_right); toolSignifer.startAnimation(moveIn); toolSignifer.invalidate(); break; case PENCIL: toolSignifer.setImageResource(R.drawable.pencil_tool_right); toolSignifer.startAnimation(moveIn); toolSignifer.invalidate(); break; } toolSignifer.setVisibility(View.VISIBLE); View strokeSignifer = findViewById(R.id.drawer_stroke); Animation fadeIn = new AlphaAnimation(0, 1); fadeIn.setDuration(150); strokeSignifer.startAnimation(fadeIn); strokeSignifer.setVisibility(View.VISIBLE); } } @Override public void onPanelExpanded(View view) { if (isPainting) { ImageView toolSignifer = (ImageView)findViewById(R.id.tool_signifier); Resources r = getResources(); float distance = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, -100, r.getDisplayMetrics()); Animation moveOut = new TranslateAnimation(0, distance, 0, 0); moveOut.setDuration(250); toolSignifer.startAnimation(moveOut); toolSignifer.setVisibility(View.INVISIBLE); View strokeSignifer = findViewById(R.id.drawer_stroke); Animation fadeOut = new AlphaAnimation(1, 0); fadeOut.setDuration(150); strokeSignifer.startAnimation(fadeOut); findViewById(R.id.drawer_stroke).setVisibility(View.INVISIBLE); } } @Override public void onPanelAnchored(View view) { } @Override public void onPanelHidden(View view) { } } private class SaveSlideListener implements SlidingUpPanelLayout.PanelSlideListener { @Override public void onPanelSlide(View view, float v) { } @Override public void onPanelCollapsed(View view) { } @Override public void onPanelExpanded(View view) { SlidingUpPanelLayout slider = (SlidingUpPanelLayout)findViewById(R.id.sliding_layout_save); slider.setSlidingEnabled(false); } @Override public void onPanelAnchored(View view) { SlidingUpPanelLayout slider = (SlidingUpPanelLayout)findViewById(R.id.sliding_layout_save); slider.setSlidingEnabled(false); } @Override public void onPanelHidden(View view) { } } //endregion //region Event Functions @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_save) { SlidingUpPanelLayout slider = (SlidingUpPanelLayout)findViewById(R.id.sliding_layout_save); slider.setSlidingEnabled(true); slider.expandPanel(); map.setMyLocationEnabled(false); invalidateOptionsMenu(); isSaving = true; } return super.onOptionsItemSelected(item); } public void onFrameConfirm(View view) { map.snapshot(new GoogleMap.SnapshotReadyCallback() { @Override public void onSnapshotReady(Bitmap bitmap) { Bitmap croppedPainting = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getWidth()); FileOutputStream out = null; try { out = openFileOutput("currentPainting.png", Context.MODE_PRIVATE); croppedPainting.compress(Bitmap.CompressFormat.PNG, 100, out); } catch (Exception e) { e.printStackTrace(); } finally { try { if (out != null) { out.close(); } } catch (IOException e) { e.printStackTrace(); } } startActivityForResult(new Intent(MapsActivity.this, ShareActivity.class), 69); } }); } //endregion //region Painting Functions public void onEraserClicked(View view) { if (selectedTool != Tool.ERASER) { minimizeTool(getViewFromTool(selectedTool)); selectedTool = Tool.ERASER; maximizeTool(view); paintingOff(); } else { selectedTool = Tool.NONE; minimizeTool(view); paintingOff(); } } public void onPencilClicked(View view) { if (selectedTool != Tool.PENCIL) { minimizeTool(getViewFromTool(selectedTool)); selectedTool = Tool.PENCIL; maximizeTool(view); painting.setThickness(5); paintingOn(); } else { selectedTool = Tool.NONE; minimizeTool(view); paintingOff(); } } public void onPaintbrushClicked(View view) { if (selectedTool != Tool.PAINTBRUSH) { minimizeTool(getViewFromTool(selectedTool)); selectedTool = Tool.PAINTBRUSH; maximizeTool(view); painting.setThickness(20); paintingOn(); } else { selectedTool = Tool.NONE; minimizeTool(view); paintingOff(); } } public void onPenClicked(View view) { if (selectedTool != Tool.PEN) { minimizeTool(getViewFromTool(selectedTool)); selectedTool = Tool.PEN; maximizeTool(view); painting.setThickness(10); paintingOn(); } else { minimizeTool(view); selectedTool = Tool.NONE; paintingOff(); } } private View getViewFromTool(Tool tool) { switch (tool){ case ERASER: return findViewById(R.id.drawer_eraser); case PENCIL: return findViewById(R.id.drawer_pencil); case PAINTBRUSH: return findViewById(R.id.drawer_paintbrush); case PEN: return findViewById(R.id.drawer_pen); default: return null; } } private void minimizeTool(View tool){ if (tool != null) { Resources r = getResources(); float offset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, -30, r.getDisplayMetrics()); TranslateAnimation anim = new TranslateAnimation(0, 0, offset, 0); anim.setDuration(250); anim.setFillAfter(true); tool.startAnimation(anim); } } private void maximizeTool(View tool){ if (tool != null) { Resources r = getResources(); float offset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, -30, r.getDisplayMetrics()); TranslateAnimation anim = new TranslateAnimation(0, 0, 0, offset); anim.setDuration(250); anim.setFillAfter(true); tool.startAnimation(anim); } } public void paintingOff() { if (isPainting) { painting.endStroke(); isPainting = false; } } public void paintingOn() { if (!isPainting) { painting.setColor(getSelectedColor()); isPainting = true; } } private void redrawPainting() { for (Polyline line : drawnPolylines) { line.remove(); } drawnPolylines.clear(); for (Stroke stroke : painting.getStrokes()) { Polyline drawnLine = map.addPolyline( new PolylineOptions().addAll(stroke.path) .width(stroke.style.thickness) .color(stroke.style.color) .visible(true) ); drawnPolylines.add(drawnLine); } } //endregion //region Color Picker Functions public void onInkwellClicked(View view) { //The color picker menu item as been clicked. Show //a dialog using the custom ColorPickerDialog class. final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); int initialValue = prefs.getInt("color_2", 0xFF000000); System.out.println("INITIAL COLOR: " + initialValue); Log.d("mColorPicker", "initial value:" + initialValue); final ColorPickerDialog colorDialog = new ColorPickerDialog(this, initialValue); //colorDialog.setAlphaSliderVisible(true); colorDialog.setTitle("Pick a Color"); colorDialog.setButton(DialogInterface.BUTTON_POSITIVE, getString(android.R.string.ok), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //Save the value in our preferences. SharedPreferences.Editor editor = prefs.edit(); editor.putInt("color_2", colorDialog.getColor()); editor.commit(); painting.setColor(colorDialog.getColor()); findViewById(R.id.drawer_inkwell).invalidate(); findViewById(R.id.drawer_stroke).invalidate(); } }); colorDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(android.R.string.cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //Nothing to do here. } }); colorDialog.show(); } private int getSelectedColor() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); return prefs.getInt("color_2", 0xFF000000); } private String colorToHexString(int color) { return String.format("#%06X", 0xFFFFFFFF & color); } //endregion @Override public void onActivityResult(int requestCode, int resultCode, Intent data){ if (requestCode == 69 && resultCode == 100){ finish(); } } @Override public void onConnected(Bundle bundle) { Log.d("PLAYSERVICES", "Connected"); LocationRequest locationRequest = LocationRequest.create(); locationRequest.setInterval(1000); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this); } @Override public void onConnectionSuspended(int i) { Toast.makeText(getBaseContext(), "Failed to connect to Google Play Services", Toast.LENGTH_LONG).show(); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { Toast.makeText(getBaseContext(), "Failed to connect to Google Play Services", Toast.LENGTH_LONG).show(); } public void onLocationChanged(Location l) { Log.e("LLEVENT", "You moved to " + l); if (isPainting) painting.addPointToStroke(new LatLng(l.getLatitude(), l.getLongitude())); redrawPainting(); } }