Opening hours editing is working

This commit is contained in:
GaidamakUA 2015-08-27 17:03:32 +03:00
parent 7b188ec97a
commit 885836d923
5 changed files with 357 additions and 88 deletions

View file

@ -2,6 +2,10 @@ package net.osmand.util;
/* Can be commented out in order to run the main function separately */
import net.osmand.PlatformUtil;
import org.apache.commons.logging.Log;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@ -17,6 +21,7 @@ import java.util.Calendar;
* if the OSM feature is open at a certain time.
*/
public class OpeningHoursParser {
private static final Log LOG = PlatformUtil.getLog(OpeningHoursParser.class);
private static final String[] daysStr = new String[] {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
private static final String[] monthsStr = new String[] {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
@ -612,7 +617,8 @@ public class OpeningHoursParser {
String timeSubstr = r.substring(k);
String[] times = timeSubstr.split(",");
boolean timesExist = true;
for (String time : times) {
for (int i = 0; i < times.length; i++) {
String time = times[i];
time = time.trim();
if(time.length() == 0){
continue;
@ -627,6 +633,9 @@ public class OpeningHoursParser {
}
String[] stEnd = time.split("-"); //$NON-NLS-1$
if (stEnd.length != 2) {
if (i == times.length - 1 && basic.getStartTime() == 0 && basic.getEndTime() == 0) {
return false;
}
continue;
}
timesExist = true;

View file

@ -19,8 +19,8 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp"
android:orientation="vertical"
android:layout_weight="1">
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/daysTextView"
@ -35,45 +35,52 @@
</LinearLayout>
<LinearLayout
android:id="@+id/timeContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical">
android:gravity="center_vertical">
<TextView
android:id="@+id/openingTextView"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="08:00"/>
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/openingTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="08:00"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider_color"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_width="16dp"
android:layout_height="1dp"
android:background="@color/divider_color"/>
</LinearLayout>
<View
android:layout_width="16dp"
android:layout_height="1dp"
android:background="@color/divider_color"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/closingTextView"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="20:00"/>
android:layout_marginLeft="16dp"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider_color"/>
<TextView
android:id="@+id/closingTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="20:00"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider_color"/>
</LinearLayout>
</LinearLayout>
<ImageButton

View file

@ -30,6 +30,8 @@ import net.osmand.util.OpeningHoursParser.BasicOpeningHourRule;
import org.apache.commons.logging.Log;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
@ -82,8 +84,11 @@ public class BasicDataFragment extends Fragment {
addOpeningHoursButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
BasicOpeningHourRule r = new BasicOpeningHourRule();
OpeningHoursDaysDialogFragment fragment = OpeningHoursDaysDialogFragment.createInstance(r, -1);
BasicOpeningHourRule rule = new BasicOpeningHourRule();
// TODO: 8/27/15 Figure out some better defauls or leave it as it is
rule.setStartTime(9 * 60);
rule.setEndTime(18 * 60);
OpeningHoursDaysDialogFragment fragment = OpeningHoursDaysDialogFragment.createInstance(rule, -1);
fragment.show(getChildFragmentManager(), "OpenTimeDialogFragment");
}
});
@ -145,9 +150,9 @@ public class BasicDataFragment extends Fragment {
super.onSaveInstanceState(outState);
}
public void addBasicOpeningHoursRule(BasicOpeningHourRule item) {
public void setBasicOpeningHoursRule(BasicOpeningHourRule item, int position) {
LOG.debug("item=" + item.toRuleString(false));
mOpeningHoursAdapter.addOpeningHoursRule(item);
mOpeningHoursAdapter.setOpeningHoursRule(item, position);
}
private static class TagMapProcessor {
@ -206,12 +211,14 @@ public class BasicDataFragment extends Fragment {
@Override
public void process(Tag tag) {
String openingHoursString = tag.value;
LOG.debug("openingHoursString=" + openingHoursString);
OpeningHoursParser.OpeningHours openingHours =
OpeningHoursParser.parseOpenedHours(openingHoursString);
parseOpenedHoursHandleErrors(openingHoursString);
if (openingHours == null) {
openingHours = new OpeningHoursParser.OpeningHours();
// TODO show error message
}
LOG.debug("openingHours=" + openingHours);
adapter.replaceOpeningHours(openingHours);
adapter.updateViews();
}
@ -230,6 +237,216 @@ public class BasicDataFragment extends Fragment {
return getEditPoiFragment().getEditPoiData();
}
private static String formatTime(int h, int t) {
StringBuilder b = new StringBuilder();
if (h < 10) {
b.append("0"); //$NON-NLS-1$
}
b.append(h).append(":"); //$NON-NLS-1$
if (t < 10) {
b.append("0"); //$NON-NLS-1$
}
b.append(t);
return b.toString();
}
private static OpeningHoursParser.OpeningHours parseOpenedHoursHandleErrors(String format){
if(format == null) {
return null;
}
String[] rules = format.split(";"); //$NON-NLS-1$
OpeningHoursParser.OpeningHours rs = new OpeningHoursParser.OpeningHours();
for(String r : rules){
r = r.trim();
if (r.length() == 0) {
continue;
}
// check if valid
rs.addRule(parseRule(r));
}
return rs;
}
// TODO: 8/27/15 Consider refactoring OpeningHoursParser
public static OpeningHoursParser.OpeningHoursRule parseRule(final String r){
// replace words "sunrise" and "sunset" by real hours
final String[] daysStr = new String[] {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"};
final String[] monthsStr = new String[] {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
String sunrise = "07:00";
String sunset = "21:00";
String endOfDay = "24:00";
String localRuleString = r.replaceAll("sunset", sunset).replaceAll("sunrise", sunrise)
.replaceAll("\\+", "-" + endOfDay);
int startDay = -1;
int previousDay = -1;
int startMonth = -1;
int previousMonth = -1;
int k = 0; // Position in opening_hours string
BasicOpeningHourRule basic = new BasicOpeningHourRule();
boolean[] days = basic.getDays();
boolean[] months = basic.getMonths();
// check 24/7
if("24/7".equals(localRuleString)){
Arrays.fill(days, true);
Arrays.fill(months, true);
basic.addTimeRange(0, 24 * 60);
return basic;
}
for (; k < localRuleString.length(); k++) {
char ch = localRuleString.charAt(k);
if (Character.isDigit(ch)) {
// time starts
break;
}
if ((k + 2 < localRuleString.length())
&& localRuleString.substring(k, k + 3).equals("off")) {
// value "off" is found
break;
}
if(Character.isWhitespace(ch) || ch == ','){
} else if (ch == '-') {
if(previousDay != -1){
startDay = previousDay;
} else if (previousMonth != -1) {
startMonth = previousMonth;
} else {
return new UnparseableRule(r);
}
} else if (k < r.length() - 1) {
int i = 0;
for(String s : daysStr){
if(s.charAt(0) == ch && s.charAt(1) == r.charAt(k+1)){
break;
}
i++;
}
if(i < daysStr.length){
if(startDay != -1){
for (int j = startDay; j <= i; j++) {
days[j] = true;
}
if(startDay > i){// overflow handling, e.g. Su-We
for (int j = startDay; j <= 6; j++) {
days[j] = true;
}
for (int j = 0; j <= i; j++){
days[j] = true;
}
}
startDay = -1;
} else {
days[i] = true;
}
previousDay = i;
} else {
// Read Month
int m = 0;
for (String s : monthsStr) {
if (s.charAt(0) == ch && s.charAt(1) == r.charAt(k + 1)
&& s.charAt(2) == r.charAt(k + 2)) {
break;
}
m++;
}
if (m < monthsStr.length) {
if (startMonth != -1) {
for (int j = startMonth; j <= m; j++) {
months[j] = true;
}
if (startMonth > m) {// overflow handling, e.g. Oct-Mar
for (int j = startMonth; j <= 11; j++) {
months[j] = true;
}
for (int j = 0; j <= m; j++) {
months[j] = true;
}
}
startMonth = -1;
} else {
months[m] = true;
}
previousMonth = m;
}
}
} else {
return new UnparseableRule(r);
}
}
if(previousDay == -1){
// no days given => take all days.
for (int i = 0; i<7; i++){
days[i] = true;
}
}
if (previousMonth == -1) {
// no month given => take all months.
for (int i = 0; i < 12; i++) {
months[i] = true;
}
}
String timeSubstr = localRuleString.substring(k);
String[] times = timeSubstr.split(",");
boolean timesExist = true;
for (int i = 0; i < times.length; i++) {
String time = times[i];
time = time.trim();
if(time.length() == 0){
continue;
}
if(time.equals("off")){
break; // add no time values
}
if(time.equals("24/7")){
// for some reason, this is used. See tagwatch.
basic.addTimeRange(0, 24*60);
break;
}
String[] stEnd = time.split("-"); //$NON-NLS-1$
if (stEnd.length != 2) {
if (i == times.length - 1 && basic.getStartTime() == 0 && basic.getEndTime() == 0) {
return new UnparseableRule(r);
}
continue;
}
timesExist = true;
int st;
int end;
try {
int i1 = stEnd[0].indexOf(':');
int i2 = stEnd[1].indexOf(':');
int startHour, startMin, endHour, endMin;
if(i1 == -1) {
// if no minutes are given, try complete value as hour
startHour = Integer.parseInt(stEnd[0].trim());
startMin = 0;
} else {
startHour = Integer.parseInt(stEnd[0].substring(0, i1).trim());
startMin = Integer.parseInt(stEnd[0].substring(i1 + 1).trim());
}
if(i2 == -1) {
// if no minutes are given, try complete value as hour
endHour = Integer.parseInt(stEnd[1].trim());
endMin = 0;
} else {
endHour = Integer.parseInt(stEnd[1].substring(0, i2).trim());
endMin = Integer.parseInt(stEnd[1].substring(i2 + 1).trim());
}
st = startHour * 60 + startMin;
end = endHour * 60 + endMin;
} catch (NumberFormatException e) {
return new UnparseableRule(r);
}
basic.addTimeRange(st, end);
}
if(!timesExist){
return new UnparseableRule(r);
}
return basic;
}
private class MyOnFocusChangeListener implements TextWatcher {
private final EditPoiData data;
private final String tagName;
@ -279,8 +496,12 @@ public class BasicDataFragment extends Fragment {
this.deleteDrawable = deleteDrawable;
}
public void addOpeningHoursRule(OpeningHoursParser.BasicOpeningHourRule rule) {
openingHours.addRule(rule);
public void setOpeningHoursRule(OpeningHoursParser.BasicOpeningHourRule rule, int position) {
if (position == -1) {
openingHours.addRule(rule);
} else {
openingHours.getRules().set(position, rule);
}
updateViews();
}
@ -303,28 +524,46 @@ public class BasicDataFragment extends Fragment {
}
private View getView(final int position) {
OpeningHoursParser.BasicOpeningHourRule rule =
(BasicOpeningHourRule) openingHours.getRules().get(position);
final View view = LayoutInflater.from(linearLayout.getContext())
.inflate(R.layout.open_time_list_item, null, false);
ImageView clockIconImageView = (ImageView) view.findViewById(R.id.clockIconImageView);
clockIconImageView.setImageDrawable(clockDrawable);
TextView daysTextView = (TextView) view.findViewById(R.id.daysTextView);
StringBuilder stringBuilder = new StringBuilder();
rule.appendDaysString(stringBuilder);
daysTextView.setText(stringBuilder.toString());
View timeContainer = view.findViewById(R.id.timeContainer);
TextView openingTextView = (TextView) view.findViewById(R.id.openingTextView);
final int openingHour = rule.getStartTime() / 60;
int openingMinute = rule.getStartTime() - openingHour * 60;
openingTextView.setText(formatTime(openingHour, openingMinute));
if (openingHours.getRules().get(position) instanceof BasicOpeningHourRule) {
final OpeningHoursParser.BasicOpeningHourRule rule =
(BasicOpeningHourRule) openingHours.getRules().get(position);
StringBuilder stringBuilder = new StringBuilder();
rule.appendDaysString(stringBuilder);
TextView closingTextView = (TextView) view.findViewById(R.id.closingTextView);
int enHour = rule.getEndTime() / 60;
int enTime = rule.getEndTime() - enHour * 60;
closingTextView.setText(formatTime(enHour, enTime));
daysTextView.setText(stringBuilder.toString());
TextView openingTextView = (TextView) view.findViewById(R.id.openingTextView);
final int openingHour = rule.getStartTime() / 60;
int openingMinute = rule.getStartTime() - openingHour * 60;
openingTextView.setText(formatTime(openingHour, openingMinute));
TextView closingTextView = (TextView) view.findViewById(R.id.closingTextView);
int enHour = rule.getEndTime() / 60;
int enTime = rule.getEndTime() - enHour * 60;
closingTextView.setText(formatTime(enHour, enTime));
timeContainer.setVisibility(View.VISIBLE);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
OpeningHoursDaysDialogFragment fragment =
OpeningHoursDaysDialogFragment.createInstance(rule, position);
fragment.show(getChildFragmentManager(), "OpenTimeDialogFragment");
}
});
} else if (openingHours.getRules().get(position) instanceof UnparseableRule) {
daysTextView.setText(openingHours.getRules().get(position).toRuleString(false));
timeContainer.setVisibility(View.GONE);
}
ImageButton deleteItemImageButton = (ImageButton) view.findViewById(R.id.deleteItemImageButton);
deleteItemImageButton.setImageDrawable(deleteDrawable);
@ -338,16 +577,38 @@ public class BasicDataFragment extends Fragment {
return view;
}
}
private static String formatTime(int h, int t) {
StringBuilder b = new StringBuilder();
if (h < 10) {
b.append("0"); //$NON-NLS-1$
// TODO: 8/27/15 Consider moving to OpeningHoursParser
private static class UnparseableRule implements OpeningHoursParser.OpeningHoursRule {
private String ruleString;
public UnparseableRule(String ruleString) {
this.ruleString = ruleString;
}
b.append(h).append(":"); //$NON-NLS-1$
if (t < 10) {
b.append("0"); //$NON-NLS-1$
@Override
public boolean isOpenedForTime(Calendar cal, boolean checkPrevious) {
return false;
}
@Override
public boolean containsPreviousDay(Calendar cal) {
return false;
}
@Override
public boolean containsDay(Calendar cal) {
return false;
}
@Override
public boolean containsMonth(Calendar cal) {
return false;
}
@Override
public String toRuleString(boolean avoidMonths) {
return ruleString;
}
b.append(t);
return b.toString();
}
}

View file

@ -63,17 +63,9 @@ public class OpeningHoursDaysDialogFragment extends DialogFragment {
for (int i = 0; i < 7; i++) {
days[(first + 5 + i) % 7] = dayToShow[i];
}
OpeningHoursHoursDialogFragment.createInstance(item, null, true)
OpeningHoursHoursDialogFragment.createInstance(item, positionToAdd, true)
.show(getFragmentManager(), "TimePickerDialogFragment");
if (positionToAdd != -1) {
// time.insert(item, positionToAdd);
// selectedRule = positionToAdd;
} else {
// time.notifyDataSetChanged();
}
// updateTimePickers();
}
});
@ -82,8 +74,9 @@ public class OpeningHoursDaysDialogFragment extends DialogFragment {
return builder.create();
}
public static OpeningHoursDaysDialogFragment createInstance(final OpeningHoursParser.BasicOpeningHourRule item,
final int positionToAdd) {
public static OpeningHoursDaysDialogFragment createInstance(
@NonNull final OpeningHoursParser.BasicOpeningHourRule item,
final int positionToAdd) {
LOG.debug("createInstance(" + "item=" + item + ", positionToAdd=" + positionToAdd + ")");
OpeningHoursDaysDialogFragment daysDialogFragment = new OpeningHoursDaysDialogFragment();
Bundle bundle = new Bundle();

View file

@ -17,34 +17,30 @@ import net.osmand.plus.R;
import net.osmand.plus.osmedit.BasicDataFragment;
import net.osmand.util.OpeningHoursParser;
import java.util.Calendar;
public class OpeningHoursHoursDialogFragment extends DialogFragment {
public static final String INITIAL_TIME = "initial_time";
public static final String IS_START = "is_start";
public static final String BASIC_OPENING_HOUR_RULE = "basic_opening_hour_rule";
public static final String POSITION_TO_ADD = "position_to_add";
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle args = getArguments();
final boolean isStart = args.getBoolean(IS_START);
final int positionToAdd = args.getInt(POSITION_TO_ADD);
final OpeningHoursParser.BasicOpeningHourRule item = (OpeningHoursParser.BasicOpeningHourRule)
args.getSerializable(BASIC_OPENING_HOUR_RULE);
AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity());
Calendar initialState = (Calendar) args.getSerializable(INITIAL_TIME);
if (initialState == null) {
initialState = Calendar.getInstance();
initialState.set(Calendar.HOUR_OF_DAY, isStart? 8 : 20);
initialState.set(Calendar.MINUTE, 0);
}
int time = isStart ? item.getStartTime() : item.getEndTime();
int hour = time / 60;
int minute = time - hour * 60;
final TimePicker timePicker = new TimePicker(getActivity());
timePicker.setIs24HourView(DateFormat.is24HourFormat(getActivity()));
timePicker.setCurrentHour(initialState.get(Calendar.HOUR_OF_DAY));
timePicker.setCurrentMinute(initialState.get(Calendar.MINUTE));
timePicker.setCurrentHour(hour);
timePicker.setCurrentMinute(minute);
builder.setView(timePicker)
.setPositiveButton(R.string.next_proceed, new DialogInterface.OnClickListener() {
@ -55,11 +51,13 @@ public class OpeningHoursHoursDialogFragment extends DialogFragment {
int time = minute + hourOfDay * 60;
if (isStart) {
item.setStartTime(time);
OpeningHoursHoursDialogFragment.createInstance(item, null, false)
OpeningHoursHoursDialogFragment
.createInstance(item, positionToAdd, false)
.show(getFragmentManager(), "TimePickerDialogFragment");
} else {
item.setEndTime(time);
((BasicDataFragment) getParentFragment()).addBasicOpeningHoursRule(item);
((BasicDataFragment) getParentFragment())
.setBasicOpeningHoursRule(item, positionToAdd);
}
}
})
@ -82,14 +80,15 @@ public class OpeningHoursHoursDialogFragment extends DialogFragment {
return builder.create();
}
public static OpeningHoursHoursDialogFragment createInstance(OpeningHoursParser.BasicOpeningHourRule item,
Calendar initialTime,
boolean isStart) {
public static OpeningHoursHoursDialogFragment createInstance(
@NonNull OpeningHoursParser.BasicOpeningHourRule item,
int positionToAdd,
boolean isStart) {
OpeningHoursHoursDialogFragment fragment = new OpeningHoursHoursDialogFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(BASIC_OPENING_HOUR_RULE, item);
bundle.putSerializable(POSITION_TO_ADD, positionToAdd);
bundle.putBoolean(IS_START, isStart);
bundle.putSerializable(INITIAL_TIME, initialTime);
fragment.setArguments(bundle);
return fragment;
}