package com.thomasdh.roosterpgplus.Data; import android.content.Context; import android.graphics.Color; import android.os.AsyncTask; import android.os.Build; import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPager; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.TextView; import com.thomasdh.roosterpgplus.Adapters.AnimatedPagerAdapter; import com.thomasdh.roosterpgplus.Adapters.MultipleUrenClickListener; import com.thomasdh.roosterpgplus.Helpers.Converter; import com.thomasdh.roosterpgplus.Helpers.HelperFunctions; import com.thomasdh.roosterpgplus.Models.Lesuur; import com.thomasdh.roosterpgplus.R; import org.apache.commons.lang3.StringUtils; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import fj.data.Array; import lombok.NonNull; import lombok.Setter; import lombok.experimental.Accessors; @Accessors(chain = true) public class RoosterBuilder extends AsyncTask<Void, Void, Void> { @Setter private Context context; private ViewPager viewPager; @Setter private int showDag = Calendar.MONDAY; @Setter private boolean showVervangenUren = true; @Setter private long lastLoad = -1; @Setter private int urenCount = -1; @Setter private BuilderFunctions builderFunctions = (lesuur, lesView, inflater) -> { SimpleDateFormat format = new SimpleDateFormat("HH:mm"); TextView vakTextView = (TextView) lesView.findViewById(R.id.rooster_vak); TextView leraarTextView = (TextView) lesView.findViewById(R.id.rooster_leraar); TextView lokaalTextView = (TextView) lesView.findViewById(R.id.rooster_lokaal); TextView tijdenTextView = (TextView) lesView.findViewById(R.id.rooster_tijden); vakTextView.setText(lesuur.vak); leraarTextView.setText(StringUtils.join(lesuur.leraren, " & ")); lokaalTextView.setText(lesuur.lokaal); tijdenTextView.setText(format.format(lesuur.lesStart) + " - " + format.format(lesuur.lesEind)); return lesView; }; @Setter private OnDagScrollListener onDagScrollListener = (scrollY, dag) -> {}; private Array<Lesuur> lessen; private boolean weekView; private Converter converter; private AnimatedPagerAdapter adapter; private ArrayList<View> dagViews = new ArrayList<>(); private LinearLayout weekLinearLayout = null; //region Builder-things public RoosterBuilder(@NonNull Context context) { setContext(context); } public RoosterBuilder in(@NonNull ViewPager viewPager) { this.viewPager = viewPager; return this; } public void build(List<Lesuur> lessen) { if(lessen == null) lessen = new ArrayList<>(); build(Array.iterableArray(lessen)); } public void build(Array<Lesuur> lessen) { this.lessen = lessen; execute(); } @Override protected Void doInBackground(Void... unused) { if(viewPager == null) throw new IllegalStateException("Geen ViewPager"); if(viewPager.getAdapter() == null) throw new IllegalArgumentException("Geen ViewPagerAdapter"); adapter = (AnimatedPagerAdapter) viewPager.getAdapter(); if(lessen == null || lessen.isEmpty()) { return null; } if(urenCount == -1) { urenCount = lessen.foldLeft((a, b) -> b.uur > a ? b.uur : a, 0); } ContextCompat.getDrawable(context, R.drawable.diagonal_stripes_optioneeluur).setAlpha(100); converter = new Converter(context); boolean isWide = context.getResources().getBoolean(R.bool.isWideWeekview); boolean isHigh = context.getResources().getBoolean(R.bool.isHighWeekview); weekView = (isWide || isHigh); int week = lessen.get(0).week; Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); Calendar now = Calendar.getInstance(); if (now.get(Calendar.WEEK_OF_YEAR) > 30 && week <= 30) { // Najaar en wil voorjaar, volgend jaar calendar.set(Calendar.YEAR, now.get(Calendar.YEAR) + 1); } else if (now.get(Calendar.WEEK_OF_YEAR) <= 30 && week > 30) { // Voorjaar en wil najaar, vorig jaar calendar.set(Calendar.YEAR, now.get(Calendar.YEAR) - 1); } else { calendar.set(Calendar.YEAR, now.get(Calendar.YEAR)); } calendar.set(Calendar.WEEK_OF_YEAR, week); if(weekView) { weekLinearLayout = new LinearLayout(context); weekLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0f)); int padding = converter.DPtoPX(10); weekLinearLayout.setPadding(padding, 0, padding, 0); } for(int i = 2; i < 7; i++) { int dag = i; View dagView = LayoutInflater.from(context).inflate(R.layout.rooster_dag, null); dagView = new DagBuilder() .setParentView(dagView) .setDag(dag) .setLessen(lessen.filter(s -> s.dag == dag - 1)) .setDateViewCalendar(calendar) .build(); if(weekView) { weekLinearLayout.addView(dagView); } else { dagViews.add(dagView); } } return null; } @Override protected void onPostExecute(Void s) { if(lessen == null || lessen.isEmpty()) { View noRoosterView = LayoutInflater.from(context).inflate(R.layout.rooster_null, null); adapter.setView(noRoosterView, 0, context); viewPager.getAdapter().notifyDataSetChanged(); return; } boolean isWide = context.getResources().getBoolean(R.bool.isWideWeekview); boolean isHigh = context.getResources().getBoolean(R.bool.isHighWeekview); boolean weekViewNoScroll = isWide && isHigh; if (weekView) { LinearLayout container = new LinearLayout(context); container.setOrientation(LinearLayout.VERTICAL); container.addView(weekLinearLayout); TextView lastUpdateTextView = getUpdateText(lastLoad); lastUpdateTextView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); int pxPadding = converter.DPtoPX(10); lastUpdateTextView.setPadding(pxPadding, pxPadding, pxPadding, pxPadding); container.addView(lastUpdateTextView); if (weekViewNoScroll || isWide) { ScrollView scrollView = new ScrollView(context); scrollView.addView(container); scrollView.getViewTreeObserver().addOnScrollChangedListener(() -> { int scrollY = scrollView.getScrollY(); for(int i = 0; i < 10; i++) { onDagScrollListener.OnScroll(scrollY, i); // weekdag naar kolomconversie, alle dagen om problemen te voorkomen } }); adapter.setView(scrollView, 0, context); } else if (isHigh) { final float[] prevX = {0}; final int touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); HorizontalScrollView scrollView = new HorizontalScrollView(context); scrollView.addView(container); scrollView.setOnTouchListener((view, motionEvent) -> { if(motionEvent.getAction() == MotionEvent.ACTION_DOWN) { prevX[0] = MotionEvent.obtain(motionEvent).getX(); } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) { float eventX = motionEvent.getX(); float xDiff = Math.abs(eventX - prevX[0]); if(xDiff > touchSlop) { for (int i = 0; i < 10; i++) { onDagScrollListener.OnScroll(1, i); } } } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) { for (int i = 0; i < 10; i++) { onDagScrollListener.OnScroll(0, i); } } return false; }); adapter.setView(scrollView, 0, context); } } else { for(int i = 0; i < dagViews.size(); i++) { adapter.setView(dagViews.get(i), i, context); } } adapter.notifyDataSetChanged(); if (!weekView) { // Ga naar de juiste dag viewPager.setCurrentItem(showDag); } } //endregion //region AsyncThings @Accessors(chain = true) private class DagBuilder { @Setter private View parentView; @Setter private int dag = Calendar.MONDAY; @Setter private Array<Lesuur> lessen; @Setter private Calendar dateViewCalendar; @Setter private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM"); private LinearLayout linearLayout; private ScrollView scrollView; public View build() { linearLayout = (LinearLayout) parentView.findViewById(R.id.rooster_dag_linearlayout); /* Dagtitel */ TextView dagNaamTextView = (TextView) parentView.findViewById(R.id.weekdagnaam); TextView dagDatumTextView = (TextView) parentView.findViewById(R.id.weekdagdatum); dagNaamTextView.setText(getDayOfWeek(dag)); int week = dateViewCalendar.get(Calendar.WEEK_OF_YEAR); dateViewCalendar.set(Calendar.DAY_OF_WEEK, dag); dateViewCalendar.set(Calendar.WEEK_OF_YEAR, week); dagDatumTextView.setText(dateFormat.format(dateViewCalendar.getTime())); for(int i = 1; i <= urenCount; i++) { int uur = i; Array<Lesuur> lessenInUur = lessen.filter(s -> s.uur == uur); ArrayList<RelativeLayout> lesViews = new ArrayList<>(); RelativeLayout urenContainer = null; RelativeLayout.LayoutParams urenContainerParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); urenContainerParams.setMargins(0, 0, 0, converter.DPtoPX(10)); if(lessenInUur == null || lessenInUur.isEmpty()) { // Geen lessen -> vrij View lesView = LayoutInflater.from(context).inflate(R.layout.rooster_tussenuur, null); lesView.setMinimumHeight(converter.SPtoPX(89)); if(uur == urenCount) { /*lesView.setBackgroundResource(R.drawable.basic_rect); lesView.setPadding(0,0,0,converter.DPtoPX(1));*/ } linearLayout.addView(lesView); continue; } Array<Lesuur> vervallenLessen = lessenInUur.filter(s -> s.vervallen); Array<Lesuur> normalLessen = lessenInUur.filter(s -> !s.vervallen); if(vervallenLessen.isNotEmpty() && (normalLessen.isEmpty() || normalLessen.isNotEmpty() && showVervangenUren)) { // Vervallen uren verwerken lesViews.add((RelativeLayout) makeView(vervallenLessen)); } if(normalLessen.isNotEmpty()) { for(Lesuur les : normalLessen) { RelativeLayout lesLayout = (RelativeLayout) makeView(les); if(lesLayout != null) lesViews.add(lesLayout); } } boolean multipleViews = lesViews.size() > 1; if(multipleViews) { urenContainer = new RelativeLayout(context); } int reverseCounter = lesViews.size() + 1; int counter = -1; for (RelativeLayout lesView : lesViews) { reverseCounter--; counter++; if (multipleViews) { TextView uurCounter = (TextView) lesView.findViewById(R.id.layerCounter); uurCounter.setVisibility(View.VISIBLE); uurCounter.setText(new StringBuilder("(").append(reverseCounter).append("/").append(lesViews.size()).append(")")); // Padding links/rechts zodat je uren kan zien :D RelativeLayout.LayoutParams lesLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); lesLayoutParams.setMargins(converter.DPtoPX(reverseCounter * 8 - 8), 0, converter.DPtoPX(counter * 8), 0); lesView.setLayoutParams(lesLayoutParams); } if(multipleViews) { urenContainer.addView(lesView); } else { lesView.setLayoutParams(urenContainerParams); linearLayout.addView(lesView, urenContainerParams); } } if(multipleViews) { urenContainer.setOnClickListener(new MultipleUrenClickListener(lesViews, context)); urenContainer.setLayoutParams(urenContainerParams); linearLayout.addView(urenContainer, urenContainerParams); } } if(weekView) { int pxPadding = converter.DPtoPX(3); linearLayout.setPadding(pxPadding, pxPadding, pxPadding, pxPadding); linearLayout.setMinimumWidth(converter.DPtoPX(250)); parentView.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)); } else { int pxPadding = converter.DPtoPX(10); linearLayout.addView(getUpdateText(lastLoad)); linearLayout.setPadding(pxPadding, pxPadding, pxPadding, pxPadding); scrollView = (ScrollView) parentView.findViewById(R.id.scrollView); scrollView.getViewTreeObserver().addOnScrollChangedListener(() -> { int scrollY = scrollView.getScrollY(); onDagScrollListener.OnScroll(scrollY, dag - 2); // weekdag naar kolomconversie }); } return parentView; } } //endregion private String getDayOfWeek(int dag) { switch (dag) { case Calendar.SUNDAY: return "zondag"; case Calendar.MONDAY: return "maandag"; case Calendar.TUESDAY: return "dinsdag"; case Calendar.WEDNESDAY: return "woensdag"; case Calendar.THURSDAY: return "donderdag"; case Calendar.FRIDAY: return "vrijdag"; case Calendar.SATURDAY: return "zaterdag"; } return null; } private View makeView(Lesuur lesuur) { return makeView(Array.array(lesuur)); } private View makeView(Array<Lesuur> lessen) { LayoutInflater inflater = LayoutInflater.from(context); View lesView; if (lessen.get(0).vervallen) { // Vervallen lessen lessen = lessen.filter(lesuur -> lesuur.vervallen); lesView = inflater.inflate(R.layout.rooster_vervallen_uur, null); lesView.setMinimumHeight(converter.SPtoPX(90)); TextView vervallenTextView = (TextView) lesView.findViewById(R.id.vervallen_tekst); if (lessen.length() > 1) { vervallenTextView.setText(StringUtils.join(lessen.map(s -> s.vak).toList(), " & ") + " vallen uit"); } else if(lessen.get(0).verplaatsing) { vervallenTextView.setText(lessen.get(0).vak + " is verplaatst naar " + lessen.get(0).lokaal); } else { vervallenTextView.setText(lessen.get(0).vak + " valt uit"); } } else if (lessen.length() > 1) { throw new IllegalArgumentException("Meerdere lessen"); } else { Lesuur lesuur = lessen.get(0); if (lesuur.verandering) { lesView = inflater.inflate(R.layout.rooster_uur_gewijzigd, null); } else if(lesuur.verplaatsing) { lesView = inflater.inflate(R.layout.rooster_uur, null); ((TextView) lesView.findViewById(R.id.rooster_lokaal)).setTextColor(Color.parseColor("#FE4A49")); } else if(lesuur.isNew) { lesView = inflater.inflate(R.layout.rooster_uur, null); ((TextView) lesView.findViewById(R.id.rooster_notes)).setText("Nieuwe les"); } else { lesView = inflater.inflate(R.layout.rooster_uur, null); } lesView = builderFunctions.fillLesView(lesuur, lesView, inflater); } if (lessen.get(0).uur == urenCount) { //lesView.findViewById(R.id.rooster_uur_linearlayout).setBackgroundResource(R.drawable.basic_rect); } lesView.setMinimumHeight(converter.SPtoPX(90)); ViewCompat.setElevation(lesView, converter.DPtoPX(1)); return lesView; } private TextView getUpdateText(long lastLoad) { TextView textView = new TextView(context); Date lastUpdate = new Date(lastLoad); SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm"); String lastUpdateText = "Laatst geupdate: " + dateFormat.format(lastUpdate); if (!HelperFunctions.hasInternetConnection(context)) { lastUpdateText = "Geen internetverbinding. " + lastUpdateText; } textView.setText(lastUpdateText); return textView; } public interface BuilderFunctions { View fillLesView(Lesuur lesuur, View lesView, LayoutInflater inflater); } public interface OnDagScrollListener { void OnScroll(int scrollY, int dag); } }