forked from organicmaps/organicmaps
[android] Editor UI
This commit is contained in:
parent
dfefd19efe
commit
24eb7eddb4
8 changed files with 982 additions and 7 deletions
|
@ -15,6 +15,7 @@ import android.support.v4.app.Fragment;
|
|||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
@ -42,6 +43,7 @@ import com.mapswithme.maps.bookmarks.ChooseBookmarkCategoryFragment;
|
|||
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
|
||||
import com.mapswithme.maps.bookmarks.data.MapObject;
|
||||
import com.mapswithme.maps.bookmarks.data.MapObject.ApiPoint;
|
||||
import com.mapswithme.maps.bookmarks.data.Metadata;
|
||||
import com.mapswithme.maps.editor.EditorActivity;
|
||||
import com.mapswithme.maps.editor.EditorFragment;
|
||||
import com.mapswithme.maps.location.LocationHelper;
|
||||
|
@ -64,6 +66,7 @@ import com.mapswithme.maps.widget.menu.MainMenu;
|
|||
import com.mapswithme.maps.widget.placepage.BasePlacePageAnimationController;
|
||||
import com.mapswithme.maps.widget.placepage.PlacePageView;
|
||||
import com.mapswithme.maps.widget.placepage.PlacePageView.State;
|
||||
import com.mapswithme.maps.widget.placepage.TimetableFragment;
|
||||
import com.mapswithme.util.Animations;
|
||||
import com.mapswithme.util.BottomSheetHelper;
|
||||
import com.mapswithme.util.Config;
|
||||
|
@ -99,7 +102,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
private static final String[] DOCKED_FRAGMENTS = { SearchFragment.class.getName(),
|
||||
DownloadFragment.class.getName(),
|
||||
RoutingPlanFragment.class.getName(),
|
||||
EditorFragment.class.getName() };
|
||||
TimetableFragment.class.getName() };
|
||||
// Instance state
|
||||
private static final String STATE_PP_OPENED = "PpOpened";
|
||||
private static final String STATE_MAP_OBJECT = "MapObject";
|
||||
|
@ -252,11 +255,14 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
|
||||
public void showEditor(MapObject point)
|
||||
{
|
||||
final String openingTime = point.getMetadata(Metadata.MetadataType.FMD_OPEN_HOURS);
|
||||
// TODO use EditorFragment after is will be finished
|
||||
if (mIsFragmentContainer)
|
||||
{
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(EditorFragment.EXTRA_POINT, point);
|
||||
replaceFragment(EditorFragment.class, args, null);
|
||||
if (!TextUtils.isEmpty(openingTime))
|
||||
args.putString(TimetableFragment.EXTRA_TIME, openingTime);
|
||||
replaceFragment(TimetableFragment.class, args, null);
|
||||
}
|
||||
else
|
||||
EditorActivity.start(this, point);
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.mapswithme.maps.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.View;
|
||||
|
||||
import com.mapswithme.maps.widget.ToolbarController;
|
||||
|
||||
public class BaseMwmToolbarFragment extends BaseMwmFragment
|
||||
{
|
||||
protected ToolbarController mToolbarController;
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mToolbarController = onCreateToolbarController(view);
|
||||
}
|
||||
|
||||
protected ToolbarController onCreateToolbarController(@NonNull View root)
|
||||
{
|
||||
return new ToolbarController(root, getActivity());
|
||||
}
|
||||
}
|
|
@ -3,29 +3,37 @@ package com.mapswithme.maps.editor;
|
|||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mapswithme.maps.base.BaseMwmFragmentActivity;
|
||||
import com.mapswithme.maps.bookmarks.data.MapObject;
|
||||
import com.mapswithme.maps.bookmarks.data.Metadata;
|
||||
import com.mapswithme.maps.widget.placepage.TimetableFragment;
|
||||
|
||||
public class EditorActivity extends BaseMwmFragmentActivity
|
||||
{
|
||||
@Override
|
||||
protected Class<? extends Fragment> getFragmentClass()
|
||||
{
|
||||
return EditorFragment.class;
|
||||
// TODO use EditorFragment after is will be finished
|
||||
return TimetableFragment.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed()
|
||||
{
|
||||
final EditorFragment fragment = (EditorFragment)getSupportFragmentManager().findFragmentByTag(getFragmentClass().getName());
|
||||
final TimetableFragment fragment = (TimetableFragment) getSupportFragmentManager().findFragmentByTag(getFragmentClass().getName());
|
||||
if ((fragment == null) || !fragment.isAdded() || !fragment.onBackPressed())
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
public static void start(Activity activity, MapObject point)
|
||||
{
|
||||
activity.startActivity(new Intent(activity, EditorActivity.class)
|
||||
.putExtra(EditorFragment.EXTRA_POINT, point));
|
||||
final Intent intent = new Intent(activity, EditorActivity.class);
|
||||
final String openHours = point.getMetadata(Metadata.MetadataType.FMD_OPEN_HOURS);
|
||||
if (!TextUtils.isEmpty(openHours))
|
||||
intent.putExtra(TimetableFragment.EXTRA_TIME, openHours);
|
||||
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
package com.mapswithme.maps.widget.placepage;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.base.BaseMwmFragment;
|
||||
import com.mapswithme.maps.editor.OpeningHours;
|
||||
import com.mapswithme.maps.editor.data.Timetable;
|
||||
import com.mapswithme.util.UiUtils;
|
||||
|
||||
public class AdvancedTimetableFragment extends BaseMwmFragment
|
||||
implements View.OnClickListener,
|
||||
TimetableFragment.TimetableProvider
|
||||
{
|
||||
private boolean mIsExampleShown;
|
||||
private EditText mInput;
|
||||
private View mExample;
|
||||
private ImageView mIndicator;
|
||||
private Timetable[] mInitTimetables;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
return inflater.inflate(R.layout.fragment_timetable_advanced, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
initViews(view);
|
||||
refreshTimetables();
|
||||
showExample(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
refreshTimetables();
|
||||
}
|
||||
|
||||
private void initViews(View view)
|
||||
{
|
||||
view.findViewById(R.id.examples).setOnClickListener(this);
|
||||
mInput = (EditText) view.findViewById(R.id.et__timetable);
|
||||
mExample = view.findViewById(R.id.tv__examples);
|
||||
mIndicator = (ImageView) view.findViewById(R.id.iv__indicator);
|
||||
}
|
||||
|
||||
private void showExample(boolean show)
|
||||
{
|
||||
mIsExampleShown = show;
|
||||
if (mIsExampleShown)
|
||||
{
|
||||
UiUtils.show(mExample);
|
||||
// TODO yunikkk animate indicator
|
||||
mIndicator.setImageResource(R.drawable.ic_expand_less);
|
||||
}
|
||||
else
|
||||
{
|
||||
UiUtils.hide(mExample);
|
||||
mIndicator.setImageResource(R.drawable.ic_expand_more);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.examples:
|
||||
showExample(!mIsExampleShown);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timetable[] getTimetables()
|
||||
{
|
||||
if (mInput.length() == 0)
|
||||
return OpeningHours.nativeGetDefaultTimetables();
|
||||
return OpeningHours.nativeTimetablesFromString(mInput.getText().toString());
|
||||
}
|
||||
|
||||
public void setTimetables(Timetable[] timetables)
|
||||
{
|
||||
mInitTimetables = timetables;
|
||||
refreshTimetables();
|
||||
}
|
||||
|
||||
private void refreshTimetables()
|
||||
{
|
||||
if (mInput != null && mInitTimetables != null)
|
||||
mInput.setText(OpeningHours.nativeTimetablesToString(mInitTimetables));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
package com.mapswithme.maps.widget.placepage;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IntRange;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TimePicker;
|
||||
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.base.BaseMwmDialogFragment;
|
||||
import com.mapswithme.maps.editor.data.HoursMinutes;
|
||||
|
||||
public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
|
||||
{
|
||||
private static final String EXTRA_FROM = "HoursMinutesFrom";
|
||||
private static final String EXTRA_TO = "HoursMinutesTo";
|
||||
private static final String EXTRA_SELECT_FIRST = "SelectedTab";
|
||||
private static final String EXTRA_ID = "Id";
|
||||
|
||||
public static final int TAB_FROM = 0;
|
||||
public static final int TAB_TO = 1;
|
||||
|
||||
private HoursMinutes mFrom;
|
||||
private HoursMinutes mTo;
|
||||
|
||||
private TimePicker mPicker;
|
||||
@IntRange(from = 0, to = 1) private int mSelectedTab;
|
||||
private TabLayout mTabs;
|
||||
|
||||
private int mId;
|
||||
|
||||
public interface OnPickListener
|
||||
{
|
||||
void onHoursMinutesPicked(HoursMinutes from, HoursMinutes to, int id);
|
||||
}
|
||||
|
||||
public static void pick(Context context, FragmentManager manager, @NonNull HoursMinutes from, @NonNull HoursMinutes to,
|
||||
@IntRange(from = 0, to = 1) int selectedPosition, int id)
|
||||
{
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(EXTRA_FROM, from);
|
||||
args.putParcelable(EXTRA_TO, to);
|
||||
args.putInt(EXTRA_SELECT_FIRST, selectedPosition);
|
||||
args.putInt(EXTRA_ID, id);
|
||||
final HoursMinutesPickerFragment fragment = (HoursMinutesPickerFragment) Fragment.instantiate(context, HoursMinutesPickerFragment.class.getName(), args);
|
||||
fragment.show(manager, null);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState)
|
||||
{
|
||||
readArgs();
|
||||
final View root = createView();
|
||||
refreshPicker();
|
||||
//noinspection ConstantConditions
|
||||
mTabs.getTabAt(mSelectedTab).select();
|
||||
|
||||
return new AlertDialog.Builder(getActivity(), R.style.MwmMain_DialogFragment_TimePicker)
|
||||
.setView(root)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
saveHoursMinutes(mPicker.getCurrentHour(), mPicker.getCurrentMinute());
|
||||
if (getParentFragment() instanceof OnPickListener)
|
||||
((OnPickListener) getParentFragment()).onHoursMinutesPicked(mFrom, mTo, mId);
|
||||
}
|
||||
})
|
||||
.setCancelable(true)
|
||||
.create();
|
||||
}
|
||||
|
||||
private void readArgs()
|
||||
{
|
||||
final Bundle args = getArguments();
|
||||
mFrom = args.getParcelable(EXTRA_FROM);
|
||||
mTo = args.getParcelable(EXTRA_TO);
|
||||
mSelectedTab = args.getInt(EXTRA_SELECT_FIRST);
|
||||
mId = args.getInt(EXTRA_ID);
|
||||
}
|
||||
|
||||
private View createView()
|
||||
{
|
||||
final LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||
@SuppressLint("InflateParams")
|
||||
final View root = inflater.inflate(R.layout.fragment_timetable_picker, null);
|
||||
|
||||
mTabs = (TabLayout) root.findViewById(R.id.tabs);
|
||||
TextView tabView = (TextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
|
||||
// TODO @yunik add translations
|
||||
tabView.setText("From");
|
||||
mTabs.addTab(mTabs.newTab().setCustomView(tabView), true);
|
||||
tabView = (TextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
|
||||
tabView.setText("To");
|
||||
mTabs.addTab(mTabs.newTab().setCustomView(tabView), true);
|
||||
mTabs.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
|
||||
{
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab)
|
||||
{
|
||||
mSelectedTab = tab.getPosition();
|
||||
refreshPicker();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab)
|
||||
{
|
||||
saveHoursMinutes(mPicker.getCurrentHour(), mPicker.getCurrentMinute());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {}
|
||||
});
|
||||
|
||||
mPicker = (TimePicker) root.findViewById(R.id.picker);
|
||||
mPicker.setIs24HourView(DateFormat.is24HourFormat(getActivity()));
|
||||
mPicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener()
|
||||
{
|
||||
@Override
|
||||
public void onTimeChanged(TimePicker view, int hourOfDay, int minute)
|
||||
{
|
||||
saveHoursMinutes(hourOfDay, minute);
|
||||
}
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void saveHoursMinutes(int hourOfDay, int minute)
|
||||
{
|
||||
if (mSelectedTab == TAB_FROM)
|
||||
mFrom = new HoursMinutes(hourOfDay, minute);
|
||||
else
|
||||
mTo = new HoursMinutes(hourOfDay, minute);
|
||||
}
|
||||
|
||||
private void refreshPicker()
|
||||
{
|
||||
final HoursMinutes hoursMinutes = mSelectedTab == TAB_FROM ? mFrom : mTo;
|
||||
mPicker.setCurrentMinute((int) hoursMinutes.minutes);
|
||||
mPicker.setCurrentHour((int) hoursMinutes.hours);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,456 @@
|
|||
package com.mapswithme.maps.widget.placepage;
|
||||
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.editor.OpeningHours;
|
||||
import com.mapswithme.maps.editor.data.HoursMinutes;
|
||||
import com.mapswithme.maps.editor.data.Timespan;
|
||||
import com.mapswithme.maps.editor.data.Timetable;
|
||||
import com.mapswithme.util.UiUtils;
|
||||
|
||||
public class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter.BaseTimetableViewHolder>
|
||||
implements HoursMinutesPickerFragment.OnPickListener,
|
||||
TimetableFragment.TimetableProvider
|
||||
{
|
||||
private static final int TYPE_TIMETABLE = 0;
|
||||
private static final int TYPE_ADD_TIMETABLE = 1;
|
||||
|
||||
private static final int ID_OPENING = 0;
|
||||
private static final int ID_CLOSED = 1;
|
||||
|
||||
private final Fragment mFragment;
|
||||
|
||||
private List<Timetable> mItems = new ArrayList<>();
|
||||
private Timetable mComplementItem;
|
||||
private int mPickingPosition;
|
||||
|
||||
SimpleTimetableAdapter(Fragment fragment)
|
||||
{
|
||||
mFragment = fragment;
|
||||
mItems = new ArrayList<>(Arrays.asList(OpeningHours.nativeGetDefaultTimetables()));
|
||||
}
|
||||
|
||||
public void setTimetables(Timetable[] tts)
|
||||
{
|
||||
mItems = new ArrayList<>(Arrays.asList(tts));
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timetable[] getTimetables()
|
||||
{
|
||||
return mItems.toArray(new Timetable[mItems.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseTimetableViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
|
||||
{
|
||||
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
return viewType == TYPE_TIMETABLE ? new TimetableViewHolder(inflater.inflate(R.layout.item_timetable, parent, false))
|
||||
: new AddTimetableViewHolder(inflater.inflate(R.layout.item_timetable_add, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(BaseTimetableViewHolder holder, int position)
|
||||
{
|
||||
holder.onBind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount()
|
||||
{
|
||||
return mItems.size() + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position)
|
||||
{
|
||||
return position == getItemCount() - 1 ? TYPE_ADD_TIMETABLE
|
||||
: TYPE_TIMETABLE;
|
||||
}
|
||||
|
||||
protected void addTimetable()
|
||||
{
|
||||
mItems.add(OpeningHours.nativeGetComplementTimetable(mItems.toArray(new Timetable[mItems.size()])));
|
||||
printItems();
|
||||
notifyItemInserted(mItems.size() - 1);
|
||||
refreshComplement();
|
||||
}
|
||||
|
||||
protected void removeTimetable(int position)
|
||||
{
|
||||
mItems.remove(position);
|
||||
printItems();
|
||||
notifyItemRemoved(position);
|
||||
refreshComplement();
|
||||
}
|
||||
|
||||
protected void refreshComplement()
|
||||
{
|
||||
mComplementItem = OpeningHours.nativeGetComplementTimetable(mItems.toArray(new Timetable[mItems.size()]));
|
||||
notifyItemChanged(getItemCount() - 1);
|
||||
}
|
||||
|
||||
protected void pickOpeningTime(int position, int tab)
|
||||
{
|
||||
final Timetable data = mItems.get(position);
|
||||
mPickingPosition = position;
|
||||
HoursMinutesPickerFragment.pick(mFragment.getActivity(), mFragment.getChildFragmentManager(),
|
||||
data.workingTimespan.start, data.workingTimespan.end,
|
||||
tab, ID_OPENING);
|
||||
}
|
||||
|
||||
protected void pickClosedHours(int position)
|
||||
{
|
||||
final Timetable data = mItems.get(position);
|
||||
mPickingPosition = position;
|
||||
HoursMinutesPickerFragment.pick(mFragment.getActivity(), mFragment.getChildFragmentManager(),
|
||||
data.workingTimespan.start, data.workingTimespan.end,
|
||||
0, ID_CLOSED);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onHoursMinutesPicked(HoursMinutes from, HoursMinutes to, int id)
|
||||
{
|
||||
final Timetable item = mItems.get(mPickingPosition);
|
||||
if (id == ID_OPENING)
|
||||
mItems.set(mPickingPosition, OpeningHours.nativeSetOpeningTime(item, new Timespan(from, to)));
|
||||
else
|
||||
mItems.set(mPickingPosition, OpeningHours.nativeAddClosedSpan(item, new Timespan(from, to)));
|
||||
notifyItemChanged(mPickingPosition);
|
||||
}
|
||||
|
||||
private void removeClosedHours(int position, int closedPosition)
|
||||
{
|
||||
mItems.set(position, OpeningHours.nativeRemoveClosedSpan(mItems.get(position), closedPosition));
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
protected void addWorkingDay(int day, int position)
|
||||
{
|
||||
final Timetable tts[] = mItems.toArray(new Timetable[mItems.size()]);
|
||||
mItems = new ArrayList<>(Arrays.asList(OpeningHours.nativeAddWorkingDay(tts, position, day)));
|
||||
refreshComplement();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
protected void removeWorkingDay(int day, int position)
|
||||
{
|
||||
final Timetable tts[] = mItems.toArray(new Timetable[mItems.size()]);
|
||||
mItems = new ArrayList<>(Arrays.asList(OpeningHours.nativeRemoveWorkingDay(tts, position, day)));
|
||||
refreshComplement();
|
||||
printItems();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
// FIXME remove
|
||||
private void printItems()
|
||||
{
|
||||
Log.d("TEST", "Items : \n");
|
||||
for (Timetable tt : mItems)
|
||||
Log.d("TEST", tt.toString() + "\n");
|
||||
}
|
||||
|
||||
private void setFullday(int position, boolean fullday)
|
||||
{
|
||||
mItems.set(position, OpeningHours.nativeSetIsFullday(mItems.get(position), fullday));
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
public abstract class BaseTimetableViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
public BaseTimetableViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
abstract void onBind();
|
||||
}
|
||||
|
||||
public class TimetableViewHolder extends BaseTimetableViewHolder implements View.OnClickListener, CompoundButton.OnCheckedChangeListener
|
||||
{
|
||||
// Limit closed spans to avoid dynamic inflation of views in recycler's children. Yeah, its a hack.
|
||||
static final int MAX_CLOSED_SPANS = 10;
|
||||
|
||||
TextView day1Text;
|
||||
TextView day2Text;
|
||||
TextView day3Text;
|
||||
TextView day4Text;
|
||||
TextView day5Text;
|
||||
TextView day6Text;
|
||||
TextView day7Text;
|
||||
SparseArray<CheckBox> days = new SparseArray<>(7);
|
||||
View allday;
|
||||
SwitchCompat swAllday;
|
||||
View schedule;
|
||||
View openClose;
|
||||
View open;
|
||||
View close;
|
||||
TextView tvOpen;
|
||||
TextView tvClose;
|
||||
View closedHours[] = new View[MAX_CLOSED_SPANS];
|
||||
View addClosed;
|
||||
View deleteTimetable;
|
||||
|
||||
public TimetableViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
addDay(R.id.chb__day_1, 1);
|
||||
addDay(R.id.chb__day_2, 2);
|
||||
addDay(R.id.chb__day_3, 3);
|
||||
addDay(R.id.chb__day_4, 4);
|
||||
addDay(R.id.chb__day_5, 5);
|
||||
addDay(R.id.chb__day_6, 6);
|
||||
addDay(R.id.chb__day_7, 7);
|
||||
fillDaysTexts();
|
||||
final int[] daysIds = new int[]{R.id.day1, R.id.day2, R.id.day3, R.id.day4, R.id.day5, R.id.day6, R.id.day7};
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
final int finalI = i;
|
||||
itemView.findViewById(daysIds[i]).setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
days.get(finalI + 1).toggle();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
allday = itemView.findViewById(R.id.allday);
|
||||
allday.setOnClickListener(this);
|
||||
swAllday = (SwitchCompat) allday.findViewById(R.id.sw__allday);
|
||||
schedule = itemView.findViewById(R.id.schedule);
|
||||
openClose = schedule.findViewById(R.id.time_open_close);
|
||||
open = openClose.findViewById(R.id.time_open);
|
||||
open.setOnClickListener(this);
|
||||
close = openClose.findViewById(R.id.time_close);
|
||||
close.setOnClickListener(this);
|
||||
tvOpen = (TextView) open.findViewById(R.id.tv__time_open);
|
||||
tvClose = (TextView) close.findViewById(R.id.tv__time_close);
|
||||
addClosed = schedule.findViewById(R.id.tv__add_closed);
|
||||
addClosed.setOnClickListener(this);
|
||||
deleteTimetable = itemView.findViewById(R.id.tv__remove_timetable);
|
||||
deleteTimetable.setOnClickListener(this);
|
||||
|
||||
final ViewGroup closedHost = (ViewGroup) itemView.findViewById(R.id.closed_host);
|
||||
for (int i = 0; i < MAX_CLOSED_SPANS; i++)
|
||||
{
|
||||
final View span = LayoutInflater.from(itemView.getContext()).inflate(R.layout.item_timetable_closed_hours, closedHost, false);
|
||||
closedHost.addView(span, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, UiUtils.dimen(R.dimen.editor_height_closed)));
|
||||
closedHours[i] = span;
|
||||
final int finalI = i;
|
||||
span.findViewById(R.id.iv__remove_closed).setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
removeClosedHours(getAdapterPosition(), finalI);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void onBind()
|
||||
{
|
||||
final int position = getAdapterPosition();
|
||||
final Timetable data = mItems.get(position);
|
||||
UiUtils.showIf(position > 0, deleteTimetable);
|
||||
tvOpen.setText(formatHoursMinutes(data.workingTimespan.start));
|
||||
tvClose.setText(formatHoursMinutes(data.workingTimespan.end));
|
||||
showDays(data.weekdays);
|
||||
showSchedule(!data.isFullday);
|
||||
showClosedHours(data.closedTimespans);
|
||||
}
|
||||
|
||||
private String formatHoursMinutes(HoursMinutes hoursMinutes)
|
||||
{
|
||||
// TODO @yunik add proper translated strings
|
||||
return String.format("%02d", Long.valueOf(hoursMinutes.hours))
|
||||
+ ":"
|
||||
+ String.format("%02d", Long.valueOf(hoursMinutes.minutes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.time_open:
|
||||
pickOpeningTime(getAdapterPosition(), HoursMinutesPickerFragment.TAB_FROM);
|
||||
break;
|
||||
case R.id.time_close:
|
||||
pickOpeningTime(getAdapterPosition(), HoursMinutesPickerFragment.TAB_TO);
|
||||
break;
|
||||
case R.id.tv__remove_timetable:
|
||||
removeTimetable(getAdapterPosition());
|
||||
break;
|
||||
case R.id.tv__add_closed:
|
||||
pickClosedHours(getAdapterPosition());
|
||||
break;
|
||||
case R.id.allday:
|
||||
swAllday.toggle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
|
||||
{
|
||||
switch (buttonView.getId())
|
||||
{
|
||||
case R.id.sw__allday:
|
||||
setFullday(getAdapterPosition(), isChecked);
|
||||
break;
|
||||
case R.id.chb__day_1:
|
||||
switchWorkingDay(1);
|
||||
break;
|
||||
case R.id.chb__day_2:
|
||||
switchWorkingDay(2);
|
||||
break;
|
||||
case R.id.chb__day_3:
|
||||
switchWorkingDay(3);
|
||||
break;
|
||||
case R.id.chb__day_4:
|
||||
switchWorkingDay(4);
|
||||
break;
|
||||
case R.id.chb__day_5:
|
||||
switchWorkingDay(5);
|
||||
break;
|
||||
case R.id.chb__day_6:
|
||||
switchWorkingDay(6);
|
||||
break;
|
||||
case R.id.chb__day_7:
|
||||
switchWorkingDay(7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void showDays(int[] weekdays)
|
||||
{
|
||||
for (int i = 1; i <= 7; i++)
|
||||
checkWithoutCallback(days.get(i), false);
|
||||
|
||||
for (int checked : weekdays)
|
||||
checkWithoutCallback(days.get(checked), true);
|
||||
}
|
||||
|
||||
void showSchedule(boolean show)
|
||||
{
|
||||
UiUtils.showIf(show, schedule);
|
||||
checkWithoutCallback(swAllday, !show);
|
||||
}
|
||||
|
||||
private void showClosedHours(Timespan[] closedSpans)
|
||||
{
|
||||
int i = 0;
|
||||
for (Timespan timespan : closedSpans)
|
||||
{
|
||||
if (i == MAX_CLOSED_SPANS)
|
||||
return;
|
||||
|
||||
if (timespan == null)
|
||||
UiUtils.hide(closedHours[i]);
|
||||
else
|
||||
{
|
||||
UiUtils.show(closedHours[i]);
|
||||
// TODO add localization
|
||||
((TextView) closedHours[i].findViewById(R.id.tv__closed)).setText(formatHoursMinutes(timespan.start)
|
||||
+ "-"
|
||||
+ formatHoursMinutes(timespan.end));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
while (i < MAX_CLOSED_SPANS)
|
||||
UiUtils.hide(closedHours[i++]);
|
||||
}
|
||||
|
||||
private void addDay(@IdRes int res, final int dayIndex)
|
||||
{
|
||||
days.put(dayIndex, (CheckBox) itemView.findViewById(res));
|
||||
}
|
||||
|
||||
private void switchWorkingDay(int day)
|
||||
{
|
||||
final CheckBox checkBox = days.get(day);
|
||||
if (checkBox.isChecked())
|
||||
addWorkingDay(day, getAdapterPosition());
|
||||
else
|
||||
removeWorkingDay(day, getAdapterPosition());
|
||||
}
|
||||
|
||||
private void fillDaysTexts()
|
||||
{
|
||||
day1Text = (TextView) itemView.findViewById(R.id.tv__day_1);
|
||||
day2Text = (TextView) itemView.findViewById(R.id.tv__day_2);
|
||||
day3Text = (TextView) itemView.findViewById(R.id.tv__day_3);
|
||||
day4Text = (TextView) itemView.findViewById(R.id.tv__day_4);
|
||||
day5Text = (TextView) itemView.findViewById(R.id.tv__day_5);
|
||||
day6Text = (TextView) itemView.findViewById(R.id.tv__day_6);
|
||||
day7Text = (TextView) itemView.findViewById(R.id.tv__day_7);
|
||||
// FIXME @yunik localize texts
|
||||
day1Text.setText("Su");
|
||||
day2Text.setText("Mo");
|
||||
day3Text.setText("Tu");
|
||||
day4Text.setText("We");
|
||||
day5Text.setText("Th");
|
||||
day6Text.setText("Fr");
|
||||
day7Text.setText("Sa");
|
||||
}
|
||||
|
||||
private void checkWithoutCallback(CompoundButton button, boolean check)
|
||||
{
|
||||
button.setOnCheckedChangeListener(null);
|
||||
button.setChecked(check);
|
||||
button.setOnCheckedChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
private class AddTimetableViewHolder extends BaseTimetableViewHolder
|
||||
{
|
||||
private TextView add;
|
||||
|
||||
public AddTimetableViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
add = (TextView) itemView.findViewById(R.id.btn__add_time);
|
||||
add.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
addTimetable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
void onBind()
|
||||
{
|
||||
// TODO @yunik add text with complement days
|
||||
add.setEnabled(mComplementItem != null && mComplementItem.weekdays.length != 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.mapswithme.maps.widget.placepage;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.base.BaseMwmRecyclerFragment;
|
||||
import com.mapswithme.maps.editor.data.HoursMinutes;
|
||||
import com.mapswithme.maps.editor.data.Timetable;
|
||||
|
||||
public class SimpleTimetableFragment extends BaseMwmRecyclerFragment
|
||||
implements TimetableFragment.TimetableProvider,
|
||||
HoursMinutesPickerFragment.OnPickListener
|
||||
{
|
||||
private SimpleTimetableAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecyclerView.Adapter createAdapter()
|
||||
{
|
||||
mAdapter = new SimpleTimetableAdapter(this);
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
return inflater.inflate(R.layout.fragment_timetable_simple, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timetable[] getTimetables()
|
||||
{
|
||||
return mAdapter.getTimetables();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHoursMinutesPicked(HoursMinutes from, HoursMinutes to, int id)
|
||||
{
|
||||
mAdapter.onHoursMinutesPicked(from, to, id);
|
||||
}
|
||||
|
||||
public void setTimetables(Timetable[] tts)
|
||||
{
|
||||
if (tts == null)
|
||||
return;
|
||||
|
||||
createAdapter();
|
||||
mAdapter.setTimetables(tts);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
package com.mapswithme.maps.widget.placepage;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.base.BaseMwmToolbarFragment;
|
||||
import com.mapswithme.maps.base.OnBackPressListener;
|
||||
import com.mapswithme.maps.editor.OpeningHours;
|
||||
import com.mapswithme.maps.editor.data.Timetable;
|
||||
import com.mapswithme.util.Utils;
|
||||
|
||||
public class TimetableFragment extends BaseMwmToolbarFragment
|
||||
implements View.OnClickListener,
|
||||
OnBackPressListener
|
||||
{
|
||||
interface TimetableProvider
|
||||
{
|
||||
Timetable[] getTimetables();
|
||||
}
|
||||
|
||||
public static final String EXTRA_TIME = "Time";
|
||||
|
||||
private boolean mIsAdvancedMode;
|
||||
|
||||
private TextView mSwitchMode;
|
||||
|
||||
private SimpleTimetableFragment mSimpleModeFragment;
|
||||
private AdvancedTimetableFragment mAdvancedModeFragment;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
return inflater.inflate(R.layout.fragment_timetable, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
initViews(view);
|
||||
simpleMode();
|
||||
|
||||
final Bundle args = getArguments();
|
||||
if (args != null && args.containsKey(EXTRA_TIME))
|
||||
mSimpleModeFragment.setTimetables(OpeningHours.nativeTimetablesFromString(args.getString(EXTRA_TIME)));
|
||||
}
|
||||
|
||||
private void initViews(View root)
|
||||
{
|
||||
mToolbarController.setTitle(R.string.editor_time_title);
|
||||
mToolbarController.findViewById(R.id.iv__submit).setOnClickListener(this);
|
||||
mSwitchMode = (TextView) root.findViewById(R.id.tv__mode_switch);
|
||||
mSwitchMode.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.tv__mode_switch:
|
||||
switchMode();
|
||||
break;
|
||||
case R.id.iv__submit:
|
||||
saveTimetable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private void switchMode()
|
||||
{
|
||||
if (mIsAdvancedMode)
|
||||
simpleMode();
|
||||
else
|
||||
advancedMode();
|
||||
}
|
||||
|
||||
private void simpleMode()
|
||||
{
|
||||
mIsAdvancedMode = false;
|
||||
mSwitchMode.setText(R.string.editor_time_advanced);
|
||||
final Timetable[] filledTimetables = getFilledTimetables(mAdvancedModeFragment, mAdvancedModeFragment);
|
||||
mSimpleModeFragment = (SimpleTimetableFragment) attachFragment(mSimpleModeFragment, SimpleTimetableFragment.class.getName());
|
||||
mSimpleModeFragment.setTimetables(filledTimetables);
|
||||
}
|
||||
|
||||
private void advancedMode()
|
||||
{
|
||||
mIsAdvancedMode = true;
|
||||
mSwitchMode.setText(R.string.editor_time_simple);
|
||||
final Timetable[] filledTimetables = getFilledTimetables(mSimpleModeFragment, mSimpleModeFragment);
|
||||
mAdvancedModeFragment = (AdvancedTimetableFragment) attachFragment(mAdvancedModeFragment, AdvancedTimetableFragment.class.getName());
|
||||
mAdvancedModeFragment.setTimetables(filledTimetables);
|
||||
}
|
||||
|
||||
private boolean hasFilledTimetables(Fragment fragment)
|
||||
{
|
||||
return fragment != null && fragment.isAdded();
|
||||
}
|
||||
|
||||
private Timetable[] getFilledTimetables(Fragment fragment, TimetableProvider provider)
|
||||
{
|
||||
if (!hasFilledTimetables(fragment))
|
||||
return null;
|
||||
|
||||
final Timetable[] timetables = provider.getTimetables();
|
||||
if (timetables == null)
|
||||
{
|
||||
// FIXME @yunikkk add correct text
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setMessage("Invalid formatted timetable!")
|
||||
.create();
|
||||
return null;
|
||||
}
|
||||
|
||||
return timetables;
|
||||
}
|
||||
|
||||
private Fragment attachFragment(Fragment current, String className)
|
||||
{
|
||||
Fragment fragment = current == null ? Fragment.instantiate(getActivity(), className)
|
||||
: current;
|
||||
getChildFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
|
||||
return fragment;
|
||||
}
|
||||
|
||||
private void saveTimetable()
|
||||
{
|
||||
if (mIsAdvancedMode)
|
||||
mAdvancedModeFragment.getTimetables();
|
||||
else
|
||||
mSimpleModeFragment.getTimetables();
|
||||
|
||||
final Timetable[] timetables = mIsAdvancedMode ? mAdvancedModeFragment.getTimetables() : mSimpleModeFragment.getTimetables();
|
||||
// TODO @yunikkk or @deathbaba save timetables to the core
|
||||
|
||||
Utils.navigateToParent(getActivity());
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue