/*
* TV-Browser for Android
* Copyright (C) 2013 René Mach (rene@tvbrowser.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to use, copy, modify or merge the Software,
* furthermore to publish and distribute the Software free of charge without modifications and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.tvbrowser.tvbrowser;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.IllegalFormatConversionException;
import java.util.TimeZone;
import org.tvbrowser.content.TvBrowserContentProvider;
import org.tvbrowser.settings.SettingConstants;
import org.tvbrowser.utils.IOUtils;
import org.tvbrowser.utils.PrefUtils;
import org.tvbrowser.utils.ProgramUtils;
import org.tvbrowser.utils.UiUtils;
import org.tvbrowser.view.ChannelLabel;
import org.tvbrowser.view.CompactProgramTableLayout;
import org.tvbrowser.view.ProgramPanel;
import org.tvbrowser.view.ProgramTableLayout;
import org.tvbrowser.view.ProgramTableLayoutConstants;
import org.tvbrowser.view.TimeBlockProgramTableLayout;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.ContentUris;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AlertDialog;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.DatePicker;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
public class FragmentProgramTable extends Fragment {
private boolean mKeepRunning;
private boolean mUpdatingLayout;
private boolean mUpdatingRunningPrograms;
private boolean mShowOrderNumbers;
private boolean mShowGenre;
private boolean mShowEpisode;
private boolean mShowInfo;
private Thread mUpdateThread;
private View.OnClickListener mClickListener;
private View mMenuView;
private View mPrevious;
private BroadcastReceiver mDataUpdateReceiver;
private BroadcastReceiver mUpdateMarkingsReceiver;
private BroadcastReceiver mUpdateChannelsReceiver;
private BroadcastReceiver mRefreshReceiver;
private BroadcastReceiver mDontWantToSeeReceiver;
private int mCurrentLogoValue;
private boolean mPictureShown;
private int mTimeBlockSize;
private int mOldScrollX;
private ProgramTableLayout mProgramPanelLayout;
private Calendar mCurrentDate;
private boolean mDaySet;
private boolean mGrowPanels;
private ArrayList<Integer> mShowInfos;
private int mStartTimeIndex;
private int mEndTimeIndex;
private int mTitleIndex;
private int mChannelIndex;
private int mGenreIndex;
private int mEpisodeIndex;
private int mKeyIndex;
private int mPictureIndex;
private int mPictureCopyrightIndex;
private int mCategoryIndex;
private HashMap<String, Integer> mMarkingsMap;
public void scrollToTime(int time, final MenuItem timeItem) {
Log.d("info4", "time " + time);
if(isResumed()) {
long value = System.currentTimeMillis();
if(time == 0) {
boolean isInRange = (mCurrentDate.get(Calendar.DAY_OF_YEAR) +1 == Calendar.getInstance().get(Calendar.DAY_OF_YEAR)) && Calendar.getInstance().get(Calendar.HOUR_OF_DAY) < 4;
if(!isInRange && (mCurrentDate.get(Calendar.DAY_OF_YEAR) != Calendar.getInstance().get(Calendar.DAY_OF_YEAR))) {
if(timeItem != null) {
timeItem.setActionView(R.layout.progressbar);
}
handler.post(new Runnable() {
@Override
public void run() {
now();
if(timeItem != null) {
timeItem.setActionView(null);
}
}
});
time = -1;
}
}
final boolean next = (time == Integer.MAX_VALUE);
if(next) {
value = System.currentTimeMillis();
}
else if(time > 0) {
Calendar now = Calendar.getInstance();
now.setTimeInMillis(mCurrentDate.getTimeInMillis());
time--;
now.set(Calendar.HOUR_OF_DAY, time / 60);
now.set(Calendar.MINUTE, time % 60);
now.set(Calendar.SECOND, 0);
now.set(Calendar.MILLISECOND, 0);
value = now.getTimeInMillis();
}
if(time >= 0) {
StringBuilder where = new StringBuilder();
where.append(" (( ");
where.append(TvBrowserContentProvider.DATA_KEY_STARTTIME);
if(next) {
where.append(">");
where.append(value);
}
else {
where.append("<=");
where.append(value);
where.append(" ) AND ( ");
where.append(value);
where.append("<=");
where.append(TvBrowserContentProvider.DATA_KEY_ENDTIME);
}
where.append(" )) ");
where.append(((TvBrowser)getActivity()).getFilterSelection(false));
Log.d("info4", "where " + where);
String[] infoNames = TvBrowserContentProvider.INFO_CATEGORIES_COLUMNS_ARRAY;
String[] projection = new String[4+infoNames.length];
projection[0] = TvBrowserContentProvider.KEY_ID;
projection[1] = TvBrowserContentProvider.DATA_KEY_TITLE;
projection[2] = TvBrowserContentProvider.DATA_KEY_STARTTIME;
projection[3] = TvBrowserContentProvider.DATA_KEY_ENDTIME;
System.arraycopy(infoNames, 0, projection, 4, infoNames.length);
if(IOUtils.isDatabaseAccessible(getActivity())) {
Cursor c = getActivity().getContentResolver().query(TvBrowserContentProvider.CONTENT_URI_DATA, projection, where.toString(), null, TvBrowserContentProvider.DATA_KEY_STARTTIME);
try {
if(IOUtils.prepareAccessFirst(c)) {
long id = -1;
do {
id = c.getLong(c.getColumnIndex(TvBrowserContentProvider.KEY_ID));
}while(((getView().findViewWithTag(id) == null) || (value - c.getLong(c.getColumnIndex(TvBrowserContentProvider.DATA_KEY_STARTTIME))) > ((int)(1.25 * 60 * 60000))) && c.moveToNext());
if(id != -1 && getView() != null) {
final View view = getView().findViewWithTag(id);
if(view != null) {
final ScrollView scroll = (ScrollView)getView().findViewById(R.id.vertical_program_table_scroll);
scroll.post(new Runnable() {
@Override
public void run() {
int location[] = new int[2];
view.getLocationInWindow(location);
scroll.scrollTo(scroll.getScrollX(), scroll.getScrollY()+location[1]);
}
});
}
}
}
}finally {
IOUtils.close(c);
}
}
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mShowInfos = new ArrayList<Integer>();
mMarkingsMap = new HashMap<String, Integer>();
mUpdatingRunningPrograms = false;
mUpdatingLayout = false;
mCurrentDate = null;
mOldScrollX = -1;
//mCurrentDay = 0;
mClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Long id = (Long)v.getTag();
if(id != null) {
UiUtils.showProgramInfo(getActivity(), id, null, handler);
}
}
};
}
Handler handler = new Handler();
@Override
public void onResume() {
super.onResume();
mKeepRunning = true;
startUpdateThread();
}
@Override
public void onPause() {
mKeepRunning = false;
super.onPause();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mUpdateMarkingsReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(SettingConstants.EXTRA_MARKINGS_ID, 0);
if(id > 0 && getView() != null) {
View view = getView().findViewWithTag(id);
if(view != null && IOUtils.isDatabaseAccessible(context)) {
String[] projection = TvBrowserContentProvider.getColumnArrayWithMarkingColums(TvBrowserContentProvider.KEY_ID,TvBrowserContentProvider.DATA_KEY_STARTTIME,TvBrowserContentProvider.DATA_KEY_ENDTIME);
Cursor cursor = getActivity().getContentResolver().query(ContentUris.withAppendedId(TvBrowserContentProvider.CONTENT_URI_DATA, id), projection, null, null, null);
Log.d("info2", "CURSOR " + cursor);
try {
if(IOUtils.prepareAccessFirst(cursor)) {
Log.d("info2", "SIZE " + cursor.getCount());
UiUtils.handleMarkings(getActivity(), cursor, view, null, null, true);
}
}finally {
IOUtils.close(cursor);
}
}
}
}
};
IntentFilter filter = new IntentFilter(SettingConstants.MARKINGS_CHANGED);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mUpdateMarkingsReceiver, filter);
mDataUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
handler.post(new Runnable() {
@Override
public void run() {
if(!isDetached() && getView() != null) {
RelativeLayout layout = (RelativeLayout)getView().findViewWithTag("LAYOUT");
if(layout != null) {
updateView(getActivity().getLayoutInflater(),layout);
}
}
}
});
}
};
IntentFilter intent = new IntentFilter(SettingConstants.DATA_UPDATE_DONE);
getActivity().registerReceiver(mDataUpdateReceiver, intent);
mUpdateChannelsReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
handler.post(new Runnable() {
@Override
public void run() {
if(!isDetached() && getView() != null) {
RelativeLayout layout = (RelativeLayout)getView().findViewWithTag("LAYOUT");
if(layout != null) {
updateView(getActivity().getLayoutInflater(),layout);
}
}
}
});
}
};
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mDataUpdateReceiver, new IntentFilter(SettingConstants.CHANNEL_UPDATE_DONE));
mDontWantToSeeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(!isDetached() && getView() != null) {
if(intent.getBooleanExtra(SettingConstants.DONT_WANT_TO_SEE_ADDED_EXTRA, true)) {
if(mProgramPanelLayout != null && IOUtils.isDatabaseAccessible(getActivity())) {
for(int i = 0; i < mProgramPanelLayout.getChildCount(); i++) {
View child = mProgramPanelLayout.getChildAt(i);
long programID = (Long)child.getTag();
Cursor test = getActivity().getContentResolver().query(ContentUris.withAppendedId(TvBrowserContentProvider.CONTENT_URI_DATA,programID), new String[] {TvBrowserContentProvider.DATA_KEY_DONT_WANT_TO_SEE}, null, null, null);
try {
if(IOUtils.prepareAccessFirst(test)) {
if(test.getInt(0) == 1) {
child.setVisibility(View.GONE);
}
}
}finally {
IOUtils.close(test);
}
}
}
}
else {
RelativeLayout layout = (RelativeLayout)getView().findViewWithTag("LAYOUT");
if(layout != null) {
updateView(getActivity().getLayoutInflater(),layout);
}
}
}
}
};
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mDontWantToSeeReceiver, new IntentFilter(SettingConstants.DONT_WANT_TO_SEE_CHANGED));
mRefreshReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
startUpdateThread();
}
};
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mRefreshReceiver, SettingConstants.RERESH_FILTER);
mKeepRunning = true;
}
@Override
public void onDetach() {
mKeepRunning = false;
if(mDataUpdateReceiver != null) {
getActivity().unregisterReceiver(mDataUpdateReceiver);
}
if(mRefreshReceiver != null) {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mRefreshReceiver);
}
if(mUpdateMarkingsReceiver != null) {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mUpdateMarkingsReceiver);
}
if(mUpdateChannelsReceiver != null) {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mUpdateChannelsReceiver);
}
if(mDontWantToSeeReceiver != null) {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mDontWantToSeeReceiver);
}
super.onDetach();
}
private void startUpdateThread() {
if(mUpdateThread == null || !mUpdateThread.isAlive()) {
mUpdateThread = new Thread() {
public void run() {
if(mKeepRunning && TvBrowserContentProvider.INFORM_FOR_CHANGES && !mUpdatingLayout) {
mUpdatingRunningPrograms = true;
if(!isDetached() && mProgramPanelLayout != null) {
for(int k = 0; k < mProgramPanelLayout.getChildCount(); k++) {
View mainChild = mProgramPanelLayout.getChildAt(k);
if(mainChild instanceof ProgramPanel) {
final ProgramPanel progPanel = (ProgramPanel)mainChild;
if(progPanel.isOnAir()) {
handler.post(new Runnable() {
@Override
public void run() {
if(!isDetached() && mKeepRunning && IOUtils.isDatabaseAccessible(getActivity())) {
String[] projection = TvBrowserContentProvider.getColumnArrayWithMarkingColums(TvBrowserContentProvider.KEY_ID,TvBrowserContentProvider.DATA_KEY_STARTTIME,TvBrowserContentProvider.DATA_KEY_ENDTIME);
Cursor c = getActivity().getContentResolver().query(ContentUris.withAppendedId(TvBrowserContentProvider.CONTENT_URI_DATA, (Long)progPanel.getTag()), projection, null, null, null);
try {
if(IOUtils.prepareAccessFirst(c)) {
UiUtils.handleMarkings(getActivity(), c, progPanel, null, null, true);
}
}finally {
IOUtils.close(c);
}
}
}
});
}
else {
progPanel.checkExpired(handler);
}
}
}
}
}
mUpdatingRunningPrograms = false;
}
};
mUpdateThread.setPriority(Thread.MIN_PRIORITY);
mUpdateThread.start();
}
}
public void updateMarkings() {
if(mUpdateThread == null || !mUpdateThread.isAlive()) {
mUpdateThread = new Thread() {
@Override
public void run() {
if(!isDetached() && getActivity() != null && IOUtils.isDatabaseAccessible(getActivity())) {
Calendar value = Calendar.getInstance();
value.setTime(mCurrentDate.getTime());
value.set(Calendar.HOUR_OF_DAY, 0);
value.set(Calendar.MINUTE, 0);
value.set(Calendar.SECOND, 0);
value.set(Calendar.MILLISECOND, 0);
long dayStart = value.getTimeInMillis();
mDaySet = true;
long dayEnd = dayStart + 28 * 60 * 60 * 1000;
String where = TvBrowserContentProvider.DATA_KEY_STARTTIME + ">=" + dayStart + " AND " + TvBrowserContentProvider.DATA_KEY_STARTTIME + "<" + dayEnd + " AND ( " + TextUtils.join(" OR ", TvBrowserContentProvider.MARKING_COLUMNS) + " ) ";
String[] projection = TvBrowserContentProvider.getColumnArrayWithMarkingColums(TvBrowserContentProvider.KEY_ID,TvBrowserContentProvider.DATA_KEY_STARTTIME,TvBrowserContentProvider.DATA_KEY_ENDTIME);
Cursor c = getActivity().getContentResolver().query(TvBrowserContentProvider.CONTENT_URI_DATA, projection, where, null, TvBrowserContentProvider.KEY_ID);
try {
if(IOUtils.prepareAccess(c)) {
int keyColumnIndex = c.getColumnIndex(TvBrowserContentProvider.KEY_ID);
int statTimeColumnIndex = c.getColumnIndex(TvBrowserContentProvider.DATA_KEY_STARTTIME);
int endTimeColumnIndex = c.getColumnIndex(TvBrowserContentProvider.DATA_KEY_ENDTIME);
HashMap<String, Integer> markingColumsIndexMap = new HashMap<String, Integer>();
for(String column : TvBrowserContentProvider.MARKING_COLUMNS) {
int index = c.getColumnIndex(column);
if(index >= 0) {
markingColumsIndexMap.put(column, index);
}
}
while(c.moveToNext()) {
long key = c.getLong(keyColumnIndex);
View view = mProgramPanelLayout.findViewWithTag(key);
if(view != null) {
long startTime = c.getLong(statTimeColumnIndex);
long endTime = c.getLong(endTimeColumnIndex);
ArrayList<String> markedColumns = new ArrayList<String>();
for(String column : TvBrowserContentProvider.MARKING_COLUMNS) {
Integer index = markingColumsIndexMap.get(column);
if(index != null && c.getInt(index) == 1) {
markedColumns.add(column);
}
}
UiUtils.handleMarkings(getActivity(), null, startTime, endTime, view, IOUtils.getStringArrayFromList(markedColumns), handler, true);
}
}
}
}finally {
IOUtils.close(c);
}
}
}
};
mUpdateThread.start();
}
}
public void updateView(LayoutInflater inflater, ViewGroup container) {
if(mUpdatingRunningPrograms) {
Thread t = new Thread() {
public void run() {
while(mUpdatingRunningPrograms) {
try {
sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mUpdatingLayout = true;
if(mProgramPanelLayout != null) {
mProgramPanelLayout.clear();
}
container.removeAllViews();
View programTable = inflater.inflate(R.layout.program_table, container);
int[] infoPrefKeyArr = SettingConstants.CATEGORY_PREF_KEY_ARR;
for(int infoKey : infoPrefKeyArr) {
if(PrefUtils.getBooleanValue(infoKey, R.bool.pref_info_show_default)) {
mShowInfos.add(infoKey);
}
}
/* Calendar cal = Calendar.getInstance();
cal.set(2013, Calendar.DECEMBER, 31);
cal.add(Calendar.DAY_OF_YEAR, 1);*/
Calendar value = Calendar.getInstance();
if(!mDaySet && value.get(Calendar.DAY_OF_YEAR) == mCurrentDate.get(Calendar.DAY_OF_YEAR) && value.get(Calendar.HOUR_OF_DAY) < 4) {
mCurrentDate.add(Calendar.DAY_OF_YEAR, -1);
TextView day = (TextView)((ViewGroup)container.getParent()).findViewById(R.id.show_current_day);
setDayString(day);
}
value.setTime(mCurrentDate.getTime());
value.set(Calendar.HOUR_OF_DAY, 0);
value.set(Calendar.MINUTE, 0);
value.set(Calendar.SECOND, 0);
value.set(Calendar.MILLISECOND, 0);
//long testDay = System.currentTimeMillis() / 1000 / 60 / 60 / 24;
long dayStart = value.getTimeInMillis();
// dayStart -= TimeZone.getDefault().getOffset(dayStart);
/* if(!mDaySet && testDay == mCurrentDay && System.currentTimeMillis() - dayStart < 4 * 60 * 60 * 1000) {
dayStart = --mCurrentDay * 24 * 60 * 60 * 1000 - TimeZone.getDefault().getOffset(dayStart);
}*/
mDaySet = true;
long dayEnd = dayStart + 28 * 60 * 60 * 1000;
String where = TvBrowserContentProvider.DATA_KEY_STARTTIME + ">=" + dayStart + " AND " + TvBrowserContentProvider.DATA_KEY_STARTTIME + "<" + dayEnd;
StringBuilder where3 = new StringBuilder(TvBrowserContentProvider.CHANNEL_KEY_SELECTION);
where3.append("=1");
where3.append(((TvBrowser)getActivity()).getFilterSelection(true).replace(TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID, TvBrowserContentProvider.KEY_ID));
if(IOUtils.isDatabaseAccessible(getActivity())) {
Cursor channels = getActivity().getContentResolver().query(TvBrowserContentProvider.CONTENT_URI_CHANNELS, new String[] {TvBrowserContentProvider.KEY_ID,TvBrowserContentProvider.CHANNEL_KEY_NAME,TvBrowserContentProvider.CHANNEL_KEY_ORDER_NUMBER,TvBrowserContentProvider.CHANNEL_KEY_LOGO}, where3.toString(), null, TvBrowserContentProvider.CHANNEL_KEY_ORDER_NUMBER);
try {
if(IOUtils.prepareAccess(channels)) {
String[] projection = null;
mPictureShown = PrefUtils.getBooleanValue(R.string.SHOW_PICTURE_IN_PROGRAM_TABLE, R.bool.prog_table_show_pictures_default);
mShowGenre = PrefUtils.getBooleanValue(R.string.SHOW_GENRE_IN_PROGRAM_TABLE, R.bool.prog_table_show_genre_default);
mShowEpisode = PrefUtils.getBooleanValue(R.string.SHOW_EPISODE_IN_PROGRAM_TABLE, R.bool.prog_table_show_episode_default);
mShowInfo = PrefUtils.getBooleanValue(R.string.SHOW_INFO_IN_PROGRAM_TABLE, R.bool.prog_table_show_infos_default);
int orderNumberColumn = channels.getColumnIndex(TvBrowserContentProvider.CHANNEL_KEY_ORDER_NUMBER);
mShowOrderNumbers = ProgramTableLayoutConstants.getShowOrderNumber();
String[] infoCategories = TvBrowserContentProvider.INFO_CATEGORIES_COLUMNS_ARRAY;
if(mPictureShown) {
projection = new String[10 + TvBrowserContentProvider.MARKING_COLUMNS.length + infoCategories.length];
projection[projection.length-2] = TvBrowserContentProvider.DATA_KEY_PICTURE;
projection[projection.length-1] = TvBrowserContentProvider.DATA_KEY_PICTURE_COPYRIGHT;
}
else {
projection = new String[8 + TvBrowserContentProvider.MARKING_COLUMNS.length + infoCategories.length];
}
mTimeBlockSize = Integer.parseInt(PrefUtils.getStringValue(R.string.PROG_PANEL_TIME_BLOCK_SIZE, R.string.prog_panel_time_block_size));
projection[0] = TvBrowserContentProvider.KEY_ID;
projection[1] = TvBrowserContentProvider.DATA_KEY_STARTTIME;
projection[2] = TvBrowserContentProvider.DATA_KEY_ENDTIME;
projection[3] = TvBrowserContentProvider.DATA_KEY_TITLE;
projection[4] = TvBrowserContentProvider.DATA_KEY_EPISODE_TITLE;
projection[5] = TvBrowserContentProvider.DATA_KEY_GENRE;
projection[6] = TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID;
projection[7] = TvBrowserContentProvider.DATA_KEY_CATEGORIES;
System.arraycopy(infoCategories, 0, projection, 8, infoCategories.length);
System.arraycopy(TvBrowserContentProvider.MARKING_COLUMNS, 0, projection, 8 + infoCategories.length, TvBrowserContentProvider.MARKING_COLUMNS.length);
LinearLayout channelBar = (LinearLayout)programTable.findViewById(R.id.program_table_channel_bar);
ArrayList<Integer> channelIDsOrdered = new ArrayList<Integer>();
while(channels.moveToNext()) {
channelIDsOrdered.add(channels.getInt(channels.getColumnIndex(TvBrowserContentProvider.KEY_ID)));
String name = channels.getString(channels.getColumnIndex(TvBrowserContentProvider.CHANNEL_KEY_NAME));
String shortName = SettingConstants.SHORT_CHANNEL_NAMES.get(name);
if(shortName != null) {
name = shortName;
}
int orderNumber = channels.getInt(orderNumberColumn);
Bitmap logo = UiUtils.createBitmapFromByteArray(channels.getBlob(channels.getColumnIndex(TvBrowserContentProvider.CHANNEL_KEY_LOGO)));
if(logo != null) {
int height = ProgramTableLayoutConstants.getChannelMaxFontHeight();
float percent = height / (float)logo.getHeight();
if(percent < 1) {
logo = Bitmap.createScaledBitmap(logo, (int)(logo.getWidth() * percent), height, true);
}
}
ChannelLabel channelLabel = new ChannelLabel(getActivity(), name, logo, orderNumber);
channelBar.addView(channelLabel);
}
if(channels.getCount() > 0) {
mGrowPanels = PrefUtils.getBooleanValue(R.string.PROG_PANEL_GROW, R.bool.prog_panel_grow_default);
if(PrefUtils.getStringValue(R.string.PROG_TABLE_LAYOUT, R.string.prog_table_layout_default).equals("0")) {
mProgramPanelLayout = new TimeBlockProgramTableLayout(getActivity(), channelIDsOrdered, mTimeBlockSize, value, mGrowPanels);
}
else {
mProgramPanelLayout = new CompactProgramTableLayout(getActivity(), channelIDsOrdered);
}
ViewGroup test = (ViewGroup)programTable.findViewById(R.id.vertical_program_table_scroll);
test.addView(mProgramPanelLayout);
where += UiUtils.getDontWantToSeeFilterString(getActivity());
where += ((TvBrowser)getActivity()).getCategoryFilterSelection();
Cursor cursor = getActivity().getContentResolver().query(TvBrowserContentProvider.CONTENT_URI_DATA, projection, where, null, TvBrowserContentProvider.DATA_KEY_STARTTIME);
try {
if(IOUtils.prepareAccess(cursor)) {
mStartTimeIndex = cursor.getColumnIndex(TvBrowserContentProvider.DATA_KEY_STARTTIME);
mEndTimeIndex = cursor.getColumnIndex(TvBrowserContentProvider.DATA_KEY_ENDTIME);
mTitleIndex = cursor.getColumnIndex(TvBrowserContentProvider.DATA_KEY_TITLE);
mChannelIndex = cursor.getColumnIndex(TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID);
mGenreIndex = cursor.getColumnIndex(TvBrowserContentProvider.DATA_KEY_GENRE);
mEpisodeIndex = cursor.getColumnIndex(TvBrowserContentProvider.DATA_KEY_EPISODE_TITLE);
mKeyIndex = cursor.getColumnIndex(TvBrowserContentProvider.KEY_ID);
mPictureIndex = cursor.getColumnIndex(TvBrowserContentProvider.DATA_KEY_PICTURE);
mPictureCopyrightIndex = cursor.getColumnIndex(TvBrowserContentProvider.DATA_KEY_PICTURE_COPYRIGHT);
mMarkingsMap.clear();
for(String column : TvBrowserContentProvider.MARKING_COLUMNS) {
int index = cursor.getColumnIndex(column);
if(index >= 0) {
mMarkingsMap.put(column, index);
}
}
mCategoryIndex = cursor.getColumnIndex(TvBrowserContentProvider.DATA_KEY_CATEGORIES);
while(cursor.moveToNext()) {
addPanel(cursor, mProgramPanelLayout);
}
}
}finally {
IOUtils.close(cursor);
}
}
if(mProgramPanelLayout instanceof CompactProgramTableLayout) {
channelBar.removeViewAt(0);
channelBar.removeViewAt(0);
}
Calendar test = Calendar.getInstance();
if(test.get(Calendar.DAY_OF_YEAR) == mCurrentDate.get(Calendar.DAY_OF_YEAR) || test.get(Calendar.DAY_OF_YEAR) - 2 == mCurrentDate.get(Calendar.DAY_OF_YEAR)) {
handler.post(new Runnable() {
@Override
public void run() {
scrollToTime(0,null);
}
});
}
handler.post(new Runnable() {
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void run() {
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
View view = getView();
if(view != null) {
View scroll = view.findViewById(R.id.horizontal_program_table_scroll);
if(scroll != null) {
scroll.setScrollX(mOldScrollX);
}
}
}
mOldScrollX = 0;
}
});
}
}finally {
IOUtils.close(channels);
}
}
mUpdatingLayout = false;
}
private void setDayString(TextView currentDay) {
if(mPrevious != null) {
final Calendar test = Calendar.getInstance();
test.add(Calendar.DAY_OF_YEAR, -1);
test.set(Calendar.HOUR_OF_DAY, 0);
test.set(Calendar.MINUTE, 0);
test.set(Calendar.SECOND, 0);
test.set(Calendar.MILLISECOND, 0);
final Calendar test2 = Calendar.getInstance();
test2.setTimeInMillis(mCurrentDate.getTimeInMillis());
test2.set(Calendar.HOUR_OF_DAY, 0);
test2.set(Calendar.MINUTE, 0);
test2.set(Calendar.SECOND, 0);
test2.set(Calendar.MILLISECOND, 0);
handler.post(new Runnable() {
@Override
public void run() {
mPrevious.setEnabled(test2.compareTo(test) > 0);
}
});
}
Date date = mCurrentDate.getTime();
String longDate = DateFormat.getLongDateFormat(getActivity()).format(date);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
longDate = longDate.replaceAll("\\s+"+cal.get(Calendar.YEAR), "");
currentDay.setText(UiUtils.LONG_DAY_FORMAT.format(date) + "\n" + longDate);
}
private void now() {
mCurrentDate = Calendar.getInstance();
TextView day = (TextView)getView().findViewById(R.id.show_current_day);
setDayString(day);
RelativeLayout layout = (RelativeLayout)getView().findViewWithTag("LAYOUT");
mOldScrollX = getView().findViewById(R.id.horizontal_program_table_scroll).getScrollX();
updateView(getActivity().getLayoutInflater(), layout);
}
private void changeDay(int count) {
mCurrentDate.add(Calendar.DAY_OF_YEAR, count);
TextView day = (TextView)getView().findViewById(R.id.show_current_day);
setDayString(day);
RelativeLayout layout = (RelativeLayout)getView().findViewWithTag("LAYOUT");
View parent = getView();
if(parent != null) {
View horizontalScroll = parent.findViewById(R.id.horizontal_program_table_scroll);
if(horizontalScroll != null) {
mOldScrollX = horizontalScroll.getScrollX();
updateView(getActivity().getLayoutInflater(), layout);
}
}
}
void updateView(LayoutInflater inflater) {
RelativeLayout layout = (RelativeLayout)getView().findViewWithTag("LAYOUT");
if(layout != null && inflater != null) {
updateView(inflater, layout);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
RelativeLayout programTableLayout = (RelativeLayout)inflater.inflate(R.layout.program_table_layout, container, false);
if(mCurrentDate == null) {
mCurrentDate = Calendar.getInstance();
mDaySet = false;
}
if(SettingConstants.IS_DARK_THEME) {
programTableLayout.findViewById(R.id.button_panel).setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.background_material_dark));
}
ProgramTableLayoutConstants.initialize(getActivity());
TextView currentDay = (TextView)programTableLayout.findViewById(R.id.show_current_day);
setDayString(currentDay);
currentDay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
selectDate(view);
}
});
mPrevious = programTableLayout.findViewById(R.id.switch_to_previous_day);
mPrevious.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeDay(-1);
}
});
programTableLayout.findViewById(R.id.switch_to_next_day).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeDay(1);
}
});
RelativeLayout layout = (RelativeLayout)programTableLayout.findViewById(R.id.program_table_base);
layout.setTag("LAYOUT");
int startTab = Integer.parseInt(PrefUtils.getStringValue(R.string.TAB_TO_SHOW_AT_START, R.string.tab_to_show_at_start_default));
if(!PrefUtils.getBooleanValue(R.string.PROG_TABLE_DELAYED, R.bool.prog_table_delayed_default) || startTab == 3) {
updateView(inflater,layout);
}
return programTableLayout;
}
public void removed() {
mDaySet = false;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
mMenuView = v;
long programID = ((Long)v.getTag());
UiUtils.createContextMenu(getActivity(), menu, programID);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if(mMenuView != null) {
View temp = mMenuView;
mMenuView = null;
long programID = ((Long)temp.getTag());
return UiUtils.handleContextMenuSelection(getActivity(), item, programID, temp, getActivity().getCurrentFocus());
}
return false;
}
public boolean updateTable() {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
boolean toShow = pref.getBoolean(getResources().getString(R.string.SHOW_PICTURE_IN_PROGRAM_TABLE), false);
boolean toGrow = PrefUtils.getBooleanValue(R.string.PROG_PANEL_GROW, R.bool.prog_panel_grow_default);
boolean updateLayout = (PrefUtils.getStringValue(R.string.PROG_TABLE_LAYOUT, R.string.prog_table_layout_default).equals("0") && mProgramPanelLayout instanceof CompactProgramTableLayout) ||
(PrefUtils.getStringValue(R.string.PROG_TABLE_LAYOUT, R.string.prog_table_layout_default).equals("1") && mProgramPanelLayout instanceof TimeBlockProgramTableLayout);
boolean updateWidth = PrefUtils.getIntValueWithDefaultKey(R.string.PROG_TABLE_COLUMN_WIDTH, R.integer.prog_table_column_width_default) != ProgramTableLayoutConstants.getRawColumnWidth();
boolean updateTextScale = Float.valueOf(PrefUtils.getStringValue(R.string.PROG_TABLE_TEXT_SCALE, R.string.prog_table_text_scale_default)) != ProgramTableLayoutConstants.getTextScale();
boolean updateShownValues = PrefUtils.getBooleanValue(R.string.SHOW_EPISODE_IN_PROGRAM_TABLE, R.bool.prog_table_show_episode_default) != mShowEpisode ||
PrefUtils.getBooleanValue(R.string.SHOW_GENRE_IN_PROGRAM_TABLE, R.bool.prog_table_show_genre_default) != mShowGenre ||
PrefUtils.getBooleanValue(R.string.SHOW_INFO_IN_PROGRAM_TABLE, R.bool.prog_table_show_infos_default) != mShowInfo;
boolean updateInfoValues = PrefUtils.getBooleanValue(R.string.SHOW_INFO_IN_PROGRAM_TABLE, R.bool.prog_table_show_infos_default);
if(updateInfoValues) {
updateInfoValues = false;
int[] infoPrefKeyArr = SettingConstants.CATEGORY_PREF_KEY_ARR;
for(int infoKey : infoPrefKeyArr) {
boolean isShownSetting = PrefUtils.getBooleanValue(infoKey, R.bool.pref_info_show_default);
boolean isCurrentlyShown = mShowInfos.contains(infoKey);
if((isShownSetting && !isCurrentlyShown) || (!isShownSetting && isCurrentlyShown)) {
updateInfoValues = true;
break;
}
}
}
if(updateTextScale) {
ProgramTableLayoutConstants.initialize(getActivity());
}
else if(updateWidth) {
ProgramTableLayoutConstants.updateColumnWidth(getActivity());
}
if(mPictureShown != toShow || mGrowPanels != toGrow || updateLayout || updateWidth || updateTextScale || updateShownValues || updateInfoValues) {
updateView(getActivity().getLayoutInflater(), (RelativeLayout)getView().findViewWithTag("LAYOUT"));
}
return mPictureShown != toShow || mGrowPanels != toGrow || updateLayout || updateWidth || updateTextScale || updateShownValues || updateInfoValues;
}
public void firstLoad(LayoutInflater inflater) {
if(!mDaySet) {
updateView(inflater);
}
}
public void updateChannelBar() {
LinearLayout channelBar = (LinearLayout)getView().findViewById(R.id.program_table_channel_bar);
ProgramTableLayoutConstants.updateChannelLogoName(getActivity());
int logoValue = Integer.parseInt(PrefUtils.getStringValue(R.string.CHANNEL_LOGO_NAME_PROGRAM_TABLE, R.string.channel_logo_name_program_table_default));
if(channelBar != null && (logoValue != mCurrentLogoValue || ProgramTableLayoutConstants.getShowOrderNumber() != mShowOrderNumbers)) {
mCurrentLogoValue = logoValue;
mShowOrderNumbers = ProgramTableLayoutConstants.getShowOrderNumber();
for(int i = 0; i < channelBar.getChildCount(); i++) {
View view = channelBar.getChildAt(i);
if(view instanceof ChannelLabel) {
((ChannelLabel)view).updateNameAndLogo();
view.invalidate();
}
}
}
}
private void addPanel(final Cursor cursor, final ProgramTableLayout layout) {
final long programId = cursor.getLong(mKeyIndex);
final long startTime = cursor.getLong(mStartTimeIndex);
final long endTime = cursor.getLong(mEndTimeIndex);
String title = cursor.getString(mTitleIndex);
int channelID = cursor.getInt(mChannelIndex);
Spannable categories = IOUtils.getInfoString(cursor.getInt(mCategoryIndex),getResources(),false);
final ProgramPanel panel = new ProgramPanel(getActivity(),startTime,endTime,title,channelID);
if(mShowGenre) {
panel.setGenre(cursor.getString(mGenreIndex));
}
if(mShowEpisode) {
panel.setEpisode(cursor.getString(mEpisodeIndex));
}
if(mShowInfo) {
panel.setInfoString(categories);
}
panel.setOnClickListener(mClickListener);
panel.setTag(programId);
registerForContextMenu(panel);
if(mPictureIndex != -1) {
Bitmap logo = UiUtils.createBitmapFromByteArray(cursor.getBlob(mPictureIndex));
if(logo != null) {
BitmapDrawable l = new BitmapDrawable(getResources(), logo);
l.setBounds(0, 0, (int)(ProgramTableLayoutConstants.getZoom() * logo.getWidth()), (int)(ProgramTableLayoutConstants.getZoom() * logo.getHeight()));
panel.setPicture(cursor.getString(mPictureCopyrightIndex), l);
}
}
layout.addView(panel);
ArrayList<String> markedColumns = new ArrayList<String>();
for(String column : TvBrowserContentProvider.MARKING_COLUMNS) {
Integer value = mMarkingsMap.get(column);
if(value != null && cursor.getInt(value) == 1) {
markedColumns.add(column);
}
else if(column.equals(TvBrowserContentProvider.DATA_KEY_MARKING_MARKING) && ProgramUtils.isMarkedWithIcon(getActivity(), programId)) {
markedColumns.add(column);
}
}
UiUtils.handleMarkings(getActivity(), null, startTime, endTime, panel, IOUtils.getStringArrayFromList(markedColumns), null, true);
}
/*private boolean isBrokenSamsungDevice() {
return true;
}*/
@SuppressLint("NewApi")
public void selectDate(View view) {try {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
long testDay = System.currentTimeMillis() / 1000 / 60 / 60 / 24;
long dayStart = testDay * 24 * 60 * 60 * 1000;
if(System.currentTimeMillis() - dayStart < 4 * 60 * 60 * 1000) {
dayStart = --testDay * 24 * 60 * 60 * 1000 - TimeZone.getDefault().getOffset(dayStart);
}
Context context = new ContextWrapper(getActivity()) {
private Resources wrappedResources;
@Override
public Resources getResources() {
Resources r = super.getResources();
if(wrappedResources == null) {
wrappedResources = new Resources(r.getAssets(), r.getDisplayMetrics(), r.getConfiguration()) {
@NonNull
@Override
public String getString(int id, Object... formatArgs) throws NotFoundException {
try {
return super.getString(id, formatArgs);
} catch (IllegalFormatConversionException ifce) {
Log.e("DatePickerDialogFix", "IllegalFormatConversionException Fixed!", ifce);
String template = super.getString(id);
template = template.replaceAll("%" + ifce.getConversion(), "%s");
return String.format(getConfiguration().locale, template, formatArgs);
}
}
};
}
return wrappedResources;
}
};
final DatePicker select = new DatePicker(context);
if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1 &&
Build.VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
select.getCalendarView().setFirstDayOfWeek(Calendar.MONDAY);
}
select.setMinDate(dayStart - 24 * 60 * 60 * 1000);
select.setMaxDate(dayStart + 21 * (24 * 60 * 60 * 1000));
select.init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate.get(Calendar.DAY_OF_MONTH), null);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mCurrentDate.set(select.getYear(), select.getMonth(), select.getDayOfMonth());
setDayString((TextView)getView().findViewById(R.id.show_current_day));
View view = getView().findViewById(R.id.horizontal_program_table_scroll);
if(view != null) {
mOldScrollX = view.getScrollX();
}
updateView(getActivity().getLayoutInflater(), (RelativeLayout)getView().findViewWithTag("LAYOUT"));
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {}
});
HorizontalScrollView scroll = new HorizontalScrollView(getActivity());
scroll.addView(select);
builder.setView(scroll);
builder.show();}catch(Throwable t) {}
}
public boolean checkTimeBlockSize() {
if(mTimeBlockSize != Integer.parseInt(PrefUtils.getStringValue(R.string.PROG_PANEL_TIME_BLOCK_SIZE, R.string.prog_panel_time_block_size))) {
RelativeLayout layout = (RelativeLayout)getView().findViewWithTag("LAYOUT");
updateView(getActivity().getLayoutInflater(), layout);
return true;
}
return false;
}
}