Merge branch 'racecommittee_integrated' of ssh://armin@sapsailing.com/home/trac/git into racecommittee_integrated

This commit is contained in:
Armin Zamani committed 2013-04-11 02:36:02 +02:00
commit 6dfb770ac9
15 files changed
+547 -285

No files matched your search

@@ -102,5 +102,21 @@
android:ems="10"
android:visibility="invisible" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_weight="0.2"
android:orientation="vertical">
<Button
android:id="@+id/buttonPositioning"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Change positioning"
android:textSize="14pt"
android:gravity="center_vertical|center_horizontal"
android:ems="10" />
</LinearLayout>
</LinearLayout>
@@ -40,7 +40,7 @@
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/InnerRelativeLayout"
android:id="@+id/innerFragmentHolder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.618"
@@ -49,6 +49,7 @@
<!-- DISPLAY SECTION -->
<!--
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -108,7 +109,7 @@
android:verticalSpacing="5dp"
android:layout_gravity="left"
/>
</LinearLayout>
</LinearLayout> -->
<!-- END DISPLAY SECTION -->
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dslv="http://schemas.android.com/apk**/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:orientation="horizontal" >
<TextView
android:id="@+id/textPositioningHeaderLeft"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="30dp"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:text="@string/positionings"
android:textSize="12pt"
android:textStyle="bold" />
<TextView
android:id="@+id/textPositioningHeaderRight"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:text="@string/availableFinishingCompetitors"
android:textSize="12pt"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:orientation="horizontal" >
<com.mobeta.android.dslv.DragSortListView
android:id="@+id/dragSortListPositioning"
android:layout_width="350dp"
android:layout_height="fill_parent"
android:layout_gravity="left"
android:layout_marginLeft="10dp"
android:layout_marginRight="30dp"
android:verticalSpacing="5dp"
dslv:collapsed_height="2dp"
dslv:drag_enabled="true"
dslv:drag_scroll_start="0.33"
dslv:float_alpha="0.6"
dslv:max_drag_scroll_speed="0.5"
dslv:slide_shuffle_speed="0.3"
dslv:track_drag_sort="false"
dslv:use_default_controller="false" />
<ListView
android:id="@+id/gridViewPositioning"
android:layout_width="250dp"
android:layout_height="fill_parent"
android:layout_gravity="left"
android:verticalSpacing="5dp" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:orientation="horizontal" >
<Button
android:id="@+id/buttonPositionOk"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:text="Confirm positioning"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>
@@ -40,8 +40,8 @@ public class RaceListAdapter extends ArrayAdapter<RaceListDataType> {
private List<RaceListDataType> items;
private List<RaceListDataType> originalItems;
public RaceListAdapter(Context context, int textViewResourceId,
List<RaceListDataType> objects, JuryFlagClickedListener juryListener) {
public RaceListAdapter(Context context, int textViewResourceId, List<RaceListDataType> objects,
JuryFlagClickedListener juryListener) {
super(context, textViewResourceId, objects);
this.items = objects;
this.originalItems = new ArrayList<RaceListDataType>();
@@ -52,24 +52,23 @@ public class RaceListAdapter extends ArrayAdapter<RaceListDataType> {
@Override
public int getCount() {
synchronized(mLock) {
return items!=null ? items.size() : 0;
synchronized (mLock) {
return items != null ? items.size() : 0;
}
}
@Override
public RaceListDataType getItem(int position) {
RaceListDataType element = null;
synchronized(mLock) {
element = items!=null ? items.get(position) : null;
synchronized (mLock) {
element = items != null ? items.get(position) : null;
}
return element;
}
@Override
public int getItemViewType(int position) {
return (getItem(position) instanceof RaceListDataTypeTitle ? VIEW_BOAT_GROUP
: VIEW_RACE);
return (getItem(position) instanceof RaceListDataTypeTitle ? VIEW_BOAT_GROUP : VIEW_RACE);
}
@Override
@@ -82,7 +81,6 @@ public class RaceListAdapter extends ArrayAdapter<RaceListDataType> {
return (getItem(position) instanceof RaceListDataTypeElement);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
RaceListDataType raceListElement = null;
@@ -154,8 +152,15 @@ public class RaceListAdapter extends ArrayAdapter<RaceListDataType> {
protected FilterResults performFiltering(CharSequence constraint) {
// Initiate our results object
FilterResults results = new FilterResults();
List<RaceListDataType> dataTypeList = new ArrayList<RaceListDataType>();
results.values = originalItems;
results.count = originalItems.size();
if (constraint.length() > 0) {
return results;
}
List<RaceListDataType> dataTypeList = new ArrayList<RaceListDataType>();
if (originalItems.isEmpty()) {
originalItems = new ArrayList<RaceListDataType>(items.size());
for (RaceListDataType type : items) {
@@ -164,63 +169,62 @@ public class RaceListAdapter extends ArrayAdapter<RaceListDataType> {
}
if (originalItems.isEmpty()) {
results.values = items;
results.count = items.size();
} else {
Map<RaceListDataTypeTitle, List<RaceListDataTypeElement>> elementMap
= new TreeMap<RaceListDataTypeTitle, List<RaceListDataTypeElement>>(new RaceListDataTypeTitleComparator());
RaceListDataTypeTitle currentTitle = null;
for (RaceListDataType element : originalItems) {
if (element instanceof RaceListDataTypeTitle) {
currentTitle = (RaceListDataTypeTitle) element;
elementMap.put(currentTitle, new ArrayList<RaceListDataTypeElement>());
} else if (element instanceof RaceListDataTypeElement) {
RaceListDataTypeElement listElement = (RaceListDataTypeElement) element;
if (elementMap.containsKey(currentTitle)) {
elementMap.get(currentTitle).add(listElement);
}
}
}
for (RaceListDataTypeTitle title : elementMap.keySet()) {
dataTypeList.add(title);
List<RaceListDataTypeElement> elementList = elementMap.get(title);
Collections.sort(elementList, new RaceListDataTypeElementComparator());
RaceListDataTypeElement lastFinishedRace = null;
int numberOfUnscheduledRaces = 0;
for (RaceListDataTypeElement dataElement : elementList) {
if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.FINISHED)) {
lastFinishedRace = dataElement;
}
}
for (RaceListDataTypeElement dataElement : elementList) {
if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.UNSCHEDULED)) {
numberOfUnscheduledRaces++;
if (numberOfUnscheduledRaces > 1)
continue;
} else if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.FINISHED)) {
if (!dataElement.equals(lastFinishedRace)) {
continue;
}
}
dataTypeList.add(dataElement);
}
}
results.values = dataTypeList;
results.count = dataTypeList.size();
return results;
}
return results;
Map<RaceListDataTypeTitle, List<RaceListDataTypeElement>> elementMap = new TreeMap<RaceListDataTypeTitle, List<RaceListDataTypeElement>>(
new RaceListDataTypeTitleComparator());
RaceListDataTypeTitle currentTitle = null;
for (RaceListDataType element : originalItems) {
if (element instanceof RaceListDataTypeTitle) {
currentTitle = (RaceListDataTypeTitle) element;
elementMap.put(currentTitle, new ArrayList<RaceListDataTypeElement>());
} else if (element instanceof RaceListDataTypeElement) {
RaceListDataTypeElement listElement = (RaceListDataTypeElement) element;
if (elementMap.containsKey(currentTitle)) {
elementMap.get(currentTitle).add(listElement);
}
}
}
for (RaceListDataTypeTitle title : elementMap.keySet()) {
dataTypeList.add(title);
List<RaceListDataTypeElement> elementList = elementMap.get(title);
Collections.sort(elementList, new RaceListDataTypeElementComparator());
RaceListDataTypeElement lastFinishedRace = null;
int numberOfUnscheduledRaces = 0;
for (RaceListDataTypeElement dataElement : elementList) {
if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.FINISHED)) {
lastFinishedRace = dataElement;
}
}
for (RaceListDataTypeElement dataElement : elementList) {
if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.UNSCHEDULED)) {
numberOfUnscheduledRaces++;
if (numberOfUnscheduledRaces > 1)
continue;
} else if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.FINISHED)) {
if (!dataElement.equals(lastFinishedRace)) {
continue;
}
}
dataTypeList.add(dataElement);
}
}
results.values = dataTypeList;
results.count = dataTypeList.size();
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
synchronized(mLock) {
synchronized (mLock) {
items = (List<RaceListDataType>) results.values;
notifyDataSetChanged();
}
@@ -61,6 +61,4 @@ public abstract class RaceFragment extends Fragment implements TickListener {
return args;
}
public abstract void notifyTick();
}
@@ -105,7 +105,10 @@ public class RaceInfoFragment extends RaceFragment implements RaceStateChangedLi
}
protected void switchToInfoFragment() {
switchToInfoFragment(infoFragmentChooser.choose(getRace()));
RaceFragment newInfoFragment = infoFragmentChooser.choose(getRace());
if (infoFragment == null || !newInfoFragment.getClass().equals(infoFragment.getClass())) {
switchToInfoFragment(newInfoFragment);
}
}
protected void switchToInfoFragment(RaceFragment choosenFragment) {
@@ -99,4 +99,9 @@ public class AbortModeSelectionDialog extends RaceDialogFragment {
}
this.dismiss();
}
@Override
public void notifyTick() {
}
}
@@ -63,4 +63,9 @@ public class AbortTypeSelectionDialog extends RaceDialogFragment {
fragment.show(fragmentManager, dialogName);
this.dismiss();
}
@Override
public void notifyTick() {
}
}
@@ -442,4 +442,9 @@ public class CourseDesignDialogFragment extends RaceDialogFragment {
}
}
@Override
public void notifyTick() {
}
}
@@ -5,11 +5,13 @@ import java.io.Serializable;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.data.OnlineDataManager;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.utils.TickListener;
import com.sap.sailing.racecommittee.app.utils.TickSingleton;
import android.app.DialogFragment;
import android.os.Bundle;
public class RaceDialogFragment extends DialogFragment {
public abstract class RaceDialogFragment extends DialogFragment implements TickListener {
public static Bundle createArguments(ManagedRace race) {
Bundle arguments = new Bundle();
@@ -30,6 +32,19 @@ public class RaceDialogFragment extends DialogFragment {
String.format("Unable to obtain ManagedRace from datastore on start of race fragment."));
}
}
@Override
public void onStart() {
super.onStart();
TickSingleton.INSTANCE.registerListener(this);
notifyTick();
}
@Override
public void onStop() {
super.onStop();
TickSingleton.INSTANCE.unregisterListener(this);
}
public ManagedRace getRace() {
return managedRace;
@@ -40,6 +40,8 @@ public class ManagedRaceListFragment extends ListFragment implements JuryFlagCli
private HashMap<Serializable, ManagedRace> managedRacesById;
private RaceListAdapter adapter;
private ArrayList<RaceListDataType> raceDataTypeList;
private String magicFilterString = "";
public ManagedRaceListFragment() {
this.selectedRaceId = null;
@@ -56,7 +58,6 @@ public class ManagedRaceListFragment extends ListFragment implements JuryFlagCli
adapter = new RaceListAdapter(getActivity(), R.layout.welter_two_row_no_image, raceDataTypeList, this);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
setListAdapter(adapter);
adapter.getFilter().filter("");
}
@Override
@@ -95,10 +96,8 @@ public class ManagedRaceListFragment extends ListFragment implements JuryFlagCli
// initialize view
initListElements(false);
if (adapter != null) {
adapter.getFilter().filter("");
adapter.notifyDataSetChanged();
}
adapter.getFilter().filter("");
notifyDataChanged();
}
@Override
@@ -205,14 +204,19 @@ public class ManagedRaceListFragment extends ListFragment implements JuryFlagCli
}
}
}
if (adapter != null) {
adapter.getFilter().filter("");
adapter.notifyDataSetChanged();
}
refilterList();
}
public void onJuryFlagClicked(BoatClassSeriesDataFleet clicked) {
// / TODO: implement.
magicFilterString = magicFilterString.equals("") ? "nofilter" : "";
refilterList();
}
private void refilterList() {
if (adapter != null) {
adapter.getFilter().filter(magicFilterString);
adapter.notifyDataSetChanged();
}
}
@Override
@@ -8,7 +8,9 @@ import java.util.Date;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.sap.sailing.domain.common.TimePoint;
@@ -48,6 +50,17 @@ public class FinishedRaceFragment extends RaceFragment {
finishTimeView.setText(getFinishTimeText());
timeLimitView.setText(getTimeLimitText());
protestStartTimeView.setText(getProtestStartTimeText());
Button positioningButton = (Button) getView().findViewById(R.id.buttonPositioning);
positioningButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
PositioningFragment fragment = new PositioningFragment();
fragment.setArguments(PositioningFragment.createArguments(getRace()));
fragment.show(getFragmentManager(), null);
}
});
}
private CharSequence getProtestStartTimeText() {
@@ -55,8 +68,17 @@ public class FinishedRaceFragment extends RaceFragment {
return getString(R.string.empty);
}
private TimePoint getTimeLimit() {
TimePoint startTime = getRace().getState().getStartTime();
TimePoint firstBoatTime = getRace().getState().getFinishingStartTime();
if (startTime == null || firstBoatTime == null) {
return null;
}
return firstBoatTime.plus((long)((firstBoatTime.asMillis() - startTime.asMillis()) * 0.75));
}
private CharSequence getTimeLimitText() {
TimePoint timeLimit = null;
TimePoint timeLimit = getTimeLimit();
if (timeLimit != null) {
return String.format("%s %s", getString(R.string.race_time_limit),
getFormattedTime(timeLimit.asDate()));
@@ -1,9 +1,6 @@
package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.app.AlertDialog;
import android.app.FragmentManager;
import android.content.DialogInterface;
@@ -12,26 +9,15 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import com.mobeta.android.dslv.DragSortController;
import com.mobeta.android.dslv.DragSortListView;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.logging.ExLog;
import com.sap.sailing.racecommittee.app.ui.adapters.finishing.CompetitorPositioningListAdapter;
import com.sap.sailing.racecommittee.app.ui.adapters.finishing.CompetitorsAdapter;
import com.sap.sailing.racecommittee.app.ui.fragments.RaceFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.AbortModeSelectionDialog;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.RaceDialogFragment;
@@ -43,22 +29,6 @@ public class FinishingRaceFragment extends RaceFragment {
private ImageButton abortingFlagButton;
private ImageButton blueFlagButton;
private DragSortListView positioningListView;
private ListView competitorListView;
private DragSortController dragSortController;
private CompetitorsAdapter competitorsAdapter;
private CompetitorPositioningListAdapter positioningAdapter;
protected List<Competitor> competitors;
protected List<Pair<Competitor, MaxPointsReason>> positionedCompetitors;
private int dragStartMode = DragSortController.ON_DRAG;
private boolean removeEnabled = true;
private int removeMode = DragSortController.FLING_REMOVE;
private boolean sortEnabled = true;
private boolean dragEnabled = true;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.race_finishing_view, container, false);
@@ -70,58 +40,15 @@ public class FinishingRaceFragment extends RaceFragment {
countUpTextView = (TextView) getView().findViewById(R.id.raceCountUp);
nextFlagCountdown = (TextView) getView().findViewById(R.id.nextFlagCountdown);
nextFlagCountdown.setText(getTimeLimitText());
blueFlagButton = (ImageButton) getView().findViewById(R.id.blueFlagButton);
abortingFlagButton = (ImageButton) getView().findViewById(R.id.abortingFlagButton);
competitors = new ArrayList<Competitor>();
Util.addAll(getRace().getCompetitors(), competitors);
competitorsAdapter = new CompetitorsAdapter(getActivity(), R.layout.welter_grid_competitor_cell, competitors);
PositioningFragment positioningFragment = new PositioningFragment();
positioningFragment.setArguments(PositioningFragment.createArguments(getRace()));
getFragmentManager().beginTransaction().add(R.id.innerFragmentHolder, positioningFragment, null).commit();
positionedCompetitors = initializeFinishPositioningList();
deletePositionedCompetitorsFromUnpositionedList();
positioningAdapter = new CompetitorPositioningListAdapter(getActivity(), R.layout.welter_positioning_item, positionedCompetitors);
positioningListView = (DragSortListView) getView().findViewById(R.id.listViewPositioningList);
positioningListView.setAdapter(positioningAdapter);
positioningListView.setDropListener(new DragSortListView.DropListener() {
@Override
public void drop(int from, int to) {
if (from != to) {
Pair<Competitor, MaxPointsReason> item = positioningAdapter.getItem(from);
setItemToNewPositioning(from, to, item);
getRace().getState().setFinishPositioningListChanged(positionedCompetitors);
}
}
});
positioningListView.setRemoveListener(new DragSortListView.RemoveListener() {
@Override
public void remove(int toBeRemoved) {
Pair<Competitor, MaxPointsReason> item = positioningAdapter.getItem(toBeRemoved);
onCompetitorRemovedFromPositioningList(item);
}
});
positioningListView.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
createMaxPointsReasonSelectionDialog(positionedCompetitors.get(position));
return true;
}
});
dragSortController = buildDragSortController(positioningListView);
positioningListView.setFloatViewManager(dragSortController);
positioningListView.setOnTouchListener(dragSortController);
positioningListView.setDragEnabled(dragEnabled);
competitorListView = (ListView) getView().findViewById(R.id.gridViewCompetitors);
competitorListView.setAdapter(competitorsAdapter);
blueFlagButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
showRemoveBlueFlagDialog();
@@ -135,131 +62,9 @@ public class FinishingRaceFragment extends RaceFragment {
ExLog.i(ExLog.FLAG_NOVEMBER, getRace().getId().toString(), getActivity());
}
});
competitorListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {
Competitor competitor = (Competitor) competitorsAdapter.getItem(position);
ExLog.i("RaceFinishingFragment", "Grid is clicked at position " + position + " for competitor " + competitor.getName());
onCompetitorClickedOnGrid(competitor);
}
});
}
/**
* Creates a DragSortController and thereby defines the behaviour of the drag sort list
*/
public DragSortController buildDragSortController(DragSortListView dragSortListView) {
DragSortController controller = new DragSortController(dragSortListView);
controller.setDragHandleId(R.id.drag_handle);
controller.setFlingHandleId(R.id.drag_handle);
controller.setRemoveEnabled(removeEnabled);
controller.setSortEnabled(sortEnabled);
controller.setDragInitMode(dragStartMode);
controller.setRemoveMode(removeMode);
controller.setBackgroundColor(getActivity().getResources().getColor(R.color.welter_medium_blue));
return controller;
}
private void deletePositionedCompetitorsFromUnpositionedList() {
for (Pair<Competitor, MaxPointsReason> positionedItem : positionedCompetitors) {
competitors.remove(positionedItem.getA());
}
}
private List<Pair<Competitor, MaxPointsReason>> initializeFinishPositioningList() {
List<Pair<Competitor, MaxPointsReason>> positionings;
if (getRace().getState().getFinishPositioningList() != null) {
positionings = getRace().getState().getFinishPositioningList();
} else {
positionings = new ArrayList<Util.Pair<Competitor,MaxPointsReason>>();
}
return positionings;
}
private void setItemToNewPositioning(int from, int to, Pair<Competitor, MaxPointsReason> item) {
positioningAdapter.remove(item);
positioningAdapter.insert(item, to);
}
private void createMaxPointsReasonSelectionDialog(final Pair<Competitor, MaxPointsReason> item) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final CharSequence[] maxPointsReasons = getAllMaxPointsReasons();
builder.setTitle(R.string.change_course_element)
.setItems(maxPointsReasons, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int position) {
setMaxPointsReasonForItem(item, maxPointsReasons[position]);
}
});
builder.create();
builder.show();
}
private CharSequence[] getAllMaxPointsReasons() {
List<CharSequence> result = new ArrayList<CharSequence>();
for (MaxPointsReason reason : MaxPointsReason.values()) {
result.add(reason.name());
}
return result.toArray(new CharSequence[result.size()]);
}
protected void setMaxPointsReasonForItem(Pair<Competitor, MaxPointsReason> item, CharSequence maxPointsReasonName) {
MaxPointsReason maxPointsReason = MaxPointsReason.valueOf(maxPointsReasonName.toString());
Pair<Competitor, MaxPointsReason> newItem = new Pair<Competitor, MaxPointsReason>(item.getA(), maxPointsReason);
int currentIndexOfItem = positionedCompetitors.indexOf(item);
replaceItemInPositioningList(currentIndexOfItem, item, newItem);
if (!maxPointsReason.equals(MaxPointsReason.NONE)) {
setCompetitorToBottomOfPositioningList(newItem);
}
getRace().getState().setFinishPositioningListChanged(positionedCompetitors);
}
private void replaceItemInPositioningList(int currentIndexOfItem, Pair<Competitor, MaxPointsReason> item, Pair<Competitor, MaxPointsReason> newItem) {
positioningAdapter.remove(item);
positioningAdapter.insert(newItem, currentIndexOfItem);
}
private void setCompetitorToBottomOfPositioningList(Pair<Competitor, MaxPointsReason> item) {
int currentIndex = positionedCompetitors.indexOf(item);
int lastIndex = positionedCompetitors.size() - 1;
setItemToNewPositioning(currentIndex, lastIndex, item);
}
protected void onCompetitorClickedOnGrid(Competitor competitor) {
addNewCompetitorToPositioningList(competitor);
removeCompetitorFromGrid(competitor);
getRace().getState().setFinishPositioningListChanged(positionedCompetitors);
}
protected void removeCompetitorFromGrid(Competitor competitor) {
competitors.remove(competitor);
competitorsAdapter.notifyDataSetChanged();
}
private void addNewCompetitorToPositioningList(Competitor competitor) {
positionedCompetitors.add(new Pair<Competitor, MaxPointsReason>(competitor, MaxPointsReason.NONE));
positioningAdapter.notifyDataSetChanged();
}
protected void onCompetitorRemovedFromPositioningList(Pair<Competitor, MaxPointsReason> item) {
addNewCompetitorToCompetitorList(item.getA());
removeCompetitorFromPositionings(item);
getRace().getState().setFinishPositioningListChanged(positionedCompetitors);
}
private void addNewCompetitorToCompetitorList(Competitor competitor) {
competitors.add(competitor);
competitorsAdapter.notifyDataSetChanged();
}
protected void removeCompetitorFromPositionings(Pair<Competitor, MaxPointsReason> item) {
positionedCompetitors.remove(item);
positioningAdapter.notifyDataSetChanged();
}
protected void setCountdownLabels(long millisecondsSinceStart) {
setStarttimeCountupLabel(millisecondsSinceStart);
}
@@ -281,12 +86,23 @@ public class FinishingRaceFragment extends RaceFragment {
return String.format(timePattern, hoursString, minutesString,
secondsString);
}
protected void setRaceFinishCountDownLabel() {
Date raceFinishingTimeDate = getRace().getState().getFinishingStartTime().asDate();
nextFlagCountdown.setText(String.format(getActivity().getResources().getString(R.string.finishing_limit_template),
getFormattedTime(raceFinishingTimeDate)));
private TimePoint getTimeLimit() {
TimePoint startTime = getRace().getState().getStartTime();
TimePoint firstBoatTime = getRace().getState().getFinishingStartTime();
if (startTime == null || firstBoatTime == null) {
return null;
}
return firstBoatTime.plus((long)((firstBoatTime.asMillis() - startTime.asMillis()) * 0.75));
}
private CharSequence getTimeLimitText() {
TimePoint timeLimit = getTimeLimit();
if (timeLimit != null) {
return String.format("%s %s", getString(R.string.race_time_limit),
getFormattedTime(timeLimit.asDate()));
}
return getString(R.string.empty);
}
private String getFormattedTime(Date time) {
@@ -336,7 +152,5 @@ public class FinishingRaceFragment extends RaceFragment {
long millisSinceStart = System.currentTimeMillis() - getRace().getState().getStartTime().asMillis();
setCountdownLabels(millisSinceStart);
setRaceFinishCountDownLabel();
}
}
@@ -0,0 +1,256 @@
package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
import java.util.ArrayList;
import java.util.List;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import com.mobeta.android.dslv.DragSortController;
import com.mobeta.android.dslv.DragSortListView;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.logging.ExLog;
import com.sap.sailing.racecommittee.app.ui.adapters.finishing.CompetitorPositioningListAdapter;
import com.sap.sailing.racecommittee.app.ui.adapters.finishing.CompetitorsAdapter;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.RaceDialogFragment;
public class PositioningFragment extends RaceDialogFragment {
private DragSortListView positioningListView;
private ListView competitorListView;
private DragSortController dragSortController;
private CompetitorsAdapter competitorsAdapter;
private CompetitorPositioningListAdapter positioningAdapter;
protected List<Competitor> competitors;
protected List<Pair<Competitor, MaxPointsReason>> positionedCompetitors;
private int dragStartMode = DragSortController.ON_DRAG;
private boolean removeEnabled = true;
private int removeMode = DragSortController.FLING_REMOVE;
private boolean sortEnabled = true;
private boolean dragEnabled = true;
private boolean isDialog() {
return getDialog() != null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (isDialog()) {
getDialog().setTitle("Change positioning");
}
return inflater.inflate(R.layout.race_positioning_view, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (isDialog()) {
Button okButton = (Button) getView().findViewById(R.id.buttonPositionOk);
okButton.setVisibility(Button.VISIBLE);
okButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getRace().getState().setFinishPositioningConfirmed();
dismiss();
}
});
}
competitors = new ArrayList<Competitor>();
Util.addAll(getRace().getCompetitors(), competitors);
competitorsAdapter = new CompetitorsAdapter(getActivity(), R.layout.welter_grid_competitor_cell, competitors);
positionedCompetitors = initializeFinishPositioningList();
for (Pair<Competitor, MaxPointsReason> positionedCompetitor : positionedCompetitors) {
competitors.remove(positionedCompetitor.getA());
}
deletePositionedCompetitorsFromUnpositionedList();
positioningAdapter = new CompetitorPositioningListAdapter(getActivity(), R.layout.welter_positioning_item, positionedCompetitors);
positioningListView = (DragSortListView) getView().findViewById(R.id.dragSortListPositioning);
positioningListView.setAdapter(positioningAdapter);
positioningListView.setDropListener(new DragSortListView.DropListener() {
@Override
public void drop(int from, int to) {
if (from != to) {
Pair<Competitor, MaxPointsReason> item = positioningAdapter.getItem(from);
setItemToNewPositioning(from, to, item);
getRace().getState().setFinishPositioningListChanged(positionedCompetitors);
}
}
});
positioningListView.setRemoveListener(new DragSortListView.RemoveListener() {
@Override
public void remove(int toBeRemoved) {
Pair<Competitor, MaxPointsReason> item = positioningAdapter.getItem(toBeRemoved);
onCompetitorRemovedFromPositioningList(item);
}
});
positioningListView.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
createMaxPointsReasonSelectionDialog(positionedCompetitors.get(position));
return true;
}
});
dragSortController = buildDragSortController(positioningListView);
positioningListView.setFloatViewManager(dragSortController);
positioningListView.setOnTouchListener(dragSortController);
positioningListView.setDragEnabled(dragEnabled);
competitorListView = (ListView) getView().findViewById(R.id.gridViewPositioning);
competitorListView.setAdapter(competitorsAdapter);
competitorListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {
Competitor competitor = (Competitor) competitorsAdapter.getItem(position);
ExLog.i("RaceFinishingFragment", "Grid is clicked at position " + position + " for competitor " + competitor.getName());
onCompetitorClickedOnGrid(competitor);
}
});
}
/**
* Creates a DragSortController and thereby defines the behaviour of the drag sort list
*/
public DragSortController buildDragSortController(DragSortListView dragSortListView) {
DragSortController controller = new DragSortController(dragSortListView);
controller.setDragHandleId(R.id.drag_handle);
controller.setFlingHandleId(R.id.drag_handle);
controller.setRemoveEnabled(removeEnabled);
controller.setSortEnabled(sortEnabled);
controller.setDragInitMode(dragStartMode);
controller.setRemoveMode(removeMode);
controller.setBackgroundColor(getActivity().getResources().getColor(R.color.welter_medium_blue));
return controller;
}
private void deletePositionedCompetitorsFromUnpositionedList() {
for (Pair<Competitor, MaxPointsReason> positionedItem : positionedCompetitors) {
competitors.remove(positionedItem.getA());
}
}
private List<Pair<Competitor, MaxPointsReason>> initializeFinishPositioningList() {
List<Pair<Competitor, MaxPointsReason>> positionings;
if (getRace().getState().getFinishPositioningList() != null) {
positionings = getRace().getState().getFinishPositioningList();
} else {
positionings = new ArrayList<Util.Pair<Competitor,MaxPointsReason>>();
}
return positionings;
}
private void setItemToNewPositioning(int from, int to, Pair<Competitor, MaxPointsReason> item) {
positioningAdapter.remove(item);
positioningAdapter.insert(item, to);
}
private void createMaxPointsReasonSelectionDialog(final Pair<Competitor, MaxPointsReason> item) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final CharSequence[] maxPointsReasons = getAllMaxPointsReasons();
builder.setTitle(R.string.change_course_element)
.setItems(maxPointsReasons, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int position) {
setMaxPointsReasonForItem(item, maxPointsReasons[position]);
}
});
builder.create();
builder.show();
}
private CharSequence[] getAllMaxPointsReasons() {
List<CharSequence> result = new ArrayList<CharSequence>();
for (MaxPointsReason reason : MaxPointsReason.values()) {
result.add(reason.name());
}
return result.toArray(new CharSequence[result.size()]);
}
protected void setMaxPointsReasonForItem(Pair<Competitor, MaxPointsReason> item, CharSequence maxPointsReasonName) {
MaxPointsReason maxPointsReason = MaxPointsReason.valueOf(maxPointsReasonName.toString());
Pair<Competitor, MaxPointsReason> newItem = new Pair<Competitor, MaxPointsReason>(item.getA(), maxPointsReason);
int currentIndexOfItem = positionedCompetitors.indexOf(item);
replaceItemInPositioningList(currentIndexOfItem, item, newItem);
if (!maxPointsReason.equals(MaxPointsReason.NONE)) {
setCompetitorToBottomOfPositioningList(newItem);
}
getRace().getState().setFinishPositioningListChanged(positionedCompetitors);
}
private void replaceItemInPositioningList(int currentIndexOfItem, Pair<Competitor, MaxPointsReason> item, Pair<Competitor, MaxPointsReason> newItem) {
positioningAdapter.remove(item);
positioningAdapter.insert(newItem, currentIndexOfItem);
}
private void setCompetitorToBottomOfPositioningList(Pair<Competitor, MaxPointsReason> item) {
int currentIndex = positionedCompetitors.indexOf(item);
int lastIndex = positionedCompetitors.size() - 1;
setItemToNewPositioning(currentIndex, lastIndex, item);
}
protected void onCompetitorClickedOnGrid(Competitor competitor) {
addNewCompetitorToPositioningList(competitor);
removeCompetitorFromGrid(competitor);
getRace().getState().setFinishPositioningListChanged(positionedCompetitors);
}
protected void removeCompetitorFromGrid(Competitor competitor) {
competitors.remove(competitor);
competitorsAdapter.notifyDataSetChanged();
}
private void addNewCompetitorToPositioningList(Competitor competitor) {
positionedCompetitors.add(new Pair<Competitor, MaxPointsReason>(competitor, MaxPointsReason.NONE));
positioningAdapter.notifyDataSetChanged();
}
protected void onCompetitorRemovedFromPositioningList(Pair<Competitor, MaxPointsReason> item) {
addNewCompetitorToCompetitorList(item.getA());
removeCompetitorFromPositionings(item);
getRace().getState().setFinishPositioningListChanged(positionedCompetitors);
}
private void addNewCompetitorToCompetitorList(Competitor competitor) {
competitors.add(competitor);
competitorsAdapter.notifyDataSetChanged();
}
protected void removeCompetitorFromPositionings(Pair<Competitor, MaxPointsReason> item) {
positionedCompetitors.remove(item);
positioningAdapter.notifyDataSetChanged();
}
@Override
public void notifyTick() {
}
}
@@ -12,9 +12,13 @@ import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.domain.startprocedure.impl.EssStartPhaseEventListener;
@@ -81,6 +85,32 @@ public class EssStartPhaseFragment extends RaceFragment implements EssStartPhase
infoListener.onResetTime();
}
});
setupUi();
}
private void setupUi() {
RaceLog log = getRace().getState().getRaceLog();
log.lockForRead();
try {
RaceLogEvent lastEvent = log.getLastFixAtOrBefore(MillisecondsTimePoint.now());
if (lastEvent instanceof RaceLogFlagEvent) {
RaceLogFlagEvent flagEvent = (RaceLogFlagEvent) lastEvent;
Flags flag = flagEvent.getUpperFlag();
if (!flagEvent.isDisplayed() && flag.equals(Flags.AP)) {
onAPDown();
} else if (flagEvent.isDisplayed() && flag.equals(Flags.ESSTHREE)) {
onEssThreeUp();
} else if (flagEvent.isDisplayed() && flag.equals(Flags.ESSTWO)) {
onEssTwoUp();
} else if (flagEvent.isDisplayed() && flag.equals(Flags.ESSONE)) {
onEssOneUp();
}
}
} finally {
log.unlockAfterRead();
}
}
@Override