/*
* AndFHEM - Open Source Android application to control a FHEM home automation
* server.
*
* Copyright (c) 2011, Matthias Klass or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU GENERAL PUBLIC LICENSE, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU GENERAL PUBLIC LICENSE
* for more details.
*
* You should have received a copy of the GNU GENERAL PUBLIC LICENSE
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package li.klass.fhem.fragments.core;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewCompat;
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 java.io.Serializable;
import li.klass.fhem.AndFHEMApplication;
import li.klass.fhem.R;
import li.klass.fhem.activities.core.Updateable;
import li.klass.fhem.constants.Actions;
import li.klass.fhem.dagger.ApplicationComponent;
import li.klass.fhem.error.ErrorHolder;
import li.klass.fhem.service.intent.DeviceIntentService;
import li.klass.fhem.widget.SwipeRefreshLayout;
import static li.klass.fhem.constants.Actions.CONNECTION_ERROR;
import static li.klass.fhem.constants.Actions.CONNECTION_ERROR_HIDE;
import static li.klass.fhem.constants.Actions.RESEND_LAST_FAILED_COMMAND;
import static li.klass.fhem.constants.Actions.TOP_LEVEL_BACK;
import static li.klass.fhem.constants.BundleExtraKeys.STRING;
import static li.klass.fhem.constants.BundleExtraKeys.STRING_ID;
public abstract class BaseFragment extends Fragment implements
Updateable, Serializable, SwipeRefreshLayout.ChildScrollDelegate {
private boolean isNavigation = false;
private transient UIBroadcastReceiver broadcastReceiver;
private transient View contentView;
private boolean backPressCalled = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
inject(((AndFHEMApplication) getActivity().getApplication()).getDaggerComponent());
}
protected abstract void inject(ApplicationComponent applicationComponent);
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button retryButton = (Button) view.findViewById(R.id.retry);
if (retryButton != null) {
retryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
hideConnectionError();
Intent resendIntent = new Intent(RESEND_LAST_FAILED_COMMAND);
resendIntent.setClass(getActivity(), DeviceIntentService.class);
getActivity().startService(resendIntent);
}
});
}
}
@Override
public boolean canChildScrollUp() {
if (!mayPullToRefresh()) {
return true;
}
return ViewCompat.canScrollVertically(getView(), -1);
}
@Override
public void update(boolean refresh) {
hideConnectionError();
updateInternal(refresh);
}
private void hideConnectionError() {
if (isNavigation) return;
View view = getView();
if (view == null) return;
View errorLayout = view.findViewById(R.id.errorLayout);
if (errorLayout == null) return;
errorLayout.setVisibility(View.GONE);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return contentView;
}
@Override
public void onResume() {
super.onResume();
if (broadcastReceiver == null) {
broadcastReceiver = new UIBroadcastReceiver(getActivity());
}
broadcastReceiver.attach();
if (contentView != null) {
contentView.clearFocus();
}
backPressCalled = false;
update(false);
}
@Override
public void onPause() {
contentView = getView();
super.onPause();
}
@Override
public void onDetach() {
super.onDetach();
if (broadcastReceiver != null) {
broadcastReceiver.detach();
broadcastReceiver = null;
}
}
public void onBackPressResult() {
update(false);
}
public void invalidate() {
View view = getView();
if (view != null) {
view.invalidate();
view.requestLayout();
}
}
public boolean isNavigation() {
return isNavigation;
}
public void setNavigation(boolean isNavigation) {
this.isNavigation = isNavigation;
}
protected void hideEmptyView() {
View view = getView();
if (view != null) {
View emptyView = view.findViewById(R.id.emptyView);
if (emptyView == null) return;
emptyView.setVisibility(View.GONE);
}
}
protected void showEmptyView() {
if (isNavigation || getView() == null) return;
View emptyView = getView().findViewById(R.id.emptyView);
if (emptyView == null) return;
emptyView.setVisibility(View.VISIBLE);
}
protected void fillEmptyView(LinearLayout view, int text, ViewGroup container) {
if (text != 0) {
View emptyView = LayoutInflater.from(getActivity()).inflate(R.layout.empty_view, container, false);
assert emptyView != null;
TextView emptyText = (TextView) emptyView.findViewById(R.id.emptyText);
emptyText.setText(text);
view.addView(emptyView);
}
}
private void showConnectionError(String content) {
if (isNavigation) return;
View view = getView();
if (view == null) return;
View errorLayout = view.findViewById(R.id.errorLayout);
if (errorLayout == null) return;
errorLayout.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
ErrorHolder.sendLastErrorAsMail(getActivity());
return true;
}
});
errorLayout.setVisibility(View.VISIBLE);
TextView errorView = (TextView) view.findViewById(R.id.errorView);
errorView.setText(content);
}
protected boolean mayUpdateFromBroadcast() {
return true;
}
protected boolean mayPullToRefresh() {
return true;
}
private void updateInternal(boolean doRefresh) {
if (mayUpdateFromBroadcast()) {
update(doRefresh);
}
}
public class UIBroadcastReceiver extends BroadcastReceiver {
private final IntentFilter intentFilter;
private FragmentActivity activity;
public UIBroadcastReceiver(FragmentActivity activity) {
this.activity = activity;
intentFilter = new IntentFilter();
intentFilter.addAction(TOP_LEVEL_BACK);
intentFilter.addAction(CONNECTION_ERROR);
intentFilter.addAction(CONNECTION_ERROR_HIDE);
}
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.v(UIBroadcastReceiver.class.getName(), "received action " + action);
if (action == null) return;
try {
if (action.equals(TOP_LEVEL_BACK)) {
if (!isVisible()) return;
if (!backPressCalled) {
backPressCalled = true;
onBackPressResult();
}
} else if (action.equals(CONNECTION_ERROR)) {
String content;
if (intent.hasExtra(STRING_ID)) {
content = context.getString(intent.getIntExtra(STRING_ID, -1));
} else {
content = intent.getStringExtra(STRING);
}
showConnectionError(content);
} else if (action.equals(CONNECTION_ERROR_HIDE)) {
hideConnectionError();
}
} catch (Exception e) {
Log.e(UIBroadcastReceiver.class.getName(), "error occurred", e);
}
}
});
}
public void attach() {
activity.registerReceiver(this, intentFilter);
}
public void detach() {
try {
activity.unregisterReceiver(this);
} catch (IllegalArgumentException e) {
Log.e(UIBroadcastReceiver.class.getName(), "error while detaching", e);
}
}
}
public CharSequence getTitle(Context context) {
return null;
}
protected void back() {
Intent intent = new Intent(Actions.BACK);
getActivity().sendBroadcast(intent);
}
}