Java tutorial
/* * Everychan Android (Meta Imageboard Client) * Copyright (C) 2014-2016 miku-nyan <https://github.com/miku-nyan> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 program. If not, see <http://www.gnu.org/licenses/>. */ package com.nttec.everychan.ui.tabs; import com.nttec.everychan.R; import com.nttec.everychan.api.ChanModule; import com.nttec.everychan.common.MainApplication; import com.nttec.everychan.ui.HistoryFragment; import com.nttec.everychan.ui.theme.ThemeUtils; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.support.v4.content.res.ResourcesCompat; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; public class TabsAdapter extends ArrayAdapter<TabModel> { private final LayoutInflater inflater; private final Context context; private final TabsState tabsState; private final TabsIdStack tabsIdStack; private final TabSelectListener selectListener; private int selectedItem; private int draggingItem = -1; private final View.OnClickListener onCloseClick = new View.OnClickListener() { @Override public void onClick(View v) { closeTab((Integer) v.getTag()); } }; /** * ? . * ? ?? ? ?? ? ({@link #setSelectedItem(int)}) * @param context ? ? ? ? (??) * @param tabsState ???? * @param selectListener ? {@link TabSelectListener}, ? ? (?) */ public TabsAdapter(Context context, TabsState tabsState, TabSelectListener selectListener) { super(context, 0, tabsState.tabsArray); this.inflater = LayoutInflater.from(context); this.context = context; this.tabsState = tabsState; this.tabsIdStack = tabsState.tabsIdStack; this.selectListener = selectListener; } /** * ( ?? ). ???? ? * @param position ? ?? */ public void setSelectedItem(int position) { setSelectedItem(position, true); } /** * ( ?? ) * @param position ? ?? * @param serialize ? true, ? ???? */ public void setSelectedItem(int position, boolean serialize) { selectedItem = position; tabsState.position = position; if (position >= 0) { tabsIdStack.addTab(getItem(position).id); } notifyDataSetChanged(serialize); selectListener.onTabSelected(position); } /** * ( ?? ) ? ? ID * @param id ID */ public void setSelectedItemId(long id) { for (int i = 0; i < getCount(); ++i) { if (getItem(i).id == id) { setSelectedItem(i); break; } } } /** * ? ? * @param position ? ?? -1, ? ? */ public void setDraggingItem(int position) { draggingItem = position; notifyDataSetChanged(false); } /** * @return */ public int getSelectedItem() { return selectedItem; } /** * @return (? ?) * -1, ? */ public int getDraggingItem() { return draggingItem; } /** * * @param position ? ?? */ public void closeTab(int position) { setDraggingItem(-1); if (position >= getCount()) return; HistoryFragment.setLastClosed(tabsState.tabsArray.get(position)); tabsIdStack.removeTab(getItem(position).id); remove(getItem(position), false); if (position == selectedItem) { if (!tabsIdStack.isEmpty()) { setSelectedItemId(tabsIdStack.getCurrentTab()); } else { if (getCount() == 0) { setSelectedItem(TabModel.POSITION_NEWTAB); } else { if (getCount() <= position) --position; setSelectedItem(position); //serialize } } } else { if (position < selectedItem) --selectedItem; setSelectedItem(selectedItem); //serialize } } /** * ? ? "?" * @return */ public boolean back() { if (selectedItem < 0) { if (!tabsIdStack.isEmpty()) { setSelectedItemId(tabsIdStack.getCurrentTab()); return true; } } else { if (MainApplication.getInstance().settings.doNotCloseTabs()) { tabsIdStack.removeTab(getItem(selectedItem).id); if (tabsIdStack.isEmpty()) { setSelectedItem(TabModel.POSITION_NEWTAB); } else { setSelectedItemId(tabsIdStack.getCurrentTab()); } } else { closeTab(selectedItem); } return true; } return false; } @Override public View getView(final int position, View convertView, ViewGroup parent) { View view = convertView == null ? inflater.inflate(R.layout.sidebar_tabitem, parent, false) : convertView; View dragHandler = view.findViewById(R.id.tab_drag_handle); ImageView favIcon = (ImageView) view.findViewById(R.id.tab_favicon); TextView title = (TextView) view.findViewById(R.id.tab_text_view); ImageView closeBtn = (ImageView) view.findViewById(R.id.tab_close_button); dragHandler.getLayoutParams().width = position == draggingItem ? ViewGroup.LayoutParams.WRAP_CONTENT : 0; dragHandler.setLayoutParams(dragHandler.getLayoutParams()); if (position == selectedItem) { TypedValue typedValue = ThemeUtils.resolveAttribute(context.getTheme(), R.attr.sidebarSelectedItem, true); if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT && typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) { view.setBackgroundColor(typedValue.data); } else { view.setBackgroundResource(typedValue.resourceId); } } else { view.setBackgroundColor(Color.TRANSPARENT); } TabModel model = this.getItem(position); switch (model.type) { case TabModel.TYPE_NORMAL: case TabModel.TYPE_LOCAL: closeBtn.setVisibility(View.VISIBLE); String titleText = model.title; if (model.unreadPostsCount > 0 || model.autoupdateError) { StringBuilder titleStringBuilder = new StringBuilder(); if (model.unreadSubscriptions) titleStringBuilder.append("[*] "); if (model.autoupdateError) titleStringBuilder.append("[X] "); if (model.unreadPostsCount > 0) titleStringBuilder.append('[').append(model.unreadPostsCount).append("] "); titleText = titleStringBuilder.append(titleText).toString(); } title.setText(titleText); ChanModule chan = MainApplication.getInstance().getChanModule(model.pageModel.chanName); Drawable icon = chan != null ? chan.getChanFavicon() : ResourcesCompat.getDrawable(context.getResources(), android.R.drawable.ic_delete, null); if (icon != null) { if (model.type == TabModel.TYPE_LOCAL) { Drawable[] layers = new Drawable[] { icon, ResourcesCompat.getDrawable(context.getResources(), R.drawable.favicon_overlay_local, null) }; icon = new LayerDrawable(layers); } /* XXX ? ( overlay favicon ), ? ?? , , ( ). ? ? ? , , ? -? - , ?. ?? ?, ? ? . else if (model.type == TabModel.TYPE_NORMAL && model.pageModel != null && model.pageModel.type == UrlPageModel.TYPE_THREADPAGE && model.autoupdateBackground && MainApplication.getInstance().settings.isAutoupdateEnabled() && MainApplication.getInstance().settings.isAutoupdateBackground()) { Drawable[] layers = new Drawable[] { icon, ResourcesCompat.getDrawable(context.getResources(), R.drawable.favicon_overlay_autoupdate, null) }; icon = new LayerDrawable(layers); } */ favIcon.setImageDrawable(icon); favIcon.setVisibility(View.VISIBLE); } else { favIcon.setVisibility(View.GONE); } break; default: closeBtn.setVisibility(View.GONE); title.setText(R.string.error_deserialization); favIcon.setVisibility(View.GONE); } closeBtn.setTag(position); closeBtn.setOnClickListener(onCloseClick); return view; } @Override public void notifyDataSetChanged() { notifyDataSetChanged(true); } /** * @param serialize ? true, ? ???? */ public void notifyDataSetChanged(boolean serialize) { super.notifyDataSetChanged(); if (serialize) MainApplication.getInstance().serializer.serializeTabsState(tabsState); } @Override public void add(TabModel object) { add(object, true); } /** * ?? * @param object * @param serialize ? true, ? ???? */ public void add(TabModel object, boolean serialize) { setNotifyOnChange(false); super.add(object); notifyDataSetChanged(serialize); } @Override public void remove(TabModel object) { remove(object, true); } /** * ?? * @param object * @param serialize ? true, ? ???? */ public void remove(TabModel object, boolean serialize) { setNotifyOnChange(false); super.remove(object); notifyDataSetChanged(serialize); } @Override public void insert(TabModel object, int index) { insert(object, index, true); } /** * ? ?? (?) * @param object * @param index ?, ? * @param serialize ? true, ? ???? */ public void insert(TabModel object, int index, boolean serialize) { setNotifyOnChange(false); super.insert(object, index); notifyDataSetChanged(serialize); } /** * ?, ? ? (?) . * @author miku-nyan * */ public static interface TabSelectListener { /** ?? . * ? ( ) , , ??. */ public void onTabSelected(int position); } }