Commit 575575ab authored by Lucas Braz Cunha's avatar Lucas Braz Cunha
Browse files

Issue AGILE#182 [WIP] added spinner behavior of disabling locations


Signed-off-by: Lucas Braz Cunha's avatarLucas B. Cunha <lbc16@inf.ufpr.br>
parent f1a07c26
......@@ -41,9 +41,10 @@ import java.util.List;
import java.util.Locale;
import br.ufpr.c3sl.agendador.agendador.helpers.ConnectionErrorDialog;
import br.ufpr.c3sl.agendador.agendador.helpers.EventDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.adapters.HintEnableAdapter;
import br.ufpr.c3sl.agendador.agendador.helpers.decorators.SchedulesDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
import br.ufpr.c3sl.agendador.agendador.helpers.SchedulingDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.decorators.NotAvailableDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.UserPhotoHelper;
import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
import br.ufpr.c3sl.agendador.agendador.helpers.adapters.HintAdapter;
......@@ -109,7 +110,9 @@ public class SchedulingActivity extends AppCompatActivity implements SchedulingV
private SectorSpinnerListener sectorSpinnerListener;
private HintAdapter hintAdapterType, hintAdapterSector, hintAdapterLocation;
private HintAdapter hintAdapterType, hintAdapterSector;
private HintEnableAdapter hintAdapterLocation;
private List<HashMap<String,ArrayList<ServiceSchedule>>> listOfScheduleDays;
......@@ -117,9 +120,9 @@ public class SchedulingActivity extends AppCompatActivity implements SchedulingV
private ServiceSchedule selectedSchedule;
private EventDecorator decorator;
private SchedulesDecorator schedulesDecorator;
private SchedulingDecorator schedulingDecorator;
private NotAvailableDecorator notAvailableDecorator;
private DateFormat dateFormat, hourFormat;
......@@ -146,11 +149,8 @@ public class SchedulingActivity extends AppCompatActivity implements SchedulingV
// TODO: 12/07/17 Tarefas
// levar o calendário para o primeiro dia de agendamento?
// verificar a necessidade de colocar limite superior nas datas
// desabilitar items do spinner?
// testar se a validação e "invalidação" de decorators está certa.
// renomear o EventDecorator.
// levar o calendário para o primeiro dia de agendamento? - ordenar aqui as chaves das hashs.
// pegar do back-end o limite superior de data.
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -243,12 +243,12 @@ public class SchedulingActivity extends AppCompatActivity implements SchedulingV
navigationView.setNavigationItemSelectedListener(this);
String[] sector;
if(sectors.size() > 0) {
sector = new String[sectors.size() + 1];
int i = 0;
for (; i < sectors.size(); i++)
for (; i < sectors.size(); i++) {
sector[i] = sectors.get(i).getName();
}
sector[i] = getResources().getString(R.string.scheduling_sector_hint);
}
else{
......@@ -268,7 +268,10 @@ public class SchedulingActivity extends AppCompatActivity implements SchedulingV
spnr_type.setSelection(hintAdapterType.getCount());
String[] locations = {"", getResources().getString(R.string.scheduling_location_hint)};
hintAdapterLocation = new HintAdapter(this, android.R.layout.simple_list_item_1, locations);
boolean[] enableView = new boolean[2];
enableView[0] = false;
enableView[1] = true;
hintAdapterLocation = new HintEnableAdapter(this, android.R.layout.simple_list_item_1, locations, enableView);
spnr_location.setAdapter(hintAdapterLocation);
spnr_location.setSelection(hintAdapterLocation.getCount());
......@@ -490,14 +493,21 @@ public class SchedulingActivity extends AppCompatActivity implements SchedulingV
@Override
public void setServiceTypesList(List<ServiceType> serviceTypes) {
int i = 0;
//block listener call for the spinners.
locationSpinnerListener.setUserSelect(false);
serviceTypeSpinnerListener.setUserSelect(false);
serviceTypeSpinnerListener.setServiceTypes(serviceTypes);
spnr_type.setEnabled(true);
String[] types;
boolean[] enableView;
if(serviceTypes.size() > 0) {
types = new String[serviceTypes.size() + 1];
enableView = new boolean[serviceTypes.size() + 1];
for (; i < serviceTypes.size(); i++) {
types[i] = serviceTypes.get(i).getmDescription();
enableView[i] = true;
}
types[i] = getResources().getString(R.string.scheduling_type_hint);
}
......@@ -513,60 +523,64 @@ public class SchedulingActivity extends AppCompatActivity implements SchedulingV
public void setServiceLocationList(List<ServiceLocation> serviceLocations){
int i = 0;
int i, schedulesListSize;
boolean hasCreatedDecorator1 = false;
boolean hasCreatedDecorator2 = false;
locationSpinnerListener.setUserSelect(false);
locationSpinnerListener.setServiceLocations(serviceLocations);
// TODO: 13/07/17 is the list ordered?
// TODO: 13/07/17 is the list ordered? -- receive "max date sum" from back-end
//get max available date to this type of service
//checking only the last position of each location
// TODO: 13/07/17 erro de array out of bounds
/*
Process: br.ufpr.c3sl.agendador.agendador, PID: 19811
java.lang.ArrayIndexOutOfBoundsException: length=0; index=-1
at java.util.ArrayList.get(ArrayList.java:413)
at br.ufpr.c3sl.agendador.agendador.SchedulingActivity.setServiceLocationList(SchedulingActivity.java:523)
at br.ufpr.c3sl.agendador.agendador.presenters.SchedulingPresenter$2.onResponse(SchedulingPresenter.java:135)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
*/
Date max = serviceLocations.get(i).getSchedules().get(serviceLocations.get(i).getSchedules().size() - 1).getEnd();
for(i = 1; i < serviceLocations.size() && serviceLocations.get(i).getSchedules().size() != 0; ++i)
i = 0;
ServiceLocation serviceLocation = serviceLocations.get(0);
List<ServiceSchedule> scheduleList = serviceLocation.getSchedules();
Date max = new Date();
schedulesListSize = serviceLocation.getSchedules().size();
for(; i < serviceLocations.size() && schedulesListSize != 0; ++i)
{
ServiceLocation location = serviceLocations.get(i);
int size = location.getSchedules().size();
if(max.before(location.getSchedules().get(size -1).getEnd()))
max = location.getSchedules().get(size -1).getEnd();
if(max.before(scheduleList.get(schedulesListSize -1).getEnd())) {
max = scheduleList.get(schedulesListSize -1).getEnd();
}
serviceLocation = serviceLocations.get(i);
scheduleList = serviceLocation.getSchedules();
schedulesListSize = serviceLocation.getSchedules().size();
}
mcv.state().edit().setMaximumDate(max).commit();
//adding 2 months to make calendar more friendly
Calendar cal = Calendar.getInstance();
cal.setTime(max);
cal.add(Calendar.MONTH, 2);
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
mcv.state().edit().setMaximumDate(cal).commit();
// TODO: 13/07/17 end of control for max date.
String[] locations;
boolean[] enableView;
if(serviceLocations.size() > 0) {
locations = new String[serviceLocations.size() + 1];
enableView = new boolean[serviceLocations.size() + 1];
for (i = 0; i < serviceLocations.size(); i++) {
locations[i] = serviceLocations.get(i).getmName() + " (" + serviceLocations.get(i).getSchedules().size() + ")";
enableView[i] = serviceLocations.get(i).getSchedules().size() != 0;
}
locations[i] = getResources().getString(R.string.scheduling_location_hint);
enableView[i] = false;
}
else{
locations = new String[2];
enableView = new boolean[2];
locations[1] = getResources().getString(R.string.no_available_hint);
locations[0] = "";
enableView[1] = true;
enableView[0] = false;
}
hintAdapterLocation = new HintAdapter(this, android.R.layout.simple_list_item_1, locations);
hintAdapterLocation = new HintEnableAdapter(this, android.R.layout.simple_list_item_1, locations, enableView);
spnr_location.setAdapter(hintAdapterLocation);
spnr_location.setSelection(hintAdapterLocation.getCount());
......@@ -588,37 +602,37 @@ public class SchedulingActivity extends AppCompatActivity implements SchedulingV
listOfScheduleDays.add(hashMap);
}
if(schedulingDecorator == null){
schedulingDecorator = new SchedulingDecorator(listOfScheduleDays, this);
schedulingDecorator.setScheduleType(SchedulingDecorator.INVALID_STATE);
sectorSpinnerListener.setSchedulingDecorator(schedulingDecorator);
locationSpinnerListener.setSchedulingDecorator(schedulingDecorator);
serviceTypeSpinnerListener.setSchedulingDecorator(schedulingDecorator);
mcv.addDecorator(schedulingDecorator);
if(notAvailableDecorator == null){
notAvailableDecorator = new NotAvailableDecorator(listOfScheduleDays, this);
notAvailableDecorator.setScheduleType(NotAvailableDecorator.INVALID_STATE);
sectorSpinnerListener.setNotAvailableDecorator(notAvailableDecorator);
locationSpinnerListener.setNotAvailableDecorator(notAvailableDecorator);
serviceTypeSpinnerListener.setNotAvailableDecorator(notAvailableDecorator);
mcv.addDecorator(notAvailableDecorator);
}
else {
schedulingDecorator.setListOfScheduleDays(listOfScheduleDays);
schedulingDecorator.setScheduleType(EventDecorator.INVALID_STATE);
notAvailableDecorator.setListOfScheduleDays(listOfScheduleDays);
notAvailableDecorator.setScheduleType(SchedulesDecorator.INVALID_STATE);
hasCreatedDecorator1 = true;
}
if(decorator == null){
decorator = new EventDecorator(listOfScheduleDays, this);
decorator.setScheduleType(EventDecorator.INVALID_STATE);
sectorSpinnerListener.setDecorator(decorator);
locationSpinnerListener.setDecorator(decorator);
serviceTypeSpinnerListener.setDecorator(decorator);
mcv.addDecorator(decorator);
if(schedulesDecorator == null){
schedulesDecorator = new SchedulesDecorator(listOfScheduleDays, this);
schedulesDecorator.setScheduleType(SchedulesDecorator.INVALID_STATE);
sectorSpinnerListener.setSchedulesDecorator(schedulesDecorator);
locationSpinnerListener.setSchedulesDecorator(schedulesDecorator);
serviceTypeSpinnerListener.setSchedulesDecorator(schedulesDecorator);
mcv.addDecorator(schedulesDecorator);
}
else {
decorator.setListOfScheduleDays(listOfScheduleDays);
decorator.setScheduleType(EventDecorator.INVALID_STATE);
schedulesDecorator.setListOfScheduleDays(listOfScheduleDays);
schedulesDecorator.setScheduleType(SchedulesDecorator.INVALID_STATE);
hasCreatedDecorator2 = true;
}
//redrawing the tiles of the calendar is an expensive operation,
//if the decorator was added there is no need to redo it.
//if the schedulesDecorator was added there is no need to redo it.
if(hasCreatedDecorator1 || hasCreatedDecorator2)
mcv.invalidateDecorators();
}
......
......@@ -13,13 +13,11 @@ import android.widget.ArrayAdapter;
public class HintAdapter extends ArrayAdapter<String> {
public HintAdapter(Context context, int resource, String[] objects) {
super(context, resource, objects);
}
public HintAdapter(@NonNull Context context, @LayoutRes int resource) {
super(context, resource);
}
@Override
public int getCount() {
......
package br.ufpr.c3sl.agendador.agendador.helpers.adapters;
import android.content.Context;
import android.graphics.Color;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
/**
* Created by Lucas B. Cunha on 07/07/17.
*
* Thanks to Luan Dang at https://stackoverflow.com/a/24951888
*
*/
public class HintEnableAdapter extends ArrayAdapter<String> {
boolean[] enableView;
public HintEnableAdapter(Context context, int resource, String[] objects, boolean[] enableView) {
super(context, resource, objects);
this.enableView = enableView;
}
@Override
public boolean isEnabled(int position) {
return enableView[position];
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
View mView = super.getDropDownView(position, convertView, parent);
TextView mTextView = (TextView) mView;
if (!enableView[position])
mTextView.setTextColor(Color.GRAY);
else
mTextView.setTextColor(Color.BLACK);
return mView;
}
@Override
public int getCount() {
// don't display last item. It is used as hint.
int count = super.getCount();
return count > 0 ? count - 1 : count;
}
}
package br.ufpr.c3sl.agendador.agendador.helpers;
package br.ufpr.c3sl.agendador.agendador.helpers.decorators;
import android.content.Context;
import android.support.v4.content.ContextCompat;
......@@ -21,7 +21,7 @@ import br.ufpr.c3sl.agendador.agendador.models.ServiceSchedule;
* Created by Lucas B. Cunha on 13/07/17.
*/
public class SchedulingDecorator implements DayViewDecorator {
public class NotAvailableDecorator implements DayViewDecorator {
public static int INVALID_STATE = -1;
......@@ -33,7 +33,7 @@ public class SchedulingDecorator implements DayViewDecorator {
private DateFormat dateFormat;
public SchedulingDecorator(List<HashMap<String,ArrayList<ServiceSchedule>>> listOfScheduleDays, Context context) {
public NotAvailableDecorator(List<HashMap<String,ArrayList<ServiceSchedule>>> listOfScheduleDays, Context context) {
this.listOfScheduleDays = listOfScheduleDays;
this.context = context;
dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
......@@ -47,7 +47,7 @@ public class SchedulingDecorator implements DayViewDecorator {
*/
@Override
public boolean shouldDecorate(CalendarDay day) {
return scheduleType != INVALID_STATE && !listOfScheduleDays.get(scheduleType).containsKey(dateFormat.format(day.getDate()));
return scheduleType != INVALID_STATE && !listOfScheduleDays.get(scheduleType).containsKey(dateFormat.format(day.getDate()));
}
/**
......
package br.ufpr.c3sl.agendador.agendador.helpers;
package br.ufpr.c3sl.agendador.agendador.helpers.decorators;
import android.content.Context;
import android.support.v4.content.ContextCompat;
......@@ -21,7 +21,7 @@ import br.ufpr.c3sl.agendador.agendador.models.ServiceSchedule;
* Created by Lucas B. Cunha on 25/05/17.
*/
public class EventDecorator implements DayViewDecorator {
public class SchedulesDecorator implements DayViewDecorator {
public static int INVALID_STATE = -1;
......@@ -33,7 +33,7 @@ public class EventDecorator implements DayViewDecorator {
private DateFormat dateFormat;
public EventDecorator(List<HashMap<String,ArrayList<ServiceSchedule>>> listOfScheduleDays, Context context) {
public SchedulesDecorator(List<HashMap<String,ArrayList<ServiceSchedule>>> listOfScheduleDays, Context context) {
this.listOfScheduleDays = listOfScheduleDays;
this.context = context;
dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
......
......@@ -4,13 +4,14 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.TextView;
import android.widget.Toast;
import com.prolificinteractive.materialcalendarview.MaterialCalendarView;
import java.util.List;
import br.ufpr.c3sl.agendador.agendador.helpers.EventDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.SchedulingDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.decorators.SchedulesDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.decorators.NotAvailableDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
import br.ufpr.c3sl.agendador.agendador.models.ServiceLocation;
import br.ufpr.c3sl.agendador.agendador.presenters.SchedulingPresenter;
......@@ -27,9 +28,9 @@ public class LocationSpinnerListener implements AdapterView.OnItemSelectedListen
private List<ServiceLocation> serviceLocations;
private EventDecorator decorator;
private SchedulesDecorator schedulesDecorator;
private SchedulingDecorator schedulingDecorator;
private NotAvailableDecorator notAvailableDecorator;
private MaterialCalendarView mcv;
......@@ -58,8 +59,8 @@ public class LocationSpinnerListener implements AdapterView.OnItemSelectedListen
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (userSelect && serviceLocations != null && serviceLocations.size() > 0) {
mcv.setSelectionMode(MaterialCalendarView.SELECTION_MODE_SINGLE);
decorator.setScheduleType(pos);
schedulingDecorator.setScheduleType(pos);
schedulesDecorator.setScheduleType(pos);
notAvailableDecorator.setScheduleType(pos);
mcv.invalidateDecorators();
userSelect = false;
......@@ -81,12 +82,12 @@ public class LocationSpinnerListener implements AdapterView.OnItemSelectedListen
this.userSelect = userSelect;
}
public void setDecorator(EventDecorator decorator) {
this.decorator = decorator;
public void setSchedulesDecorator(SchedulesDecorator schedulesDecorator) {
this.schedulesDecorator = schedulesDecorator;
}
public void setSchedulingDecorator(SchedulingDecorator schedulingDecorator) {
this.schedulingDecorator = schedulingDecorator;
public void setNotAvailableDecorator(NotAvailableDecorator notAvailableDecorator) {
this.notAvailableDecorator = notAvailableDecorator;
}
......
......@@ -4,14 +4,13 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.TextView;
import android.widget.Toast;
import com.prolificinteractive.materialcalendarview.MaterialCalendarView;
import java.util.List;
import br.ufpr.c3sl.agendador.agendador.helpers.EventDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.SchedulingDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.decorators.SchedulesDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.decorators.NotAvailableDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
import br.ufpr.c3sl.agendador.agendador.models.SectorInput;
import br.ufpr.c3sl.agendador.agendador.presenters.SchedulingPresenter;
......@@ -34,9 +33,9 @@ public class SectorSpinnerListener implements AdapterView.OnItemSelectedListener
private String[] days_short, months_short;
private EventDecorator decorator;
private SchedulesDecorator schedulesDecorator;
private SchedulingDecorator schedulingDecorator;
private NotAvailableDecorator notAvailableDecorator;
public SectorSpinnerListener(SchedulingPresenter presenter, List<SectorInput> sectorList, MaterialCalendarView mcv,
TextView calendarHeaderYear, TextView calendarHeaderDayHour, String[] days_short, String[] months_short){
......@@ -63,11 +62,11 @@ public class SectorSpinnerListener implements AdapterView.OnItemSelectedListener
userSelect = false;
Utils.updateCalendarHeaderDate(mcv, tv_calendarHeaderYear, tv_calendarHeaderDayHour, days_short, months_short, null);
if(decorator != null){
decorator.setScheduleType(EventDecorator.INVALID_STATE);
if(schedulesDecorator != null){
schedulesDecorator.setScheduleType(SchedulesDecorator.INVALID_STATE);
}
if(schedulingDecorator != null){
schedulingDecorator.setScheduleType(SchedulingDecorator.INVALID_STATE);
if(notAvailableDecorator != null){
notAvailableDecorator.setScheduleType(NotAvailableDecorator.INVALID_STATE);
}
mcv.invalidateDecorators();
......@@ -76,14 +75,13 @@ public class SectorSpinnerListener implements AdapterView.OnItemSelectedListener
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
public void setDecorator(EventDecorator decorator) {
this.decorator = decorator;
public void setSchedulesDecorator(SchedulesDecorator schedulesDecorator) {
this.schedulesDecorator = schedulesDecorator;
}
public void setSchedulingDecorator(SchedulingDecorator schedulingDecorator) {
this.schedulingDecorator = schedulingDecorator;
public void setNotAvailableDecorator(NotAvailableDecorator notAvailableDecorator) {
this.notAvailableDecorator = notAvailableDecorator;
}
}
......@@ -9,8 +9,8 @@ import com.prolificinteractive.materialcalendarview.MaterialCalendarView;
import java.util.List;
import br.ufpr.c3sl.agendador.agendador.helpers.EventDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.SchedulingDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.decorators.SchedulesDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.decorators.NotAvailableDecorator;
import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
import br.ufpr.c3sl.agendador.agendador.models.ServiceType;
import br.ufpr.c3sl.agendador.agendador.presenters.SchedulingPresenter;
......@@ -33,9 +33,9 @@ public class ServiceTypeSpinnerListener implements AdapterView.OnItemSelectedLis
private String[] days_short, months_short;
private EventDecorator decorator;
private SchedulesDecorator schedulesDecorator;
private SchedulingDecorator schedulingDecorator;
private NotAvailableDecorator notAvailableDecorator;
public ServiceTypeSpinnerListener(SchedulingPresenter presenter, MaterialCalendarView mcv, TextView calendarHeaderYear,
......@@ -62,11 +62,11 @@ public class ServiceTypeSpinnerListener implements AdapterView.OnItemSelectedLis
Utils.updateCalendarHeaderDate(mcv, tv_calendarHeaderYear, tv_calendarHeaderDayHour, days_short, months_short, null);
if(decorator != null){
decorator.setScheduleType(EventDecorator.INVALID_STATE);
if(schedulesDecorator != null){
schedulesDecorator.setScheduleType(SchedulesDecorator.INVALID_STATE);
}
if(schedulingDecorator != null){
schedulingDecorator.setScheduleType(SchedulingDecorator.INVALID_STATE);
if(notAvailableDecorator != null){
notAvailableDecorator.setScheduleType(NotAvailableDecorator.INVALID_STATE);
}
mcv.invalidateDecorators();
......@@ -75,7 +75,6 @@ public class ServiceTypeSpinnerListener implements AdapterView.OnItemSelectedLis
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
public void setServiceTypes(List<ServiceType> serviceTypes) {
......@@ -86,12 +85,12 @@ public class ServiceTypeSpinnerListener implements AdapterView.OnItemSelectedLis
this.userSelect = userSelect;
}
public void setDecorator(EventDecorator decorator) {
this.decorator = decorator;
public void setSchedulesDecorator(SchedulesDecorator schedulesDecorator) {
this.schedulesDecorator = schedulesDecorator;
}
public void setSchedulingDecorator(SchedulingDecorator schedulingDecorator) {
this.schedulingDecorator = schedulingDecorator;
public void setNotAvailableDecorator(NotAvailableDecorator notAvailableDecorator) {
this.notAvailableDecorator = notAvailableDecorator;
}
}