Java tutorial
/* * Copyright (C) 2005-2015 Alfresco Software Limited. * * This file is part of Alfresco Mobile for Android. * * 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 org.alfresco.mobile.android.application.fragments.node.browser; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.alfresco.mobile.android.api.model.Folder; import org.alfresco.mobile.android.api.model.Node; import org.alfresco.mobile.android.api.model.impl.publicapi.PublicAPIPropertyIds; import org.alfresco.mobile.android.api.utils.NodeRefUtils; import org.alfresco.mobile.android.application.R; import org.alfresco.mobile.android.application.configuration.ConfigurableActionHelper; import org.alfresco.mobile.android.application.fragments.DisplayUtils; import org.alfresco.mobile.android.application.fragments.actions.NodeActions; import org.alfresco.mobile.android.application.fragments.node.details.NodeDetailsFragment; import org.alfresco.mobile.android.async.Operation; import org.alfresco.mobile.android.async.OperationSchema; import org.alfresco.mobile.android.async.OperationsContentProvider; import org.alfresco.mobile.android.async.node.create.CreateDocumentRequest; import org.alfresco.mobile.android.async.node.download.DownloadRequest; import org.alfresco.mobile.android.async.node.update.UpdateContentRequest; import org.alfresco.mobile.android.async.utils.NodePlaceHolder; import org.alfresco.mobile.android.platform.favorite.FavoritesProvider; import org.alfresco.mobile.android.platform.favorite.FavoritesSchema; import org.alfresco.mobile.android.platform.mimetype.MimeTypeManager; import org.alfresco.mobile.android.platform.provider.CursorUtils; import org.alfresco.mobile.android.platform.utils.AccessibilityUtils; import org.alfresco.mobile.android.platform.utils.SessionUtils; import org.alfresco.mobile.android.sync.SyncContentManager; import org.alfresco.mobile.android.sync.SyncContentProvider; import org.alfresco.mobile.android.sync.SyncContentSchema; import org.alfresco.mobile.android.sync.operations.SyncContentStatus; import org.alfresco.mobile.android.ui.ListingModeFragment; import org.alfresco.mobile.android.ui.holder.TwoLinesProgressViewHolder; import org.alfresco.mobile.android.ui.utils.UIUtils; import android.annotation.TargetApi; import android.database.Cursor; import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.PopupMenu; import android.widget.PopupMenu.OnDismissListener; import android.widget.PopupMenu.OnMenuItemClickListener; import android.widget.ProgressBar; /** * @since 1.2 * @author Jean Marie Pascal */ public class ProgressNodeAdapter extends NodeAdapter implements LoaderManager.LoaderCallbacks<Cursor>, OnMenuItemClickListener { private static final String TAG = ProgressNodeAdapter.class.getName(); private static final int LOADER_OPERATION_ID = 1; private static final int LOADER_SYNC_ID = 2; private static final int LOADER_FAVORITE_ID = 3; private static final int MAX_PROGRESS = 100; protected Node parentNode; private List<Node> selectedOptionItems = new ArrayList<Node>(); private Map<String, Node> placeHolderMap = new HashMap<String, Node>(); private Map<String, SyncInfo> syncInfos; private boolean hasSync = false, hasFavorited = false; public ProgressNodeAdapter(Fragment fr, int textViewResourceId, Node parentNode, List<Node> listItems, List<Node> selectedItems, int mode) { super(fr, textViewResourceId, listItems, selectedItems, mode); vhClassName = TwoLinesProgressViewHolder.class.getCanonicalName(); this.parentNode = parentNode; if (parentNode != null) { fr.getActivity().getSupportLoaderManager().restartLoader(LOADER_OPERATION_ID, null, this); fr.getActivity().getSupportLoaderManager().restartLoader(LOADER_SYNC_ID, null, this); fr.getActivity().getSupportLoaderManager().restartLoader(LOADER_FAVORITE_ID, null, this); hasParentFavorite(); } } public ProgressNodeAdapter(FragmentActivity context, int textViewResourceId, List<Node> listItems) { super(context, textViewResourceId, listItems); } public ProgressNodeAdapter(Fragment fr, int textViewResourceId, Node parentNode, List<Node> listItems, Map<String, Node> selectedItems, int mode) { super(fr.getActivity(), textViewResourceId, listItems, selectedItems); fragmentRef = new WeakReference<>(fr); vhClassName = TwoLinesProgressViewHolder.class.getCanonicalName(); this.parentNode = parentNode; if (parentNode != null) { getActivity().getSupportLoaderManager().restartLoader(LOADER_OPERATION_ID, null, this); getActivity().getSupportLoaderManager().restartLoader(LOADER_SYNC_ID, null, this); getActivity().getSupportLoaderManager().restartLoader(LOADER_FAVORITE_ID, null, this); hasParentFavorite(); } } // ///////////////////////////////////////////////////////////// // ITEM LINE // //////////////////////////////////////////////////////////// @Override protected void updateTopText(TwoLinesProgressViewHolder vh, Node item) { ProgressBar progressView = vh.progress; if (item instanceof NodePlaceHolder) { vh.topText.setText(item.getName()); vh.topText.setEnabled(false); long totalSize = ((NodePlaceHolder) item).getLength(); if ((Integer) item.getPropertyValue(PublicAPIPropertyIds.REQUEST_STATUS) == Operation.STATUS_PAUSED || (Integer) item .getPropertyValue(PublicAPIPropertyIds.REQUEST_STATUS) == Operation.STATUS_PENDING) { progressView.setVisibility(View.GONE); } else { progressView.setVisibility(View.VISIBLE); progressView.setIndeterminate(false); if (totalSize == -1) { progressView.setMax(MAX_PROGRESS); progressView.setProgress(0); } else { long progress = ((NodePlaceHolder) item).getProgress(); float value = (((float) progress / ((float) totalSize)) * MAX_PROGRESS); int percentage = Math.round(value); if (percentage == MAX_PROGRESS) { if ((Integer) item .getPropertyValue(PublicAPIPropertyIds.REQUEST_TYPE) == DownloadRequest.TYPE_ID) { progressView.setVisibility(View.GONE); super.updateTopText(vh, item); vh.bottomText.setVisibility(View.VISIBLE); super.updateBottomText(vh, item); super.updateIcon(vh, item); } else { progressView.setIndeterminate(true); } } else { progressView.setIndeterminate(false); progressView.setMax(MAX_PROGRESS); progressView.setProgress(percentage); } } } } else { progressView.setVisibility(View.GONE); super.updateTopText(vh, item); } } @Override protected void updateBottomText(TwoLinesProgressViewHolder vh, Node item) { if (favoritesNodeIndex != null && favoritesNodeIndex.contains(NodeRefUtils.getCleanIdentifier(item.getIdentifier()))) { vh.favoriteIcon.setVisibility(View.VISIBLE); vh.favoriteIcon.setImageResource(R.drawable.ic_favorite_light); } else { vh.favoriteIcon.setVisibility(View.GONE); } vh.syncIcon.setVisibility(View.GONE); if (hasSync && syncInfos.containsKey(NodeRefUtils.getCleanIdentifier(item.getIdentifier()))) { SyncInfo syncInfo = syncInfos.get(NodeRefUtils.getCleanIdentifier(item.getIdentifier())); if (syncInfo.isRoot == 1) { vh.syncIcon.setVisibility(View.VISIBLE); vh.syncIcon.setImageResource(R.drawable.ic_sync_light); } else { vh.syncIcon.setVisibility(View.GONE); } if (SyncContentManager.getInstance(getContext()) .hasActivateSync(SessionUtils.getAccount(getContext()))) { switch (syncInfo.status) { case SyncContentStatus.STATUS_PENDING: displayStatut(vh, R.drawable.sync_status_pending); break; case SyncContentStatus.STATUS_RUNNING: displayStatut(vh, R.drawable.sync_status_loading); break; case SyncContentStatus.STATUS_PAUSED: displayStatut(vh, R.drawable.sync_status_pending); break; case SyncContentStatus.STATUS_MODIFIED: displayStatut(vh, R.drawable.sync_status_pending); break; case SyncContentStatus.STATUS_SUCCESSFUL: displayStatut(vh, R.drawable.sync_status_success); break; case SyncContentStatus.STATUS_FAILED: displayStatut(vh, R.drawable.sync_status_failed); break; case SyncContentStatus.STATUS_CANCEL: displayStatut(vh, R.drawable.sync_status_failed); break; case SyncContentStatus.STATUS_REQUEST_USER: displayStatut(vh, R.drawable.sync_status_failed); break; default: vh.iconRight.setVisibility(View.GONE); break; } } else { vh.iconRight.setVisibility(View.GONE); } } else { vh.iconRight.setVisibility(View.GONE); } if (item instanceof NodePlaceHolder) { vh.bottomText.setEnabled(false); int status = item.getPropertyValue(PublicAPIPropertyIds.REQUEST_STATUS); if (status == Operation.STATUS_PAUSED || status == Operation.STATUS_PENDING) { vh.bottomText.setVisibility(View.VISIBLE); int resId = R.string.download_await; switch ((Integer) item.getPropertyValue(PublicAPIPropertyIds.REQUEST_TYPE)) { case DownloadRequest.TYPE_ID: resId = R.string.download_await; break; case CreateDocumentRequest.TYPE_ID: case UpdateContentRequest.TYPE_ID: resId = R.string.upload_await; break; default: break; } vh.bottomText.setText(resId); } else { vh.bottomText.setVisibility(View.GONE); } } else { vh.bottomText.setVisibility(View.VISIBLE); super.updateBottomText(vh, item); } } @Override protected void updateIcon(TwoLinesProgressViewHolder vh, Node item) { if (item instanceof NodePlaceHolder) { UIUtils.setBackground(vh.icon, null); vh.icon.setImageResource(MimeTypeManager.getInstance(getActivity()).getIcon(item.getName())); vh.choose.setVisibility(View.GONE); return; } else { super.updateIcon(vh, item); } if ((selectedItems != null && selectedItems.contains(item)) || (selectedMapItems != null && selectedMapItems.containsKey(item.getIdentifier()))) { if (getFragment() != null && getFragment() instanceof DocumentFolderBrowserFragment && ((DocumentFolderBrowserFragment) getFragment()).hasActionMode()) { vh.choose.setVisibility(View.VISIBLE); vh.choose.setImageResource(R.drawable.ic_done_single_white); int d_16 = DisplayUtils.getPixels(getContext(), R.dimen.d_16); vh.choose.setPadding(d_16, d_16, d_16, d_16); UIUtils.setBackground(vh.choose, null); vh.choose.setOnClickListener(null); } } else if (item.isFolder()) { vh.icon.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.mime_256_folder)); if (mode == ListingModeFragment.MODE_IMPORT) { return; } if (mode == ListingModeFragment.MODE_PICK) { return; } vh.choose.setImageResource(R.drawable.ic_more_options); vh.choose.setBackgroundResource(R.drawable.alfrescohololight_list_selector_holo_light); int d_16 = DisplayUtils.getPixels(getContext(), R.dimen.d_16); vh.choose.setPadding(d_16, d_16, d_16, d_16); vh.choose.setVisibility(View.VISIBLE); AccessibilityUtils.addContentDescription(vh.choose, String.format(getActivity().getString(R.string.more_options_folder), item.getName())); vh.choose.setTag(R.id.node_action, item); vh.choose.setOnClickListener(new OnClickListener() { @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Override public void onClick(View v) { Node item = (Node) v.getTag(R.id.node_action); if (item == null) { return; } selectedOptionItems.add(item); PopupMenu popup = new PopupMenu(getActivity(), v); getMenu(popup.getMenu(), item); popup.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss(PopupMenu menu) { selectedOptionItems.clear(); } }); popup.setOnMenuItemClickListener(ProgressNodeAdapter.this); popup.show(); } }); } else { UIUtils.setBackground(vh.choose, null); vh.choose.setPadding(0, 0, 0, 0); vh.choose.setVisibility(View.GONE); } } // ///////////////////////////////////////////////////////////// // INLINE PROGRESS // //////////////////////////////////////////////////////////// @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { switch (id) { case LOADER_OPERATION_ID: return new CursorLoader(getActivity(), OperationsContentProvider.CONTENT_URI, OperationSchema.COLUMN_ALL, OperationSchema.COLUMN_PARENT_ID + "=\"" + parentNode.getIdentifier() + "\" AND " + OperationSchema.COLUMN_REQUEST_TYPE + " IN(" + CreateDocumentRequest.TYPE_ID + " , " + DownloadRequest.TYPE_ID + " , " + UpdateContentRequest.TYPE_ID + ")", null, null); case LOADER_SYNC_ID: return new CursorLoader(getActivity(), SyncContentProvider.CONTENT_URI, SyncContentSchema.COLUMN_ALL, SyncContentSchema.COLUMN_PARENT_ID + " =\"" + parentNode.getIdentifier() + "\" AND " + SyncContentSchema.COLUMN_STATUS + " NOT IN (" + SyncContentStatus.STATUS_HIDDEN + ")", null, null); case LOADER_FAVORITE_ID: return new CursorLoader(getActivity(), FavoritesProvider.CONTENT_URI, FavoritesSchema.COLUMN_ALL, FavoritesSchema.COLUMN_PARENT_ID + " =\"" + parentNode.getIdentifier() + "\"", null, null); } return null; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { switch (loader.getId()) { case LOADER_SYNC_ID: hasSync = (cursor.getCount() > 0); if (syncInfos == null) { syncInfos = new HashMap<String, SyncInfo>(cursor.getCount()); } syncInfos.clear(); if (hasSync) { while (cursor.moveToNext()) { syncInfos.put( NodeRefUtils.getCleanIdentifier(cursor.getString(SyncContentSchema.COLUMN_NODE_ID_ID)), new SyncInfo(cursor)); } } notifyDataSetChanged(); break; case LOADER_FAVORITE_ID: hasFavorited = (cursor.getCount() > 0); if (favoritesNodeIndex == null) { favoritesNodeIndex = new ArrayList<>(cursor.getCount()); } favoritesNodeIndex.clear(); if (hasFavorited) { while (cursor.moveToNext()) { favoritesNodeIndex.add( NodeRefUtils.getCleanIdentifier(cursor.getString(FavoritesSchema.COLUMN_NODE_ID_ID))); } } notifyDataSetChanged(); break; case LOADER_OPERATION_ID: // Case where 0 ==> check if placeHolder present if (cursor.getCount() == 0) { for (Entry<String, Node> entryNode : placeHolderMap.entrySet()) { remove(entryNode.getValue()); } placeHolderMap.clear(); } Node placeHolder = null; while (cursor.moveToNext()) { int status = cursor.getInt(OperationSchema.COLUMN_STATUS_ID); String name = cursor.getString(OperationSchema.COLUMN_TITLE_ID); int type = cursor.getInt(OperationSchema.COLUMN_REQUEST_TYPE_ID); // Log.d("UI", "[Update]" + name + "/" + status); switch (status) { case Operation.STATUS_PAUSED: case Operation.STATUS_PENDING: // Add Node if not present if (name != null && !hasNode(name)) { // Log.d("UI", "[Init Placeholder]" + name); placeHolder = new NodePlaceHolder(name, type, status); placeHolderMap.put(name, placeHolder); replaceNode(placeHolder); } break; case Operation.STATUS_RUNNING: // Update node if not present long progress = cursor.getLong(OperationSchema.COLUMN_BYTES_DOWNLOADED_SO_FAR_ID); long totalSize = cursor.getLong(OperationSchema.COLUMN_TOTAL_SIZE_BYTES_ID); if (name != null) { // Log.d("UI", "[Update Placeholder]" + name + // " : " + progress + "/" + totalSize); placeHolder = new NodePlaceHolder(name, type, status, totalSize, progress); placeHolderMap.put(name, placeHolder); replaceNode(placeHolder); } break; case Operation.STATUS_SUCCESSFUL: Log.d("UI", "[Update Sucess]" + name); // Update node if not present if (type != DownloadRequest.TYPE_ID && hasNode(name) && getNode(name) instanceof NodePlaceHolder) { notifyDataSetChanged(); } else if (hasNode(name) && getNode(name) instanceof NodePlaceHolder) { remove(name); } break; default: if (hasNode(name) && getNode(name) instanceof NodePlaceHolder) { remove(name); } break; } } break; default: break; } } @Override public void onLoaderReset(Loader<Cursor> arg0) { // DO Nothing } // /////////////////////////////////////////////////////////////////////////// // MENU // /////////////////////////////////////////////////////////////////////////// public void getMenu(Menu menu, Node node) { MenuItem mi; mi = menu.add(Menu.NONE, R.id.menu_node_details, Menu.FIRST, R.string.action_view_properties); mi.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); if (ConfigurableActionHelper.isVisible(getActivity(), SessionUtils.getAccount(getActivity()), SessionUtils.getSession(getActivity()), node, ConfigurableActionHelper.ACTION_NODE_EDIT)) { mi = menu.add(Menu.NONE, R.id.menu_action_edit, Menu.FIRST + 50, R.string.action_edit_properties); mi.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); } if (ConfigurableActionHelper.isVisible(getActivity(), SessionUtils.getAccount(getActivity()), SessionUtils.getSession(getActivity()), node, ConfigurableActionHelper.ACTION_NODE_DELETE)) { mi = menu.add(Menu.NONE, R.id.menu_action_delete_folder, Menu.FIRST + 1000, R.string.delete); mi.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); } } @Override public boolean onMenuItemClick(MenuItem item) { boolean onMenuItemClick = true; switch (item.getItemId()) { case R.id.menu_node_details: onMenuItemClick = true; NodeDetailsFragment.with(getActivity()).node(selectedOptionItems.get(0)).display(); if (DisplayUtils.hasCentralPane(getActivity())) { selectedItems.add(selectedOptionItems.get(0)); } notifyDataSetChanged(); break; case R.id.menu_action_edit: onMenuItemClick = true; NodeActions.edit(getActivity(), (Folder) parentNode, selectedOptionItems.get(0)); break; case R.id.menu_action_delete_folder: onMenuItemClick = true; Fragment fr = getActivity().getSupportFragmentManager() .findFragmentByTag(DocumentFolderBrowserFragment.TAG); NodeActions.delete(getActivity(), fr, selectedOptionItems.get(0)); break; default: onMenuItemClick = false; break; } selectedOptionItems.clear(); return onMenuItemClick; } // /////////////////////////////////////////////////////////////////////////// // FAVORITES // /////////////////////////////////////////////////////////////////////////// public void refreshOperations() { if (parentNode != null) { getActivity().getSupportLoaderManager().restartLoader(LOADER_OPERATION_ID, null, this); getActivity().getSupportLoaderManager().restartLoader(LOADER_SYNC_ID, null, this); getActivity().getSupportLoaderManager().restartLoader(LOADER_FAVORITE_ID, null, this); notifyDataSetChanged(); } } private static class SyncInfo { long id; String nodeIdentifier; int status; int isRoot; public SyncInfo(Cursor syncCursor) { this.id = syncCursor.getLong(SyncContentSchema.COLUMN_NODE_ID_ID); this.nodeIdentifier = syncCursor.getString(SyncContentSchema.COLUMN_NODE_ID_ID); this.status = syncCursor.getInt(SyncContentSchema.COLUMN_STATUS_ID); this.isRoot = syncCursor.getInt(SyncContentSchema.COLUMN_IS_SYNC_ROOT_ID); } } public boolean hasParentFavorite() { Cursor parentCursorId = null; boolean isSyncFolder = false; try { parentCursorId = SyncContentManager.getCursorForId(getActivity(), SessionUtils.getAccount(getContext()), parentNode.getIdentifier()); if (parentCursorId.getCount() == 1 && parentCursorId.moveToFirst()) { isSyncFolder = true; } } catch (Exception e) { // do nothing } finally { CursorUtils.closeCursor(parentCursorId); } return isSyncFolder; } protected void displayStatut(TwoLinesProgressViewHolder vh, int imageResource) { if (vh.iconRight != null) { vh.iconRight.setVisibility(View.VISIBLE); vh.iconRight.setImageResource(imageResource); } } }