/* * Copyright (C) 2014 The Android Open Source Project * * 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 it.angelic.soulissclient.fragments; import android.Manifest; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Looper; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CollapsingToolbarLayout; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.ActivityCompat; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.io.File; import java.sql.SQLDataException; import java.util.HashSet; import java.util.Set; import java.util.Stack; import it.angelic.soulissclient.Constants; import it.angelic.soulissclient.R; import it.angelic.soulissclient.SoulissApp; import it.angelic.soulissclient.TagDetailActivity; import it.angelic.soulissclient.adapters.TagDetailParallaxExenderAdapter; import it.angelic.soulissclient.helpers.AlertDialogHelper; import it.angelic.soulissclient.helpers.SoulissPreferenceHelper; import it.angelic.soulissclient.model.ISoulissObject; import it.angelic.soulissclient.model.SoulissModelException; import it.angelic.soulissclient.model.SoulissTag; import it.angelic.soulissclient.model.SoulissTypical; import it.angelic.soulissclient.model.db.SoulissDBHelper; import it.angelic.soulissclient.model.db.SoulissDBTagHelper; import it.angelic.soulissclient.net.UDPHelper; import it.angelic.soulissclient.util.FontAwesomeUtil; import it.angelic.soulissclient.util.SoulissUtils; /** * Demonstrates the use of {@link android.support.v7.widget.RecyclerView} with a {@link android.support.v7.widget.LinearLayoutManager} and a * {@link android.support.v7.widget.GridLayoutManager}. */ public class TagDetailFragment extends AbstractTypicalFragment implements AppBarLayout.OnOffsetChangedListener { private static final String TAG = "RecyclerViewFragment"; private static final String KEY_LAYOUT_MANAGER = "layoutManager"; private static final int SPAN_COUNT = 2; private static final int SPAN_COUNT_LAND = 3; protected LayoutManagerType mCurrentLayoutManagerType; protected RecyclerView mRecyclerView; protected TagDetailParallaxExenderAdapter parallaxExtAdapter; private AppBarLayout appBarLayout; private CollapsingToolbarLayout collapseToolbar; private SoulissTag collectedTag; private SoulissDBTagHelper datasource; private FloatingActionButton fab; private ImageView infoAlpha; private TextView mLogoIcon; private ImageView mLogoImg; private SoulissPreferenceHelper opzioni; private SwipeRefreshLayout swipeLayout; private long tagId; // Aggiorna il feedback private BroadcastReceiver datareceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "Broadcast received, refresh from DB"); swipeLayout.setRefreshing(false); SoulissDBHelper.open(); initDataset(getActivity()); parallaxExtAdapter.setData(collectedTag); parallaxExtAdapter.notifyDataSetChanged(); mRecyclerView.invalidate(); } }; private TextView tagTitle; /** * Generates Strings for RecyclerView's adapter. This data would usually come * from a local content provider or remote server. */ private void initDataset(Context ctx) { datasource = new SoulissDBTagHelper(ctx); SoulissDBHelper.open(); try { collectedTag = datasource.getTag(tagId); } catch (SQLDataException e) { Log.e(Constants.TAG, "CANT LOAD tagId" + tagId); } Log.i(Constants.TAG, "initDataset loaded TAG" + tagId + " with father ID: " + collectedTag.getFatherId()); if (!opzioni.isDbConfigured()) AlertDialogHelper.dbNotInitedDialog(ctx); } @Override public void onCreate(Bundle savedInstanceState) { opzioni = SoulissApp.getOpzioni(); if (opzioni.isLightThemeSelected()) getActivity().setTheme(R.style.LightThemeSelector); else getActivity().setTheme(R.style.DarkThemeSelector); super.onCreate(savedInstanceState); Bundle extras = getActivity().getIntent().getExtras(); // recuper nodo da extra if (extras != null && extras.get("TAG") != null) tagId = (long) extras.get("TAG"); initDataset(getActivity()); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.addchildtagctx_menu, menu); Log.i(Constants.TAG, "Inflated add child menu"); // super.onCreateOptionsMenu(menu, inflater); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.recycler_view_frag, container, false); rootView.setTag(TAG); setHasOptionsMenu(true); Log.i(Constants.TAG, "onCreateView with size of data:" + collectedTag.getAssignedTypicals().size()); appBarLayout = (AppBarLayout) getActivity().findViewById(R.id.appBar_layout); swipeLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeRefreshContainer); swipeLayout.setColorSchemeResources(R.color.std_blue, R.color.std_blue_shadow); // BEGIN_INCLUDE(initializeRecyclerView) mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView); swipeLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeRefreshContainer); mCurrentLayoutManagerType = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? LayoutManagerType.LAND_LAYOUT_MANAGER : LayoutManagerType.PORT_LAYOUT_MANAGER; setRecyclerViewLayoutManager(mCurrentLayoutManagerType); //HEADER // shared trans su queste mLogoIcon = (TextView) getActivity().findViewById(R.id.imageTagIconFAwe); infoAlpha = (ImageView) getActivity().findViewById(R.id.infoAlpha); mLogoImg = (ImageView) getActivity().findViewById(R.id.photo); parallaxExtAdapter = new TagDetailParallaxExenderAdapter(opzioni, (TagDetailActivity) getActivity(), collectedTag, tagId); if (collectedTag.getIconResourceId() != 0) { FontAwesomeUtil.prepareFontAweTextView(getActivity(), mLogoIcon, collectedTag.getIconResourceId()); } else FontAwesomeUtil.prepareFontAweTextView(getActivity(), mLogoIcon, "fa-tag"); TypedValue a = new TypedValue(); getActivity().getTheme().resolveAttribute(android.R.attr.windowBackground, a, true); if (a.type >= TypedValue.TYPE_FIRST_COLOR_INT && a.type <= TypedValue.TYPE_LAST_COLOR_INT) { // windowBackground is a color int color = a.data; mLogoIcon.setTextColor(color); } else { // windowBackground is not a color, probably a drawable //Drawable d = getActivity().getResources().getDrawable(a.resourceId); Log.w(Constants.TAG, "not getting window background"); } //mLogoIcon.setTextColor(getActivity().getResources().getColor(R.color.white)); tagTitle = (TextView) getActivity().findViewById(R.id.tagTextView); collapseToolbar = (CollapsingToolbarLayout) getActivity().findViewById(R.id.Collapselayout); fab = (FloatingActionButton) getActivity().findViewById(R.id.fabTag); //EDIT TAG fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AlertDialog.Builder alert = AlertDialogHelper.renameSoulissObjectDialog(getActivity(), tagTitle, null, datasource, collectedTag); alert.show(); } }); fab.hide(); fab.postDelayed(new Runnable() { @Override public void run() { fab.show(); } }, 500); swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { new Thread(new Runnable() { @Override public void run() { Looper.prepare(); Set<Short> alreadyRequested = new HashSet<>(); for (SoulissTypical typ : collectedTag.getAssignedTypicals()) { if (!alreadyRequested.contains(typ.getNodeId())) { UDPHelper.pollRequest(opzioni, 1, typ.getNodeId()); alreadyRequested.add(Short.valueOf(typ.getNodeId())); } } //Avvisa solo if (!opzioni.isSoulissReachable()) { getActivity().runOnUiThread(new Runnable() { public void run() { Toast.makeText(getActivity(), getString(R.string.status_souliss_notreachable), Toast.LENGTH_SHORT) .show(); swipeLayout.setRefreshing(false); } }); } } }).start(); } }); swipeLayout.setColorSchemeResources(R.color.std_blue, R.color.std_blue_shadow); if (tagTitle != null && collectedTag != null) { setTitleBar(); } if (collectedTag != null && collectedTag.getImagePath() != null) { try { if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { File picture = new File(SoulissUtils.getRealPathFromURI(getActivity(), Uri.parse(collectedTag.getImagePath()))); if (picture.exists()) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; Bitmap myBitmap = BitmapFactory.decodeFile(picture.getAbsolutePath(), options); if (myBitmap.getHeight() > mRecyclerView.getWidth()) myBitmap = Bitmap.createScaledBitmap(myBitmap, myBitmap.getWidth() / 2, myBitmap.getHeight() / 2, true); // Log.i(Constants.TAG, "bitmap size " + myBitmap.getRowBytes()); mLogoImg.setImageBitmap(myBitmap); } } else { ActivityCompat.requestPermissions(getActivity(), new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, Constants.MY_PERMISSIONS_READ_EXT_STORAGE); //img di default } } catch (Exception e) { Log.d(TAG, "can't set logo", e); } } registerForContextMenu(mRecyclerView); return rootView; } private void setTitleBar() { StringBuilder header = new StringBuilder(); Stack<String> path = new Stack<>(); Long fatherIt = collectedTag.getFatherId(); while (!(fatherIt == null)) { try { SoulissTag father = datasource.getTag(fatherIt); path.push(father.getNiceName() + " > "); fatherIt = father.getFatherId();//vai al nonno } catch (SQLDataException | NullPointerException e) { e.printStackTrace(); fatherIt = null; } } while (!path.isEmpty()) { header.append(path.pop()); } header.append(collectedTag.getNiceName()); header.append("\n"); header.append(getActivity().getResources().getQuantityString(R.plurals.Devices, collectedTag.getAssignedTypicals().size(), collectedTag.getAssignedTypicals().size())); header.append(" - "); header.append(getActivity().getResources().getQuantityString(R.plurals.SubTags, collectedTag.getAssignedTypicals().size(), collectedTag.getChildTags().size())); tagTitle.setText(header.toString()); // tagTitle.setText(collectedTag.getNiceName()); collapseToolbar.setTitle(collectedTag.getNiceName()); } @Override public void onOffsetChanged(AppBarLayout appBarLayout, int i) { //The Refresh must be only active when the offset is zero : swipeLayout.setEnabled(i == 0); } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.aggiungiFiglio: long nuovoFiglioId = datasource.createOrUpdateTag(null); try { SoulissTag figlio = datasource.getTag(nuovoFiglioId); figlio.setFatherId(collectedTag.getTagId()); collectedTag.getChildTags().add(figlio); datasource.createOrUpdateTag(collectedTag); } catch (SQLDataException e) { e.printStackTrace(); } parallaxExtAdapter.notifyItemInserted(collectedTag.getChildTags().size() - 1); return true; } //home e altro nel activity return getActivity().onOptionsItemSelected(item); } @Override public void onPause() { super.onPause(); getActivity().unregisterReceiver(datareceiver); appBarLayout.removeOnOffsetChangedListener(this); } @Override public void onResume() { super.onResume(); IntentFilter filtere = new IntentFilter(); filtere.addAction("it.angelic.soulissclient.GOT_DATA"); filtere.addAction(Constants.CUSTOM_INTENT_SOULISS_RAWDATA); getActivity().registerReceiver(datareceiver, filtere); appBarLayout.addOnOffsetChangedListener(this); } @Override public void onSaveInstanceState(Bundle savedInstanceState) { // Save currently selected layout manager. savedInstanceState.putSerializable(KEY_LAYOUT_MANAGER, mCurrentLayoutManagerType); super.onSaveInstanceState(savedInstanceState); } @Override public void onStart() { super.onStart(); refreshStatusIcon(); Log.i(Constants.TAG, "mCurrentLayoutManagerType: " + mCurrentLayoutManagerType); // Set CustomAdapter as the adapter for RecyclerView. mRecyclerView.setAdapter(parallaxExtAdapter); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && opzioni.isAnimationsEnabled()) { Log.d(Constants.TAG, "onStart() setting setTransitionName for detail frag:" + collectedTag.getTagId()); mLogoImg.setTransitionName("photo_hero" + collectedTag.getTagId()); infoAlpha.setTransitionName("shadow_hero" + collectedTag.getTagId()); mLogoIcon.setTransitionName("tag_hero" + collectedTag.getTagId()); fab.setTransitionName("fab_hero"); } // Extend the Callback class ItemTouchHelper.Callback launcherCallback = new TagDetailFragment.ParallaxGridCallback(getActivity(), parallaxExtAdapter, datasource, collectedTag); // Create an `ItemTouchHelper` and attach it to the `RecyclerView` ItemTouchHelper ith = new ItemTouchHelper(launcherCallback); ith.attachToRecyclerView(mRecyclerView); //spiega di sbloccare a render finito scheduleStartPostponedTransition(mRecyclerView); } /** * Set RecyclerView's LayoutManager to the one given. * * @param layoutManagerType Type of layout manager to switch to. */ public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) { int scrollPosition = 0; // If a layout manager has already been set, get current scroll position. /* TENGO QUESTO CODICE PER RIFERIMENTO uso solo GridLayoutManager }*/ GridLayoutManager mTagTypicalsLayoutManager; switch (layoutManagerType) { case LAND_LAYOUT_MANAGER: mTagTypicalsLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT_LAND); mCurrentLayoutManagerType = LayoutManagerType.LAND_LAYOUT_MANAGER; break; case PORT_LAYOUT_MANAGER://OCCHIO OVERRIDE GRID mTagTypicalsLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT); mCurrentLayoutManagerType = LayoutManagerType.LAND_LAYOUT_MANAGER; break; default: throw new SoulissModelException("NON CONTEMPLATO"); //mTagTypicalsLayoutManager = new LinearLayoutManager(getActivity()); //mCurrentLayoutManagerType = LayoutManagerType.PORT_LAYOUT_MANAGER; } mTagTypicalsLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { switch (parallaxExtAdapter.getItemViewType(position)) { case TagDetailParallaxExenderAdapter.VIEW_TYPE_TAG_TYPICAL: return 2; case TagDetailParallaxExenderAdapter.VIEW_TYPE_TAG_NESTED: return 1; default: return -1; } } }); mRecyclerView.setLayoutManager(mTagTypicalsLayoutManager); mRecyclerView.scrollToPosition(scrollPosition); } private enum LayoutManagerType { LAND_LAYOUT_MANAGER, PORT_LAYOUT_MANAGER } private static class ParallaxGridCallback extends ItemTouchHelper.Callback { private final TagDetailParallaxExenderAdapter adapter; private final Context context; //View.OnClickListener mOnClickListener; private SoulissDBTagHelper database; private SoulissTag targetTag; public ParallaxGridCallback(Context xct, final TagDetailParallaxExenderAdapter adapter, SoulissDBTagHelper database, final SoulissTag targetTag) { this.adapter = adapter; this.context = xct; this.database = database; this.targetTag = targetTag; } //defines the enabled move directions in each state (idle, swiping, dragging). @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.START | ItemTouchHelper.END; int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); } //and in your imlpementaion of public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { // coi subtag volutamente non funziona try { adapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition()); //nel ordine del adapter aggiorno tutti senza complimenti database.updateTagTypicalsOrder(adapter.getItems(), targetTag); } catch (SoulissModelException e) { Log.i(Constants.TAG, "User tried to swap incompatible tag elements"); } return true; } @Override public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) { final int deletedPosition = viewHolder.getAdapterPosition(); final ISoulissObject toRemove = adapter.getItems().get(deletedPosition); Log.w(Constants.TAG, "Removing TAG:" + toRemove.getNiceName()); AlertDialog.Builder alert = new AlertDialog.Builder(context); alert.setTitle(R.string.removeTag); alert.setIcon(android.R.drawable.ic_dialog_alert); alert.setMessage(R.string.sureToRemoveTag); alert.setPositiveButton(context.getString(android.R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { adapter.removeAt(deletedPosition); // launcherMainAdapter.notifyItemRemoved(viewHolder.getAdapterPosition()); //clearView(mRecyclerView, viewHolder); if (toRemove instanceof SoulissTypical) { database.deleteTagTypical(targetTag.getTagId(), ((SoulissTypical) toRemove).getNodeId(), ((SoulissTypical) toRemove).getSlot()); } else if (toRemove instanceof SoulissTag) { database.deleteTag((SoulissTag) toRemove); } else throw new SoulissModelException("UNIMPLEMENTED STRUCTURAL ERROR"); } }); alert.setNegativeButton(context.getResources().getString(android.R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { Log.w(Constants.TAG, "Remove canceled"); adapter.notifyItemChanged(deletedPosition); } }); alert.show(); } } }