1 package org.coolreader.crengine;
2 
3 import android.database.DataSetObserver;
4 import android.os.Bundle;
5 import android.view.LayoutInflater;
6 import android.view.View;
7 import android.view.ViewGroup;
8 import android.widget.BaseAdapter;
9 import android.widget.ImageView;
10 import android.widget.ListView;
11 import android.widget.TextView;
12 
13 import org.coolreader.R;
14 
15 import java.util.ArrayList;
16 
17 public class TOCDlg extends BaseDialog {
18 	//CoolReader mCoolReader;
19 	ReaderView mReaderView;
20 	TOCItem mTOC;
21 	ListView mListView;
22 	int mCurrentPage;
23 	TOCItem mCurrentPageItem;
24 	ArrayList<TOCItem> mItems = new ArrayList<>();
25 	private LayoutInflater mInflater;
26 
initItems( TOCItem toc, boolean expanded )27 	private void initItems( TOCItem toc, boolean expanded )
28 	{
29 		for ( int i=0; i<toc.getChildCount(); i++ ) {
30 			TOCItem child = toc.getChild(i);
31 			if ( child.getPage()<=mCurrentPage )
32 				mCurrentPageItem = child;
33 			if ( expanded ) {
34 				child.setGlobalIndex(mItems.size());
35 				mItems.add(child);
36 			} else {
37 				child.setGlobalIndex(-1); // invisible
38 			}
39 			initItems(child, expanded && child.getExpanded());
40 		}
41 	}
initItems()42 	private void initItems()
43 	{
44 		mCurrentPageItem = null;
45 		mItems.clear();
46 		initItems(mTOC, true);
47 	}
48 
expand( TOCItem item )49 	private void expand( TOCItem item )
50 	{
51 		if ( item==null )
52 			return;
53 		item.setExpanded(true);
54 		// expand all parents
55 		for ( TOCItem p = item.getParent(); p!=null; p = p.getParent() )
56 			p.setExpanded(true);
57 		initItems();
58 		refreshList();
59 		if ( mItems.size()>0 ) {
60 			if ( item.getGlobalIndex()>=0 ) {
61 				mListView.setSelection(item.getGlobalIndex());
62 				mListView.setSelectionFromTop(item.getGlobalIndex(), mListView.getHeight()/2);
63 			} else
64 				mListView.setSelection(0);
65 		}
66 	}
67 
collapse( TOCItem item )68 	private void collapse( TOCItem item )
69 	{
70 		item.setExpanded(false);
71 		initItems();
72 		refreshList();
73 	}
74 
refreshList()75 	private void refreshList()
76 	{
77 		mListView.setAdapter(new BaseAdapter() {
78 			public boolean areAllItemsEnabled() {
79 				return true;
80 			}
81 
82 			public boolean isEnabled(int arg0) {
83 				return true;
84 			}
85 
86 			public int getCount() {
87 				return mItems.size();
88 			}
89 
90 			public Object getItem(int position) {
91 				return mItems.get(position);
92 			}
93 
94 			public long getItemId(int position) {
95 				return position;
96 			}
97 
98 			public int getItemViewType(int position) {
99 				TOCItem item = mItems.get(position);
100 				boolean isCurrentItem = item==mCurrentPageItem;
101 				return isCurrentItem ? 0 : 1;
102 			}
103 
104 
105 			public View getView(int position, View convertView, ViewGroup parent) {
106 				View view;
107 				TOCItem item = mItems.get(position);
108 				boolean isCurrentItem = item==mCurrentPageItem;
109 				if ( convertView==null ) {
110 					//view = new TextView(getContext());
111 					view = mInflater.inflate(isCurrentItem ? R.layout.toc_item_current : R.layout.toc_item, null);
112 				} else {
113 					view = convertView;
114 				}
115 				TextView pageTextView = view.findViewById(R.id.toc_page);
116 				TextView titleTextView = view.findViewById(R.id.toc_title);
117 				TextView marginTextView = view.findViewById(R.id.toc_level_margin);
118 				ImageView expandImageView = view.findViewById(R.id.toc_expand_icon);
119 				StringBuilder buf = new StringBuilder(item.getLevel()*2);
120 				for ( int i=1; i<item.getLevel(); i++ )
121 					buf.append("  ");
122 				if ( item.getChildCount()>0 ) {
123 					if ( item.getExpanded() ) {
124 						expandImageView.setImageResource(R.drawable.cr3_toc_item_expanded);
125 					} else {
126 						expandImageView.setImageResource(R.drawable.cr3_toc_item_collapsed);
127 					}
128 				} else {
129 					expandImageView.setImageResource(R.drawable.cr3_toc_item_normal);
130 				}
131 				marginTextView.setText(buf.toString());
132 				titleTextView.setText(item.getName());
133 				pageTextView.setText(String.valueOf(item.getPage()+1));
134 				return view;
135 			}
136 
137 			public int getViewTypeCount() {
138 				return 2;
139 			}
140 
141 			public boolean hasStableIds() {
142 				return true;
143 			}
144 
145 			public boolean isEmpty() {
146 				return false;
147 			}
148 
149 			private ArrayList<DataSetObserver> observers = new ArrayList<>();
150 
151 			public void registerDataSetObserver(DataSetObserver observer) {
152 				observers.add(observer);
153 			}
154 
155 			public void unregisterDataSetObserver(DataSetObserver observer) {
156 				observers.remove(observer);
157 			}
158 		});
159 	}
160 
TOCDlg(BaseActivity coolReader, ReaderView readerView, TOCItem toc, int currentPage )161 	public TOCDlg(BaseActivity coolReader, ReaderView readerView, TOCItem toc, int currentPage )
162 	{
163 		super(coolReader, coolReader.getResources().getString(R.string.win_title_toc), false, false);
164         setCancelable(true);
165 //		this.mCoolReader = coolReader;
166 		this.mReaderView = readerView;
167 		this.mTOC = toc;
168 		this.mCurrentPage = currentPage;
169 		this.mListView = new BaseListView(getContext(), true);
170 		mListView.setOnItemClickListener((listview, view, position, id) -> {
171 			TOCItem item = mItems.get(position);
172 			if ( item.getChildCount()==0 || item.getExpanded() ) {
173 				mReaderView.goToPage(item.getPage()+1);
174 				dismiss();
175 			} else {
176 				expand(item);
177 			}
178 		});
179 		mListView.setOnItemLongClickListener((listview, view, position, id) -> {
180 			TOCItem item = mItems.get(position);
181 			if ( item.getChildCount()==0 ) {
182 				mReaderView.goToPage(item.getPage()+1);
183 				dismiss();
184 			} else {
185 				if ( item.getExpanded() )
186 					collapse(item);
187 				else
188 					expand(item);
189 			}
190 			return true;
191 		});
192 		mListView.setLongClickable(true);
193 		mListView.setClickable(true);
194 		mListView.setFocusable(true);
195 		mListView.setFocusableInTouchMode(true);
196 		mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
197 		setView(mListView);
198 		// cancel
199 		//
200 		setFlingHandlers(mListView, TOCDlg.this::dismiss, TOCDlg.this::dismiss);
201 	}
202 
203 	@Override
onCreate(Bundle savedInstanceState)204 	protected void onCreate(Bundle savedInstanceState) {
205         mInflater = LayoutInflater.from(getContext());
206 		super.onCreate(savedInstanceState);
207 		expand( mTOC );
208 		expand( mCurrentPageItem );
209 	}
210 }
211