RCApp: ESS Course Designer is now build with RecyclerView instead of ListView

This commit is contained in:
Peter Siegmund
2015-04-14 15:17:48 +02:00
parent 0445b9ffd0
commit 2d44750ae6
51 changed files with 2102 additions and 210 deletions
@@ -68,6 +68,8 @@ android {
}
dependencies {
compile "com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.6.2"
/* support libraries */
compile "com.android.support:appcompat-v7:22.0.0"
compile "com.android.support:recyclerview-v7:22.0.0"
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z1_mdpi"
tools:ignore="unused" />
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z3_mdpi"
tools:ignore="unused" />
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z1_mdpi"
tools:ignore="unused" />
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z3_mdpi"
tools:ignore="unused" />
Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z1_xhdpi"
tools:ignore="unused" />
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z3_xhdpi"
tools:ignore="unused" />
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z1_xxhdpi"
tools:ignore="unused" />
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z3_xxhdpi"
tools:ignore="unused" />
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z1_xxxhdpi"
tools:ignore="unused" />
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:src="@drawable/material_shadow_z3_xxxhdpi"
tools:ignore="unused" />
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:padding="@dimen/default_padding_half"
android:orientation="vertical">
<ImageView
android:id="@+id/cell_image"
android:layout_width="32dp"
android:layout_height="32dp"
android:contentDescription="@string/markImage"
android:scaleType="fitCenter"
tools:src="@drawable/buoy_black_cyl"/>
<TextView
android:id="@+id/cell_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="?white"
android:textIsSelectable="false"
android:textAppearance="?textXXSmall"
tools:text="Black Cylinder"
android:singleLine="true"/>
</LinearLayout>
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight">
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@id/drag_handle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/drag_symbol"
android:contentDescription="@string/drag_handle_description"/>
<LinearLayout
android:id="@+id/column_left"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/column_left_image"
android:layout_width="32dp"
android:layout_height="32dp"
android:contentDescription="@string/markImage"
android:gravity="center"
tools:src="@drawable/buoy_dark_orange"/>
<TextView
android:id="@+id/column_left_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:padding="5dp"
android:singleLine="true"
android:textAppearance="?textXXSmall"
android:textColor="?white"
android:textIsSelectable="false"
tools:text="Pin End"/>
</LinearLayout>
<TextView
android:id="@+id/rounding_direction"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:singleLine="true"
android:textAppearance="?textSmall"
android:textColor="?white"
android:textIsSelectable="false"
tools:text="Line"/>
<LinearLayout
android:id="@+id/column_right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical">
<ImageView
android:id="@+id/column_right_image"
android:layout_width="32dp"
android:layout_height="32dp"
android:contentDescription="@string/markImage"
android:gravity="center"
tools:src="@drawable/buoy_dark_orange"/>
<TextView
android:id="@+id/column_right_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:padding="5dp"
android:singleLine="true"
android:textAppearance="?textXXSmall"
android:textColor="?white"
android:textIsSelectable="false"
tools:text="Startboat"/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
@@ -98,7 +98,7 @@
android:layout_marginRight="5dp"
android:src="@drawable/lock_outline"
android:tint="?sap_light_gray"
android:visibility="visible" />
android:visibility="gone" />
</LinearLayout>
<RelativeLayout
@@ -1,5 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
android:baselineAligned="false"
android:orientation="vertical"
tools:ignore="ResAuto">
<include
android:id="@+id/header"
layout="@layout/race_schedule_course_header"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/header_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:orientation="horizontal"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:text="@string/previous_course"
android:textAppearance="?textNormal"
android:textStyle="bold"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:text="@string/make_new_course"
android:textAppearance="?textNormal"
android:textStyle="bold"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:text="@string/course_design_assets"
android:textAppearance="?textNormal"
android:textStyle="bold"/>
</LinearLayout>
<LinearLayout
android:id="@+id/bottom_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="20dp">
<Button
android:id="@+id/publishCourse"
style="?buttonSolidNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:text="@string/publish"/>
<Button
android:id="@+id/unpublishCourse"
style="?buttonSolidNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:text="@string/unpublish"/>
<Button
android:id="@+id/takeHistoryCourse"
style="?buttonSolidNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/take_previous"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottom_bar"
android:layout_below="@id/header_bar"
android:gravity="center"
android:orientation="horizontal"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin">
<android.support.v7.widget.RecyclerView
android:id="@+id/previous_course"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center"
android:layout_weight="1"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/new_course"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_gravity="left"
android:gravity="center_horizontal|center_vertical"
android:verticalSpacing="5dp"
android:layout_weight="1"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/assets"
android:layout_width="0dp"
android:layout_height="match_parent"
android:columnWidth="100dp"
android:gravity="center"
android:horizontalSpacing="10dp"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp"
android:layout_weight="1"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
@@ -1,44 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
<include
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="@dimen/selector_header_height"
android:background="?sap_gray">
<LinearLayout
android:id="@+id/header_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginStart="@dimen/default_margin"
android:orientation="horizontal">
<ImageView
android:id="@+id/header_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_chevron_left_white_24dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/course"
android:textAppearance="?textNormal" />
</LinearLayout>
<View
android:id="@+id/line_top"
android:layout_width="match_parent"
android:layout_height="@dimen/thick_line"
android:layout_alignParentBottom="true"
android:background="?black" />
</RelativeLayout>
layout="@layout/race_schedule_course_header"/>
<ListView
android:id="@+id/listView"
@@ -47,5 +15,5 @@
android:layout_below="@id/header"
android:background="?sap_gray_black_30"
android:divider="@null"
android:dividerHeight="0dp" />
android:dividerHeight="0dp"/>
</RelativeLayout>
@@ -17,6 +17,8 @@
<!-- custom references (e.g. styles) -->
<attr name="buttonSolidSmall" format="reference"/>
<attr name="buttonSolidNormal" format="reference"/>
<attr name="textXXSmall" format="reference"/>
<attr name="textXSmall" format="reference"/>
<attr name="textSmall" format="reference"/>
<attr name="textNormal" format="reference"/>
<attr name="textLarge" format="reference"/>
@@ -15,7 +15,8 @@
<dimen name="thin_line">1dp</dimen>
<dimen name="thick_line">2dp</dimen>
<dimen name="textSize_18">18sp</dimen>
<dimen name="textSize_14">14sp</dimen> <!-- XXSmall -->
<dimen name="textSize_18">18sp</dimen> <!-- XSmall -->
<dimen name="textSize_20">20sp</dimen>
<dimen name="textSize_22">22sp</dimen> <!-- Small -->
<dimen name="textSize_26">26sp</dimen> <!-- Normal -->
@@ -31,6 +31,8 @@
<!-- styles -->
<item name="buttonSolidSmall">@style/AppTheme.Dark.Button.Small</item>
<item name="buttonSolidNormal">@style/AppTheme.Dark.Button.Normal</item>
<item name="textXXSmall">@style/AppTheme.Dark.Text.XXSmall</item>
<item name="textXSmall">@style/AppTheme.Dark.Text.XSmall</item>
<item name="textSmall">@style/AppTheme.Dark.Text.Small</item>
<item name="textNormal">@style/AppTheme.Dark.Text.Normal</item>
<item name="textLarge">@style/AppTheme.Dark.Text.Large</item>
@@ -78,6 +80,14 @@
<item name="android:textColor">?white</item>
</style>
<style name="AppTheme.Dark.Text.XXSmall">
<item name="android:textSize">@dimen/textSize_14</item>
</style>
<style name="AppTheme.Dark.Text.XSmall">
<item name="android:textSize">@dimen/textSize_18</item>
</style>
<style name="AppTheme.Dark.Text.Small">
<item name="android:textSize">@dimen/textSize_22</item>
</style>
@@ -31,6 +31,8 @@
<!-- styles -->
<item name="buttonSolidSmall">@style/AppTheme.Light.Button.Small</item>
<item name="buttonSolidNormal">@style/AppTheme.Light.Button.Normal</item>
<item name="textXXSmall">@style/AppTheme.Light.Text.XXSmall</item>
<item name="textXSmall">@style/AppTheme.Light.Text.XSmall</item>
<item name="textSmall">@style/AppTheme.Light.Text.Small</item>
<item name="textNormal">@style/AppTheme.Light.Text.Normal</item>
<item name="textLarge">@style/AppTheme.Light.Text.Large</item>
@@ -78,6 +80,14 @@
<item name="android:textColor">?white</item>
</style>
<style name="AppTheme.Light.Text.XXSmall">
<item name="android:textSize">@dimen/textSize_14</item>
</style>
<style name="AppTheme.Light.Text.XSmall">
<item name="android:textSize">@dimen/textSize_18</item>
</style>
<style name="AppTheme.Light.Text.Small">
<item name="android:textSize">@dimen/textSize_22</item>
</style>
@@ -28,6 +28,6 @@ public interface LoadClient<T> {
* @param isCached
* <code>true</code> if returned data is cached data.
*/
public void onLoadSucceded(T data, boolean isCached);
public void onLoadSucceeded(T data, boolean isCached);
}
@@ -15,7 +15,7 @@ import com.sap.sailing.racecommittee.app.data.clients.LoadClient;
*
* <p>
* On result {@link DataLoaderResult#isSuccessful()} is checked. If true
* {@link LoadClient#onLoadSucceded(Object, boolean)} is called; other {@link LoadClient#onLoadFailed(Exception)} is
* {@link LoadClient#onLoadSucceeded(Object, boolean)} is called; other {@link LoadClient#onLoadFailed(Exception)} is
* called.
* </p>
*
@@ -57,7 +57,7 @@ public class DataLoaderCallbacks<T> implements LoaderCallbacks<DataLoaderResult<
public void onLoadFinished(Loader<DataLoaderResult<T>> loader, DataLoaderResult<T> result) {
if (result.isSuccessful()) {
clientCallback.onLoadSucceded(result.getResult(), result.isResultCached());
clientCallback.onLoadSucceeded(result.getResult(), result.isResultCached());
} else {
clientCallback.onLoadFailed(result.getException());
}
@@ -0,0 +1,16 @@
package com.sap.sailing.racecommittee.app.domain.impl;
import com.sap.sailing.racecommittee.app.ui.adapters.coursedesign.CourseListDataElement;
public class CourseListDataElementWithId extends CourseListDataElement {
private long mId;
public void setId(long id) {
mId = id;
}
public long getId() {
return mId;
}
}
@@ -287,7 +287,7 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener
}
@Override
public void onLoadSucceded(DeviceConfiguration configuration, boolean isCached) {
public void onLoadSucceeded(DeviceConfiguration configuration, boolean isCached) {
setSupportProgressBarIndeterminateVisibility(false);
progressDialog.dismiss();
@@ -47,6 +47,8 @@ import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.RaceFinishingFrag
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.RaceFlagViewerFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.RaceInfoListener;
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.WindFragment;
import com.sap.sailing.racecommittee.app.ui.utils.DialogBuilder;
import com.sap.sailing.racecommittee.app.utils.ColorHelper;
import com.sap.sailing.racecommittee.app.utils.ThemeHelper;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
@@ -439,7 +441,8 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
@Override
public void onClick(DialogInterface dialog, int which) {
ExLog.i(RacingActivity.this, LogEvent.RACE_RESET_YES, mSelectedRace.getId().toString());
ExLog.w(RacingActivity.this, TAG, String.format("Race %s is selected for reset.", mSelectedRace.getId()));
ExLog.w(RacingActivity.this, TAG,
String.format("Race %s is selected for reset.", mSelectedRace.getId()));
mSelectedRace.getState().setAdvancePass(MillisecondsTimePoint.now());
onRaceItemClicked(mSelectedRace);
}
@@ -451,7 +454,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
dialog.cancel();
}
});
builder.create().show();
DialogBuilder.showColoredDialog(builder.create(), ColorHelper.getThemedColor(this, R.attr.colorAccent));
}
public void openDrawer() {
@@ -494,7 +497,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
}
@Override
public void onLoadSucceded(Collection<ManagedRace> data, boolean isCached) {
public void onLoadSucceeded(Collection<ManagedRace> data, boolean isCached) {
// Let's do the setup stuff only when the data is changed (or its the first time)
if (lastSeenRaces != null && CollectionUtils.isEqualCollection(data, lastSeenRaces)) {
ExLog.i(RacingActivity.this, TAG, "Same races are already loaded...");
@@ -535,7 +538,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
}
@Override
public void onLoadSucceded(Collection<EventBase> data, boolean isCached) {
public void onLoadSucceeded(Collection<EventBase> data, boolean isCached) {
Toast.makeText(RacingActivity.this, getString(R.string.loading_events_succeded), Toast.LENGTH_SHORT).show();
setSupportProgressBarIndeterminateVisibility(false);
@@ -564,7 +567,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
}
@Override
public void onLoadSucceded(Collection<CourseArea> data, boolean isCached) {
public void onLoadSucceeded(Collection<CourseArea> data, boolean isCached) {
Toast.makeText(RacingActivity.this, "Loading of CourseData succeeded", Toast.LENGTH_SHORT).show();
setSupportProgressBarIndeterminateVisibility(false);
@@ -0,0 +1,71 @@
package com.sap.sailing.racecommittee.app.ui.adapters;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemViewHolder;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemViewHolder;
public abstract class BaseDraggableSwipeViewHolder extends RecyclerView.ViewHolder
implements DraggableItemViewHolder, SwipeableItemViewHolder {
private int mDragStateFlags;
private int mSwipeStateFlags;
private int mSwipeResult = RecyclerViewSwipeManager.RESULT_NONE;
private int mAfterSwipeReaction = RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_DEFAULT;
private float mSwipeAmount;
public BaseDraggableSwipeViewHolder(View itemView) {
super(itemView);
}
@Override
public void setDragStateFlags(int flags) {
mDragStateFlags = flags;
}
@Override
public int getDragStateFlags() {
return mDragStateFlags;
}
@Override
public void setSwipeStateFlags(int flags) {
mSwipeStateFlags = flags;
}
@Override
public int getSwipeStateFlags() {
return mSwipeStateFlags;
}
@Override
public void setSwipeResult(int result) {
mSwipeResult = result;
}
@Override
public int getSwipeResult() {
return mSwipeResult;
}
@Override
public void setAfterSwipeReaction(int reaction) {
mAfterSwipeReaction = reaction;
}
@Override
public int getAfterSwipeReaction() {
return mAfterSwipeReaction;
}
@Override
public void setSwipeItemSlideAmount(float amount) {
mSwipeAmount = amount;
}
@Override
public float getSwipeItemSlideAmount() {
return mSwipeAmount;
}
}
@@ -0,0 +1,288 @@
package com.sap.sailing.racecommittee.app.ui.adapters.coursedesign;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemAdapter;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.domain.impl.CourseListDataElementWithId;
import com.sap.sailing.racecommittee.app.ui.adapters.BaseDraggableSwipeViewHolder;
import com.sap.sailing.racecommittee.app.ui.utils.MarkImageHelper;
import com.sap.sailing.racecommittee.app.utils.ColorHelper;
import java.util.ArrayList;
import java.util.List;
public class CourseElementAdapter extends RecyclerView.Adapter<CourseElementAdapter.ViewHolder>
implements DraggableItemAdapter<CourseElementAdapter.ViewHolder>,
SwipeableItemAdapter<CourseElementAdapter.ViewHolder> {
private final static String TAG = CourseElementAdapter.class.getName();
private Context mContext;
private List<CourseListDataElementWithId> mElements;
private MarkImageHelper mImageHelper;
private ElementLongClick mListener;
private EventListener mEventListener;
private boolean mEditable;
public CourseElementAdapter(Context context, ArrayList<CourseListDataElementWithId> elements,
MarkImageHelper imageHelper, boolean editable) {
mContext = context;
mElements = elements;
mImageHelper = imageHelper;
mEditable = editable;
setHasStableIds(true);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View layout = LayoutInflater.from(mContext).inflate(R.layout.ess_course_waypoint_item, parent, false);
return new ViewHolder(layout);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
CourseListDataElement element = mElements.get(position);
holder.dragHandle.setVisibility((mEditable) ? View.VISIBLE : View.GONE);
holder.leftText.setVisibility(View.GONE);
holder.leftImage.setVisibility(View.GONE);
if (element.getLeftMark() != null) {
holder.leftText.setText(element.getLeftMark().getName());
holder.leftText.setVisibility(View.VISIBLE);
int resId = mImageHelper.resolveMarkImage(element.getLeftMark());
holder.leftImage.setImageResource(resId);
holder.leftImage.setVisibility(View.VISIBLE);
}
holder.roundingDirection.setVisibility(View.GONE);
if (element.getPassingInstructions() != null) {
holder.roundingDirection.setText(getDisplayValueForRounding(element.getPassingInstructions()));
holder.roundingDirection.setVisibility(View.VISIBLE);
}
holder.rightText.setVisibility(View.GONE);
holder.rightImage.setVisibility(View.GONE);
if (element.getRightMark() != null) {
holder.rightText.setText(element.getRightMark().getName());
holder.rightText.setVisibility(View.VISIBLE);
int resId = mImageHelper.resolveMarkImage(element.getRightMark());
holder.rightImage.setImageResource(resId);
holder.rightImage.setVisibility(View.VISIBLE);
}
int dragState = holder.getDragStateFlags();
if ((dragState & RecyclerViewDragDropManager.STATE_FLAG_IS_UPDATED) != 0) {
int bgColor;
if ((dragState & RecyclerViewDragDropManager.STATE_FLAG_IS_ACTIVE) != 0) {
bgColor = ColorHelper.getThemedColor(mContext, R.attr.sap_gray);
} else {
bgColor = mContext.getResources().getColor(android.R.color.transparent);
}
holder.container.setBackgroundColor(bgColor);
}
}
@Override
public int getItemCount() {
if (mElements != null) {
return mElements.size();
}
return 0;
}
@Override
public long getItemId(int position) {
return mElements.get(position).getId();
}
public void setListener(ElementLongClick listener) {
mListener = listener;
}
public void setEventListener(EventListener listener) {
mEventListener = listener;
}
protected String getDisplayValueForRounding(PassingInstruction direction) {
if (PassingInstruction.Gate.equals(direction)) {
return "Gate";
}
if (PassingInstruction.Port.equals(direction)) {
return "P";
}
if (PassingInstruction.Starboard.equals(direction)) {
return "S";
}
if (PassingInstruction.Line.equals(direction)) {
return "Line";
}
if (PassingInstruction.Offset.equals(direction)) {
return "Offset";
}
return "";
}
public boolean hitTest(View v, int x, int y) {
int tx = (int) (ViewCompat.getTranslationX(v) + 0.5f);
int ty = (int) (ViewCompat.getTranslationY(v) + 0.5f);
int left = v.getLeft() + tx;
int right = v.getRight() + tx;
int top = v.getTop() + ty;
int bottom = v.getBottom() + ty;
return (x >= left) && (x <= right) && (y >= top) && (y <= bottom);
}
@Override
public boolean onCheckCanStartDrag(ViewHolder holder, int x, int y) {
ExLog.i(mContext, TAG, "onCheckCanStartDrag(" + x + ", " + y);
// x, y --- relative from the itemView's top-left
View containerView = holder.container;
View dragHandleView = holder.dragHandle;
int offsetX = containerView.getLeft() + (int) (ViewCompat.getTranslationX(containerView) + 0.5f);
int offsetY = containerView.getTop() + (int) (ViewCompat.getTranslationY(containerView) + 0.5f);
return hitTest(dragHandleView, x - offsetX, y - offsetY);
}
@Override
public ItemDraggableRange onGetItemDraggableRange(ViewHolder holder) {
return null;
}
@Override
public void onMoveItem(int fromPosition, int toPosition) {
ExLog.i(mContext, TAG, "onMoveItem(" + fromPosition + ", " + toPosition + ")");
if (fromPosition == toPosition) {
return;
}
CourseListDataElementWithId item = mElements.get(fromPosition);
mElements.remove(item);
mElements.add(toPosition, item);
notifyItemMoved(fromPosition, toPosition);
}
@Override
public int onGetSwipeReactionType(ViewHolder holder, int x, int y) {
if (onCheckCanStartDrag(holder, x, y)) {
return RecyclerViewSwipeManager.REACTION_CAN_NOT_SWIPE_BOTH;
} else {
return RecyclerViewSwipeManager.REACTION_CAN_SWIPE_BOTH;
}
}
@Override
public void onSetSwipeBackground(ViewHolder holder, int type) {
// don't change background color
}
@Override
public int onSwipeItem(ViewHolder holder, int result) {
switch (result) {
case RecyclerViewSwipeManager.RESULT_SWIPED_LEFT:
case RecyclerViewSwipeManager.RESULT_SWIPED_RIGHT:
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_REMOVE_ITEM;
default:
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_DEFAULT;
}
}
@Override
public void onPerformAfterSwipeReaction(ViewHolder holder, int result, int reaction) {
int position = holder.getAdapterPosition();
CourseListDataElementWithId element = mElements.get(position);
switch (reaction) {
case RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_REMOVE_ITEM:
mElements.remove(element);
notifyItemRemoved(position);
if (mEventListener != null) {
mEventListener.onItemRemoved(position);
}
break;
default:
break;
}
}
public interface ElementLongClick {
void onItemLongClick(CourseListDataElementWithId element);
}
public interface EventListener {
void onItemRemoved(int position);
}
protected class ViewHolder extends BaseDraggableSwipeViewHolder implements View.OnLongClickListener {
public ViewGroup container;
public ImageView dragHandle;
public TextView leftText;
public ImageView leftImage;
public TextView roundingDirection;
public TextView rightText;
public ImageView rightImage;
public ViewHolder(View itemView) {
super(itemView);
if (mEditable) {
itemView.setOnLongClickListener(this);
}
container = (ViewGroup) itemView.findViewById(R.id.container);
dragHandle = (ImageView) itemView.findViewById(R.id.drag_handle);
leftText = (TextView) itemView.findViewById(R.id.column_left_text);
leftImage = (ImageView) itemView.findViewById(R.id.column_left_image);
roundingDirection = (TextView) itemView.findViewById(R.id.rounding_direction);
rightText = (TextView) itemView.findViewById(R.id.column_right_text);
rightImage = (ImageView) itemView.findViewById(R.id.column_right_image);
}
@Override
public boolean onLongClick(View v) {
Toast.makeText(mContext, "Id " + getItemId(), Toast.LENGTH_SHORT).show();
if (mListener != null) {
mListener.onItemLongClick(mElements.get(getAdapterPosition()));
return true;
}
return false;
}
@Override
public View getSwipeableContainerView() {
return container;
}
}
}
@@ -0,0 +1,84 @@
package com.sap.sailing.racecommittee.app.ui.adapters.coursedesign;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.utils.MarkImageHelper;
import java.util.ArrayList;
import java.util.List;
public class CourseMarkAdapter extends RecyclerView.Adapter<CourseMarkAdapter.ViewHolder> {
private Context mContext;
private List<Mark> mMarks;
private MarkImageHelper mImageHelper;
private MarkLongClick mListener;
public CourseMarkAdapter(Context context, ArrayList<Mark> marks, MarkImageHelper imageHelper) {
mContext = context;
mMarks = marks;
mImageHelper = imageHelper;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View layout = LayoutInflater.from(mContext).inflate(R.layout.ess_course_item, parent, false);
return new ViewHolder(layout);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Mark mark = mMarks.get(position);
int drawable = mImageHelper.resolveMarkImage(mark);
holder.imageView.setImageResource(drawable);
holder.textView.setText(mark.getName());
}
@Override
public int getItemCount() {
if (mMarks != null) {
return mMarks.size();
}
return 0;
}
public void setListener(MarkLongClick listener) {
mListener = listener;
}
public interface MarkLongClick {
void onItemLongClick(Mark mark);
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener {
public TextView textView;
public ImageView imageView;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnLongClickListener(this);
textView = (TextView) itemView.findViewById(R.id.cell_text);
imageView = (ImageView) itemView.findViewById(R.id.cell_image);
}
@Override
public boolean onLongClick(View v) {
if (mListener != null) {
mListener.onItemLongClick(mMarks.get(getAdapterPosition()));
return true;
}
return false;
}
}
}
@@ -190,7 +190,7 @@ public class PositioningFragment extends RaceDialogFragment {
}
@Override
public void onLoadSucceded(Collection<Competitor> data, boolean isCached) {
public void onLoadSucceeded(Collection<Competitor> data, boolean isCached) {
if (!isCached) {
getActivity().setProgressBarIndeterminateVisibility(false);
}
@@ -176,8 +176,7 @@ public class ESSCourseDesignDialog extends RaceDialogFragment {
R.id.listViewPreviousCourse);
previousCourseListView.setAdapter(previousCourseElementAdapter);
takePreviousButton = (Button) getView().findViewById(
R.id.takePreviousCourseDesignButton);
takePreviousButton = (Button) getView().findViewById(R.id.takePreviousCourseDesignButton);
takePreviousButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
@@ -281,8 +280,8 @@ public class ESSCourseDesignDialog extends RaceDialogFragment {
}
@Override
public void onLoadSucceded(Collection<Mark> data,
boolean isCached) {
public void onLoadSucceeded(Collection<Mark> data,
boolean isCached) {
onLoadMarksSucceeded(data);
}
}));
@@ -122,7 +122,7 @@ public abstract class NamedListFragment<T extends Named> extends LoggableListFra
}
@Override
public void onLoadSucceded(Collection<T> data, boolean isCached) {
public void onLoadSucceeded(Collection<T> data, boolean isCached) {
setListShown(true);
namedList.clear();
namedList.addAll(data);
@@ -8,7 +8,6 @@ import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.view.LayoutInflater;
@@ -68,7 +67,6 @@ public class SetupPanelFragment extends BasePanelFragment {
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.race_panel_setup, container, false);
@@ -169,7 +167,8 @@ public class SetupPanelFragment extends BasePanelFragment {
mStartMode.setVisibility(View.VISIBLE);
}
RRS26RacingProcedure procedure = getRaceState().getTypedRacingProcedure();
mStartModeFlag.setImageDrawable(FlagsResources.getFlagDrawable(getActivity(), procedure.getStartModeFlag().name(), 48));
mStartModeFlag.setImageDrawable(
FlagsResources.getFlagDrawable(getActivity(), procedure.getStartModeFlag().name(), 48));
} catch (Exception ex) {
if (mStartMode != null) {
mStartMode.setVisibility(View.GONE);
@@ -188,61 +187,61 @@ public class SetupPanelFragment extends BasePanelFragment {
private void checkStatus() {
switch (getRace().getStatus()) {
case UNSCHEDULED:
changeVisibility(mStartProcedureLock, View.GONE);
changeVisibility(mStartModeLock, View.GONE);
changeVisibility(mCourseLock, View.GONE);
changeVisibility(mWindLock, View.GONE);
break;
case UNSCHEDULED:
changeVisibility(mStartProcedureLock, View.GONE);
changeVisibility(mStartModeLock, View.GONE);
changeVisibility(mCourseLock, View.GONE);
changeVisibility(mWindLock, View.GONE);
break;
case SCHEDULED:
case STARTPHASE:
changeVisibility(mStartProcedureLock, View.GONE);
changeVisibility(mStartModeLock, View.GONE);
changeVisibility(mCourseLock, View.GONE);
changeVisibility(mWindLock, View.GONE);
break;
case SCHEDULED:
case STARTPHASE:
changeVisibility(mStartProcedureLock, View.GONE);
changeVisibility(mStartModeLock, View.GONE);
changeVisibility(mCourseLock, View.GONE);
changeVisibility(mWindLock, View.GONE);
break;
case RUNNING:
changeVisibility(mStartProcedureLock, View.VISIBLE);
changeVisibility(mStartModeLock, View.VISIBLE);
changeVisibility(mCourseLock, View.GONE);
changeVisibility(mWindLock, View.GONE);
uncheckMarker(mStartProcedure);
uncheckMarker(mStartMode);
break;
case RUNNING:
changeVisibility(mStartProcedureLock, View.VISIBLE);
changeVisibility(mStartModeLock, View.VISIBLE);
changeVisibility(mCourseLock, View.GONE);
changeVisibility(mWindLock, View.GONE);
uncheckMarker(mStartProcedure);
uncheckMarker(mStartMode);
break;
case FINISHING:
changeVisibility(mStartProcedureLock, View.VISIBLE);
changeVisibility(mStartModeLock, View.VISIBLE);
changeVisibility(mCourseLock, View.VISIBLE);
changeVisibility(mWindLock, View.GONE);
uncheckMarker(mStartProcedure);
uncheckMarker(mStartMode);
uncheckMarker(mCourseLock);
break;
case FINISHING:
changeVisibility(mStartProcedureLock, View.VISIBLE);
changeVisibility(mStartModeLock, View.VISIBLE);
changeVisibility(mCourseLock, View.VISIBLE);
changeVisibility(mWindLock, View.GONE);
uncheckMarker(mStartProcedure);
uncheckMarker(mStartMode);
uncheckMarker(mCourseLock);
break;
case FINISHED:
changeVisibility(mStartProcedureLock, View.GONE);
changeVisibility(mStartModeLock, View.GONE);
changeVisibility(mCourseLock, View.GONE);
changeVisibility(mWindLock, View.GONE);
uncheckMarker(mStartProcedure);
uncheckMarker(mStartMode);
uncheckMarker(mCourse);
uncheckMarker(mWind);
break;
case FINISHED:
changeVisibility(mStartProcedureLock, View.GONE);
changeVisibility(mStartModeLock, View.GONE);
changeVisibility(mCourseLock, View.GONE);
changeVisibility(mWindLock, View.GONE);
uncheckMarker(mStartProcedure);
uncheckMarker(mStartMode);
uncheckMarker(mCourse);
uncheckMarker(mWind);
break;
default:
changeVisibility(mStartProcedureLock, View.VISIBLE);
changeVisibility(mStartModeLock, View.VISIBLE);
changeVisibility(mCourseLock, View.VISIBLE);
changeVisibility(mWindLock, View.VISIBLE);
uncheckMarker(mStartProcedure);
uncheckMarker(mStartMode);
uncheckMarker(mCourse);
uncheckMarker(mWind);
break;
default:
changeVisibility(mStartProcedureLock, View.VISIBLE);
changeVisibility(mStartModeLock, View.VISIBLE);
changeVisibility(mCourseLock, View.VISIBLE);
changeVisibility(mWindLock, View.VISIBLE);
uncheckMarker(mStartProcedure);
uncheckMarker(mStartMode);
uncheckMarker(mCourse);
uncheckMarker(mWind);
break;
}
}
@@ -337,19 +336,20 @@ public class SetupPanelFragment extends BasePanelFragment {
@Override
public void onClick(View v) {
if (mStartProcedureLock == null || mStartProcedureLock.getVisibility() == View.GONE) {
sendIntent(AppConstants.INTENT_ACTION_TOGGLE, AppConstants.INTENT_ACTION_EXTRA, AppConstants.INTENT_ACTION_TOGGLE_PROCEDURE);
sendIntent(AppConstants.INTENT_ACTION_TOGGLE, AppConstants.INTENT_ACTION_EXTRA,
AppConstants.INTENT_ACTION_TOGGLE_PROCEDURE);
switch (toggleMarker(v, R.id.start_procedure_marker)) {
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 1:
replaceFragment(StartProcedureFragment.newInstance(1));
break;
case 1:
replaceFragment(StartProcedureFragment.newInstance(1));
break;
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
break;
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
break;
}
}
}
@@ -362,18 +362,19 @@ public class SetupPanelFragment extends BasePanelFragment {
@Override
public void onClick(View v) {
if (mStartModeLock == null || mStartModeLock.getVisibility() == View.GONE) {
sendIntent(AppConstants.INTENT_ACTION_TOGGLE, AppConstants.INTENT_ACTION_EXTRA, AppConstants.INTENT_ACTION_TOGGLE_MODE);
sendIntent(AppConstants.INTENT_ACTION_TOGGLE, AppConstants.INTENT_ACTION_EXTRA,
AppConstants.INTENT_ACTION_TOGGLE_MODE);
switch (toggleMarker(v, R.id.start_mode_marker)) {
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 1:
replaceFragment(StartModeFragment.newInstance(1));
break;
case 1:
replaceFragment(StartModeFragment.newInstance(1));
break;
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
}
}
}
@@ -386,18 +387,19 @@ public class SetupPanelFragment extends BasePanelFragment {
@Override
public void onClick(View v) {
if (mCourseLock == null || mCourseLock.getVisibility() == View.GONE) {
sendIntent(AppConstants.INTENT_ACTION_TOGGLE, AppConstants.INTENT_ACTION_EXTRA, AppConstants.INTENT_ACTION_TOGGLE_COURSE);
sendIntent(AppConstants.INTENT_ACTION_TOGGLE, AppConstants.INTENT_ACTION_EXTRA,
AppConstants.INTENT_ACTION_TOGGLE_COURSE);
switch (toggleMarker(v, R.id.course_marker)) {
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 1:
replaceFragment(CourseFragment.newInstance(1));
break;
case 1:
replaceFragment(CourseFragment.newInstance(1, getRace()));
break;
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
}
}
}
@@ -410,18 +412,19 @@ public class SetupPanelFragment extends BasePanelFragment {
@Override
public void onClick(View v) {
if (mWindLock == null || mWindLock.getVisibility() == View.GONE) {
sendIntent(AppConstants.INTENT_ACTION_TOGGLE, AppConstants.INTENT_ACTION_EXTRA, AppConstants.INTENT_ACTION_TOGGLE_WIND);
sendIntent(AppConstants.INTENT_ACTION_TOGGLE, AppConstants.INTENT_ACTION_EXTRA,
AppConstants.INTENT_ACTION_TOGGLE_WIND);
switch (toggleMarker(v, R.id.wind_marker)) {
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 1:
replaceFragment(WindFragment.newInstance(1));
break;
case 1:
replaceFragment(WindFragment.newInstance(1));
break;
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
}
}
}
@@ -86,7 +86,7 @@ public abstract class BaseRaceInfoRaceFragment<ProcedureType extends RacingProce
}
protected void showCourseDesignDialog() {
RaceDialogFragment fragment = CourseDesignerChooser.choose(preferences, getRace());
RaceDialogFragment fragment = CourseDesignerChooser.choose(getRace());
fragment.setArguments(getRecentArguments());
fragment.show(getFragmentManager(), "courseDesignDialogFragment");
}
@@ -1,12 +1,72 @@
package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
import android.os.Bundle;
import android.view.View;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.common.CourseDesignerMode;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.ui.fragments.RaceFragment;
public abstract class CourseFragment extends BaseFragment {
public static RaceFragment newInstance(int startMode) {
return CourseFragmentName.newInstance(startMode);
protected static final String START_MODE = "startMode";
public static RaceFragment newInstance(int startMode, ManagedRace race) {
RaceFragment fragment;
RegattaConfiguration configuration = race.getState().getConfiguration();
CourseDesignerMode mode = configuration.getDefaultCourseDesignerMode();
switch (mode) {
case BY_NAME:
fragment = CourseFragmentName.newInstance(startMode);
break;
case BY_MAP:
fragment = CourseFragmentMap.newInstance(startMode);
break;
case BY_MARKS:
fragment = CourseFragmentMarks.newInstance(startMode);
break;
default:
throw new IllegalArgumentException("Invalid CourseDesignerMode");
}
return fragment;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getView() != null) {
if (getArguments() != null) {
View header = getView().findViewById(R.id.header);
if (header != null) {
switch (getArguments().getInt(START_MODE, 0)) {
case 1:
header.setVisibility(View.GONE);
break;
default:
View text = header.findViewById(R.id.header_text);
if (text != null) {
text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openMainScheduleFragment();
}
});
}
break;
}
}
}
}
}
@Override
@@ -6,12 +6,17 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.fragments.RaceFragment;
public class CourseFragmentMap extends CourseFragment {
public CourseFragmentMap() {
private static final String TAG = CourseFragmentMap.class.getName();
public static CourseFragmentMap newInstance(int startMode) {
CourseFragmentMap fragment = new CourseFragmentMap();
Bundle args = new Bundle();
args.putInt(START_MODE, startMode);
fragment.setArguments(args);
return fragment;
}
@Override
@@ -1,25 +1,497 @@
package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Loader;
import android.graphics.drawable.NinePatchDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import com.h6ah4i.android.widget.advrecyclerview.animator.SwipeDismissItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.decoration.ItemShadowDecorator;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager;
import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager;
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils;
import com.sap.sailing.domain.base.*;
import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl;
import com.sap.sailing.domain.base.impl.CourseDataImpl;
import com.sap.sailing.domain.base.impl.WaypointImpl;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.fragments.RaceFragment;
import com.sap.sailing.racecommittee.app.data.DataManager;
import com.sap.sailing.racecommittee.app.data.InMemoryDataStore;
import com.sap.sailing.racecommittee.app.data.ReadonlyDataManager;
import com.sap.sailing.racecommittee.app.data.clients.LoadClient;
import com.sap.sailing.racecommittee.app.domain.impl.CourseListDataElementWithId;
import com.sap.sailing.racecommittee.app.ui.adapters.coursedesign.CourseElementAdapter;
import com.sap.sailing.racecommittee.app.ui.adapters.coursedesign.CourseElementAdapter.ElementLongClick;
import com.sap.sailing.racecommittee.app.ui.adapters.coursedesign.CourseElementAdapter.EventListener;
import com.sap.sailing.racecommittee.app.ui.adapters.coursedesign.CourseListDataElement;
import com.sap.sailing.racecommittee.app.ui.adapters.coursedesign.CourseMarkAdapter;
import com.sap.sailing.racecommittee.app.ui.adapters.coursedesign.CourseMarkAdapter.MarkLongClick;
import com.sap.sailing.racecommittee.app.ui.comparators.NaturalNamedComparator;
import com.sap.sailing.racecommittee.app.ui.utils.DialogBuilder;
import com.sap.sailing.racecommittee.app.ui.utils.ESSMarkImageHelper;
import com.sap.sailing.racecommittee.app.utils.ColorHelper;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class CourseFragmentMarks extends CourseFragment {
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class CourseFragmentMarks extends CourseFragment implements MarkLongClick, ElementLongClick, EventListener {
private RecyclerViewDragDropManager mDragDropManager;
private RecyclerViewSwipeManager mSwipeManager;
private RecyclerViewTouchActionGuardManager mGuardManager;
private ReadonlyDataManager mDataManager;
private ArrayList<CourseListDataElementWithId> mHistory;
private ArrayList<CourseListDataElementWithId> mElements;
private ArrayList<Mark> mMarks;
private RecyclerView mHistoryCourse;
private RecyclerView mCurrentCourse;
private RecyclerView mMarkGrid;
private CourseElementAdapter mHistoryAdapter;
private RecyclerView.Adapter mCourseAdapter;
private CourseMarkAdapter mMarkAdapter;
private int mId;
public CourseFragmentMarks() {
super();
mId = 0;
mHistory = new ArrayList<>();
mElements = new ArrayList<>();
mMarks = new ArrayList<>();
}
public static CourseFragmentMarks newInstance(int startMode) {
CourseFragmentMarks fragment = new CourseFragmentMarks();
Bundle args = new Bundle();
args.putInt(START_MODE, startMode);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.race_schedule_course_marks, container, false);
Button confirm = (Button) view.findViewById(R.id.confirm);
mHistoryCourse = (RecyclerView) view.findViewById(R.id.previous_course);
if (mHistoryCourse != null) {
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
mHistoryCourse.setLayoutManager(layoutManager);
mHistoryAdapter = new CourseElementAdapter(getActivity(), mHistory, ESSMarkImageHelper.getInstance(),
false);
mHistoryCourse.setAdapter(mHistoryAdapter);
}
mCurrentCourse = (RecyclerView) view.findViewById(R.id.new_course);
if (mCurrentCourse != null) {
mGuardManager = new RecyclerViewTouchActionGuardManager();
mGuardManager.setInterceptVerticalScrollingWhileAnimationRunning(true);
mGuardManager.setEnabled(true);
mDragDropManager = new RecyclerViewDragDropManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mDragDropManager.setDraggingItemShadowDrawable(
(NinePatchDrawable) getActivity().getDrawable(R.drawable.material_shadow_z3));
} else {
mDragDropManager.setDraggingItemShadowDrawable(
(NinePatchDrawable) getResources().getDrawable(R.drawable.material_shadow_z3));
}
mSwipeManager = new RecyclerViewSwipeManager();
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
CourseElementAdapter adapter = new CourseElementAdapter(getActivity(), mElements,
ESSMarkImageHelper.getInstance(), true);
adapter.setListener(this);
adapter.setEventListener(this);
mCourseAdapter = mDragDropManager.createWrappedAdapter(adapter);
mCourseAdapter = mSwipeManager.createWrappedAdapter(mCourseAdapter);
mCurrentCourse.setLayoutManager(layoutManager);
mCurrentCourse.setAdapter(mCourseAdapter);
mCurrentCourse.setItemAnimator(new SwipeDismissItemAnimator());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
mCurrentCourse.addItemDecoration(new ItemShadowDecorator(
(NinePatchDrawable) getResources().getDrawable(R.drawable.material_shadow_z1)));
}
mGuardManager.attachRecyclerView(mCurrentCourse);
mSwipeManager.attachRecyclerView(mCurrentCourse);
mDragDropManager.attachRecyclerView(mCurrentCourse);
}
mMarkGrid = (RecyclerView) view.findViewById(R.id.assets);
if (mMarkGrid != null) {
GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 3);
mMarkGrid.setLayoutManager(layoutManager);
mMarkAdapter = new CourseMarkAdapter(getActivity(), mMarks, ESSMarkImageHelper.getInstance());
mMarkAdapter.setListener(this);
mMarkGrid.setAdapter(mMarkAdapter);
}
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mDataManager = DataManager.create(getActivity());
if (getRace().getCourseDesign() != null) {
fillCourseElement();
}
loadMarks();
fillPreviousCourseElementsWithLastPublishedCourseDesign();
if (getView() != null) {
Button takePreviousButton = (Button) getView().findViewById(R.id.takeHistoryCourse);
takePreviousButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (!mHistory.isEmpty()) {
if (!mElements.isEmpty()) {
createUsePreviousCourseDialog();
} else {
copyPreviousToNewCourseDesign();
}
} else {
Toast.makeText(getActivity(), "No course available to copy", Toast.LENGTH_LONG).show();
}
}
});
Button publishButton = (Button) getView().findViewById(R.id.publishCourse);
publishButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
try {
CourseBase courseData = convertCourseElementsToACourseData();
sendCourseDataAndDismiss(courseData);
} catch (IllegalStateException ex) {
if (ex.getMessage().equals("Missing second mark")) {
Toast.makeText(getActivity(),
"The selected passing instructions require two buoys. Please select the second buoy.",
Toast.LENGTH_LONG).show();
} else if (ex.getMessage().equals("Each waypoints needs passing instructions")) {
Toast.makeText(getActivity(),
"A waypoint has no passing instructions. Please select the passing instruction by clicking long on the waypoint.",
Toast.LENGTH_LONG).show();
}
} catch (IllegalArgumentException ex) {
Toast.makeText(getActivity(), "The course design has to have at least one waypoint.",
Toast.LENGTH_LONG).show();
}
}
});
Button unpublishButton = (Button) getView().findViewById(R.id.unpublishCourse);
unpublishButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
CourseBase emptyCourse = new CourseDataImpl("Unpublished course design");
sendCourseDataAndDismiss(emptyCourse);
}
});
}
}
@Override
public void onPause() {
mDragDropManager.cancelDrag();
super.onPause();
}
@Override
public void onDestroy() {
if (mDragDropManager != null) {
mDragDropManager.release();
mDragDropManager = null;
}
if (mSwipeManager != null) {
mSwipeManager.release();
mSwipeManager = null;
}
if (mGuardManager != null) {
mGuardManager.release();
mGuardManager = null;
}
if (mHistoryCourse != null) {
mHistoryCourse.setAdapter(null);
mHistoryCourse = null;
}
if (mCurrentCourse != null) {
mCurrentCourse.setItemAnimator(null);
mCurrentCourse.setAdapter(null);
mCurrentCourse = null;
}
if (mMarkGrid != null) {
mMarkGrid.setAdapter(null);
mMarkGrid = null;
}
if (mCourseAdapter != null) {
WrapperAdapterUtils.releaseAll(mCourseAdapter);
mCourseAdapter = null;
}
super.onDestroy();
}
private void fillCourseElement() {
mElements.clear();
mElements.addAll(convertCourseDesignToCourseElements(getRace().getCourseDesign()));
mCourseAdapter.notifyDataSetChanged();
}
private void loadMarks() {
Loader<?> marksLoader = getLoaderManager()
.restartLoader(0, null, mDataManager.createMarksLoader(getRace(), new LoadClient<Collection<Mark>>() {
@Override
public void onLoadFailed(Exception reason) {
Toast.makeText(getActivity(), String.format("Marks: %s", reason.toString()), Toast.LENGTH_LONG)
.show();
}
@Override
public void onLoadSucceeded(Collection<Mark> data, boolean isCached) {
onLoadMarksSucceeded(data);
}
}));
marksLoader.forceLoad();
}
private void onLoadMarksSucceeded(Collection<Mark> data) {
mMarks.clear();
mMarks.addAll(data);
Collections.sort(mMarks, new NaturalNamedComparator());
mMarkAdapter.notifyDataSetChanged();
}
protected List<CourseListDataElementWithId> convertCourseDesignToCourseElements(CourseBase courseData) {
List<CourseListDataElementWithId> elementList = new ArrayList<>();
for (Waypoint waypoint : courseData.getWaypoints()) {
ControlPoint controlPoint = waypoint.getControlPoint();
if (controlPoint instanceof Mark) {
CourseListDataElementWithId element = new CourseListDataElementWithId();
element.setId(mId);
element.setLeftMark((Mark) controlPoint);
element.setPassingInstructions(waypoint.getPassingInstructions());
elementList.add(element);
} else if (controlPoint instanceof ControlPointWithTwoMarks) {
ControlPointWithTwoMarks controlPointTwoMarks = (ControlPointWithTwoMarks) controlPoint;
CourseListDataElementWithId element = new CourseListDataElementWithId();
element.setId(mId);
element.setLeftMark(controlPointTwoMarks.getLeft());
element.setRightMark(controlPointTwoMarks.getRight());
element.setPassingInstructions(waypoint.getPassingInstructions());
elementList.add(element);
}
mId++;
}
return elementList;
}
@Override
public void onItemLongClick(CourseListDataElementWithId element) {
createPassingInstructionDialog(element);
mCourseAdapter.notifyDataSetChanged();
}
@Override
public void onItemLongClick(Mark mark) {
if (mElements.isEmpty()) {
addNewCourseElementToList(mark);
} else {
CourseListDataElement twoMarksCourseElement = getFirstTwoMarksCourseElementWithoutRightMark();
if (twoMarksCourseElement != null) {
twoMarksCourseElement.setRightMark(mark);
mCourseAdapter.notifyDataSetChanged();
} else {
addNewCourseElementToList(mark);
}
}
}
private CourseListDataElement getFirstTwoMarksCourseElementWithoutRightMark() {
for (CourseListDataElement courseElement : mElements) {
if ((courseElement.getPassingInstructions().equals(PassingInstruction.Gate) || courseElement
.getPassingInstructions().equals(PassingInstruction.Line) || courseElement.getPassingInstructions()
.equals(PassingInstruction.Offset)) && courseElement.getRightMark() == null) {
return courseElement;
}
}
return null;
}
private void addNewCourseElementToList(Mark mark) {
CourseListDataElementWithId courseElement = new CourseListDataElementWithId();
courseElement.setId(mId);
courseElement.setLeftMark(mark);
createPassingInstructionDialog(courseElement);
mId++;
}
private void createPassingInstructionDialog(final CourseListDataElementWithId courseElement) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_a_rounding_direction)
.setItems(R.array.rounding_directions, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int position) {
PassingInstruction pickedDirection = PassingInstruction.relevantValues()[position];
onPassingInstructionPicked(courseElement, pickedDirection);
}
});
DialogBuilder
.showColoredDialog(builder.create(), ColorHelper.getThemedColor(getActivity(), R.attr.colorAccent));
}
protected void onPassingInstructionPicked(CourseListDataElementWithId courseElement,
PassingInstruction pickedDirection) {
courseElement.setPassingInstructions(pickedDirection);
if (!mElements.contains(courseElement)) {
mElements.add(courseElement);
}
mCourseAdapter.notifyDataSetChanged();
}
private void fillPreviousCourseElementsWithLastPublishedCourseDesign() {
CourseBase lastPublishedCourseDesign = InMemoryDataStore.INSTANCE.getLastPublishedCourseDesign();
if (lastPublishedCourseDesign != null) {
fillPreviousCourseElementsInList(lastPublishedCourseDesign);
}
}
private void fillPreviousCourseElementsInList(CourseBase previousCourseData) {
if (previousCourseData != null) {
mHistory.clear();
mHistory.addAll(convertCourseDesignToCourseElements(previousCourseData));
mHistoryAdapter.notifyDataSetChanged();
}
}
private void createUsePreviousCourseDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Use previous course design");
builder.setMessage("Use previously published course design?");
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
copyPreviousToNewCourseDesign();
}
});
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
});
DialogBuilder.showColoredDialog(builder.create(), ColorHelper.getThemedColor(getActivity(), R.attr.colorAccent));
}
protected void copyPreviousToNewCourseDesign() {
mElements.clear();
mElements.addAll(mHistory);
mCourseAdapter.notifyDataSetChanged();
}
protected CourseBase convertCourseElementsToACourseData() throws IllegalStateException, IllegalArgumentException {
// TODO find a proper name for the highly flexible ESS courses to be shown on the regatta overview page
CourseBase design = new CourseDataImpl("Course");
List<Waypoint> waypoints = new ArrayList<>();
for (CourseListDataElement courseElement : mElements) {
if ((courseElement.getPassingInstructions().equals(PassingInstruction.Gate)
|| courseElement.getPassingInstructions().equals(PassingInstruction.Line) || courseElement
.getPassingInstructions().equals(PassingInstruction.Offset))) {
if (courseElement.getRightMark() != null) {
String cpwtmName = "ControlPointWithTwoMarks " + courseElement.getLeftMark().getName() + " / "
+ courseElement.getRightMark().getName();
ControlPointWithTwoMarks cpwtm = new ControlPointWithTwoMarksImpl(courseElement.getLeftMark(),
courseElement.getRightMark(), cpwtmName);
Waypoint waypoint = new WaypointImpl(cpwtm, courseElement.getPassingInstructions());
waypoints.add(waypoint);
} else {
throw new IllegalStateException("Missing second mark");
}
} else if (courseElement.getPassingInstructions().equals(PassingInstruction.None)) {
throw new IllegalStateException("Each waypoints needs passing instructions");
} else {
Waypoint waypoint = new WaypointImpl(courseElement.getLeftMark(),
courseElement.getPassingInstructions());
waypoints.add(waypoint);
}
}
if (waypoints.isEmpty()) {
throw new IllegalArgumentException("The course design to be published has no waypoints.");
}
int i = 0;
for (Waypoint waypoint : waypoints) {
design.addWaypoint(i++, waypoint);
}
return design;
}
private void saveChangedCourseDesignInCache(CourseBase courseDesign) {
if (!Util.isEmpty(courseDesign.getWaypoints())) {
InMemoryDataStore.INSTANCE.setLastPublishedCourseDesign(courseDesign);
}
}
protected void sendCourseDataAndDismiss(CourseBase courseDesign) {
getRaceState().setCourseDesign(MillisecondsTimePoint.now(), courseDesign);
saveChangedCourseDesignInCache(courseDesign);
switch (getArguments().getInt(START_MODE, 0)) {
case 1:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
default:
openMainScheduleFragment();
break;
}
}
@Override
public void onItemRemoved(int position) {
// do nothing - later maybe show "undo" or something
}
}
@@ -7,50 +7,27 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.impl.CourseDataImpl;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.adapters.CourseNameAdapter;
import com.sap.sailing.racecommittee.app.ui.fragments.RaceFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.panels.TimePanelFragment;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class CourseFragmentName extends CourseFragment implements CourseNameAdapter.CourseItemClick {
private static final String TAG = CourseFragmentName.class.getName();
private static final String STARTMODE = "startMode";
private ListView mListView;
public static CourseFragmentName newInstance(int startMode) {
CourseFragmentName fragment = new CourseFragmentName();
Bundle args = new Bundle();
args.putInt(STARTMODE, startMode);
args.putInt(START_MODE, startMode);
fragment.setArguments(args);
return fragment;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getView() != null) {
if (getArguments() != null) {
switch (getArguments().getInt(STARTMODE, 0)) {
case 1:
View header = getView().findViewById(R.id.header);
header.setVisibility(View.GONE);
break;
default:
break;
}
}
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.race_schedule_course_name, container, false);
@@ -85,7 +62,7 @@ public class CourseFragmentName extends CourseFragment implements CourseNameAdap
CourseBase courseLayout = new CourseDataImpl(course);
getRaceState().setCourseDesign(MillisecondsTimePoint.now(), courseLayout);
if (getArguments() != null && getArguments().getInt(STARTMODE, 0) == 0) {
if (getArguments() != null && getArguments().getInt(START_MODE, 0) == 0) {
openMainScheduleFragment();
} else {
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
@@ -174,7 +174,7 @@ public class MainScheduleFragment extends RaceFragment implements View.OnClickLi
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_course:
openFragment(CourseFragment.newInstance(0));
openFragment(CourseFragment.newInstance(0, getRace()));
break;
case R.id.start_mode:
@@ -161,7 +161,7 @@ public class SetStartTimeRaceFragment extends RaceFragment {
}
private void showCourseDesignDialog() {
RaceDialogFragment fragment = CourseDesignerChooser.choose(preferences, getRace());
RaceDialogFragment fragment = CourseDesignerChooser.choose(getRace());
fragment.setArguments(getRecentArguments());
fragment.show(getFragmentManager(), "courseDesignDialogFragment");
}
@@ -2,7 +2,6 @@ package com.sap.sailing.racecommittee.app.ui.utils;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.common.CourseDesignerMode;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.RaceDialogFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.coursedesign.ByMapCourseDesignDialog;
@@ -10,11 +9,11 @@ import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.coursedesign.ByNam
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.coursedesign.ESSCourseDesignDialog;
public class CourseDesignerChooser {
public static RaceDialogFragment choose(AppPreferences preferences, ManagedRace race) {
public static RaceDialogFragment choose(ManagedRace race) {
RegattaConfiguration configuration = race.getState().getConfiguration();
CourseDesignerMode mode = configuration.getDefaultCourseDesignerMode();
switch (mode) {
case BY_MAP:
return new ByMapCourseDesignDialog();
@@ -0,0 +1,468 @@
package com.sap.sailing.racecommittee.app.ui.utils;
/*
* Copyright (C) 2014 Jared Rummler <jared.rummler@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.*;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.view.View;
import android.view.WindowManager;
import android.widget.*;
/**
* Class which extends {@link AlertDialog.Builder}.</p>
* <p/>
* This adds the ability to set the color for the title, icon, divider, and progressbar.</p>
*
* @author Jared Rummler <jared.rummler@gmail.com>
* @since Dec 11, 2014
*/
public class DialogBuilder extends AlertDialog.Builder {
// ===========================================================
// STATIC FIELDS
// ===========================================================
private static final String DIALOG_COLOR_ERROR = "The dialog must be shown before any color changes can be made. Call dialog.show() beforehand.";
// ===========================================================
// STATIC METHODS
// ===========================================================
private int mIconColor = -1;
private int mTitleColor = -1;
private int mDividerColor = -1;
private int mProgressBarColor = -1;
public DialogBuilder(Context context) {
super(context);
}
public DialogBuilder(Context context, final int theme) {
super(context, theme);
}
/**
* Returns a new {@link DialogInterface.OnClickListener} that dismisses the dialog in
* {@link DialogInterface.OnClickListener#onClick(DialogInterface, int)}
*/
public static DialogInterface.OnClickListener newOnDismissListener() {
return new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, final int which) {
dialog.dismiss();
}
};
}
/**
* As long as this dialog is visible to the user, keep the device's screen turned on and bright.
*
* @param dialog
*/
public static void keepScreenOn(Dialog dialog) {
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
// ===========================================================
// FIELDS
// ===========================================================
/**
* @see #showColoredDialog(Dialog, int, boolean, boolean, boolean, boolean)
*/
public static void showColoredDialog(Dialog dialog, final int color) {
showColoredDialog(dialog, color, true, true, true, true);
}
/**
* Show a dialog and apply a color to it.
*
* @param dialog The dialog to show
* @param color The color to tint the icon, title, divider, progress-bar, etc.
* @param setIconColor {@code true} to set a ColorFilter on the title icon color.
* @param setTitleColor {@code true} to set the text color on the title.
* @param setDividerColor {@code true} to set the color for the title divider.
* @param setProgressBarColor {@code true} to set the color for the horizontal progress bar.
*/
public static void showColoredDialog(Dialog dialog, final int color, final boolean setIconColor,
final boolean setTitleColor, final boolean setDividerColor, final boolean setProgressBarColor) {
if (!dialog.isShowing()) {
dialog.show();
}
if (setIconColor) {
setIconColor(dialog, color);
}
if (setTitleColor) {
setTitleColor(dialog, color);
}
if (setDividerColor) {
setDividerColor(dialog, color);
}
if (setProgressBarColor) {
setProgressBarColor(dialog, color);
}
}
public static void setIconColor(Dialog dialog, final int color) {
if (!dialog.isShowing()) {
throw new RuntimeException(DIALOG_COLOR_ERROR);
}
if (color != -1) {
final int iconId = dialog.getContext().getResources().getIdentifier("android:id/icon", null, null);
if (iconId != 0) {
final ImageView icon = (ImageView) dialog.findViewById(iconId);
if (icon != null) {
icon.setColorFilter(color);
}
}
}
}
public static void setTitleColor(Dialog dialog, final int color) {
if (!dialog.isShowing()) {
throw new RuntimeException(DIALOG_COLOR_ERROR);
}
if (color != -1) {
final int textViewId = dialog.getContext().getResources()
.getIdentifier("android:id/alertTitle", null, null);
if (textViewId != 0) {
final TextView tv = (TextView) dialog.findViewById(textViewId);
if (tv != null) {
tv.setTextColor(color);
}
}
}
}
// ===========================================================
// CONSTRUCTORS
// ===========================================================
public static void setDividerColor(Dialog dialog, final int color) {
if (!dialog.isShowing()) {
throw new RuntimeException(DIALOG_COLOR_ERROR);
}
if (color != -1) {
final int dividerId = dialog.getContext().getResources()
.getIdentifier("android:id/titleDivider", null, null);
if (dividerId != 0) {
final View divider = dialog.findViewById(dividerId);
if (divider != null) {
divider.setBackgroundColor(color);
}
}
}
}
public static void setProgressBarColor(Dialog dialog, final int color) {
if (!dialog.isShowing()) {
throw new RuntimeException(DIALOG_COLOR_ERROR);
}
if (color != -1) {
try {
final ProgressBar bar = (ProgressBar) dialog.findViewById(android.R.id.progress);
final LayerDrawable ld = (LayerDrawable) bar.getProgressDrawable();
final Drawable progress = ld.getDrawable(2);
progress.setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_ATOP);
ld.setDrawableByLayerId(android.R.id.progress, progress);
bar.setProgressDrawable(ld);
} catch (Exception ignore) {
}
}
}
// ===========================================================
// METHODS FOR/FROM SUPERCLASS/INTERFACES
// ===========================================================
@Override
public DialogBuilder setTitle(int titleId) {
super.setTitle(titleId);
return this;
}
@Override
public DialogBuilder setTitle(CharSequence title) {
super.setTitle(title);
return this;
}
@Override
public DialogBuilder setCustomTitle(View customTitleView) {
super.setCustomTitle(customTitleView);
return this;
}
@Override
public DialogBuilder setMessage(int messageId) {
super.setMessage(messageId);
return this;
}
@Override
public DialogBuilder setMessage(CharSequence message) {
super.setMessage(message);
return this;
}
@Override
public DialogBuilder setIcon(int iconId) {
super.setIcon(iconId);
return this;
}
@Override
public DialogBuilder setIcon(Drawable icon) {
super.setIcon(icon);
return this;
}
@Override
public DialogBuilder setIconAttribute(int attrId) {
super.setIconAttribute(attrId);
return this;
}
@Override
public DialogBuilder setPositiveButton(int textId, final OnClickListener listener) {
super.setPositiveButton(textId, listener);
return this;
}
@Override
public DialogBuilder setPositiveButton(CharSequence text, final OnClickListener listener) {
super.setPositiveButton(text, listener);
return this;
}
@Override
public DialogBuilder setNegativeButton(int textId, final OnClickListener listener) {
super.setNegativeButton(textId, listener);
return this;
}
@Override
public DialogBuilder setNegativeButton(CharSequence text, final OnClickListener listener) {
super.setNegativeButton(text, listener);
return this;
}
@Override
public DialogBuilder setNeutralButton(int textId, final OnClickListener listener) {
super.setNeutralButton(textId, listener);
return this;
}
@Override
public DialogBuilder setNeutralButton(CharSequence text, final OnClickListener listener) {
super.setNeutralButton(text, listener);
return this;
}
@Override
public DialogBuilder setCancelable(boolean cancelable) {
super.setCancelable(cancelable);
return this;
}
@Override
public DialogBuilder setOnCancelListener(OnCancelListener onCancelListener) {
super.setOnCancelListener(onCancelListener);
return this;
}
@Override
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public DialogBuilder setOnDismissListener(OnDismissListener onDismissListener) {
super.setOnDismissListener(onDismissListener);
return this;
}
@Override
public DialogBuilder setOnKeyListener(OnKeyListener onKeyListener) {
super.setOnKeyListener(onKeyListener);
return this;
}
@Override
public DialogBuilder setItems(int itemsId, final OnClickListener listener) {
super.setItems(itemsId, listener);
return this;
}
@Override
public DialogBuilder setItems(CharSequence[] items, final OnClickListener listener) {
super.setItems(items, listener);
return this;
}
@Override
public DialogBuilder setAdapter(ListAdapter adapter, final OnClickListener listener) {
super.setAdapter(adapter, listener);
return this;
}
@Override
public DialogBuilder setCursor(Cursor cursor, final OnClickListener listener, final String labelColumn) {
super.setCursor(cursor, listener, labelColumn);
return this;
}
@Override
public DialogBuilder setMultiChoiceItems(int itemsId, final boolean[] checkedItems,
final OnMultiChoiceClickListener listener) {
super.setMultiChoiceItems(itemsId, checkedItems, listener);
return this;
}
@Override
public DialogBuilder setMultiChoiceItems(CharSequence[] items, final boolean[] checkedItems,
final OnMultiChoiceClickListener listener) {
super.setMultiChoiceItems(items, checkedItems, listener);
return this;
}
@Override
public DialogBuilder setMultiChoiceItems(Cursor cursor, final String isCheckedColumn, final String labelColumn,
final OnMultiChoiceClickListener listener) {
super.setMultiChoiceItems(cursor, isCheckedColumn, labelColumn, listener);
return this;
}
@Override
public DialogBuilder setSingleChoiceItems(int itemsId, final int checkedItem, final OnClickListener listener) {
super.setSingleChoiceItems(itemsId, checkedItem, listener);
return this;
}
@Override
public DialogBuilder setSingleChoiceItems(Cursor cursor, final int checkedItem, final String labelColumn,
final OnClickListener listener) {
super.setSingleChoiceItems(cursor, checkedItem, labelColumn, listener);
return this;
}
@Override
public DialogBuilder setSingleChoiceItems(CharSequence[] items, final int checkedItem,
final OnClickListener listener) {
super.setSingleChoiceItems(items, checkedItem, listener);
return this;
}
@Override
public DialogBuilder setSingleChoiceItems(ListAdapter adapter, final int checkedItem,
final OnClickListener listener) {
super.setSingleChoiceItems(adapter, checkedItem, listener);
return this;
}
@Override
public DialogBuilder setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {
super.setOnItemSelectedListener(listener);
return this;
}
@Override
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public DialogBuilder setView(int layoutResId) {
super.setView(layoutResId);
return this;
}
@Override
public DialogBuilder setView(View view) {
super.setView(view);
return this;
}
@Override
public DialogBuilder setInverseBackgroundForced(boolean useInverseBackground) {
super.setInverseBackgroundForced(useInverseBackground);
return this;
}
@Override
public AlertDialog show() {
final AlertDialog dialog = super.show();
setIconColor(dialog, mIconColor);
setTitleColor(dialog, mTitleColor);
setDividerColor(dialog, mDividerColor);
setProgressBarColor(dialog, mProgressBarColor);
return dialog;
}
// ===========================================================
// METHODS
// ===========================================================
/**
* @param color The color for the title icon, text, divider, and progressbar.
* @return This Builder object to allow for chaining of calls to set methods
*/
public DialogBuilder setColor(int color) {
mIconColor = color;
mTitleColor = color;
mDividerColor = color;
mProgressBarColor = color;
return this;
}
/**
* @param iconColor The color for the title icon.
* @return This Builder object to allow for chaining of calls to set methods
*/
public DialogBuilder setIconColor(int iconColor) {
mIconColor = iconColor;
return this;
}
/**
* @param titleColor The color for the title text.
* @return This Builder object to allow for chaining of calls to set methods
*/
public DialogBuilder setTitleColor(int titleColor) {
mTitleColor = titleColor;
return this;
}
/**
* @param dividerColor The color for the title divider.
* @return This Builder object to allow for chaining of calls to set methods
*/
public DialogBuilder setDividerColor(int dividerColor) {
mDividerColor = dividerColor;
return this;
}
/**
* @param progressBarColor The color for the progressbar.
* @return This Builder object to allow for chaining of calls to set methods
*/
public DialogBuilder setProgressBarColor(int progressBarColor) {
mProgressBarColor = progressBarColor;
return this;
}
}
@@ -53,13 +53,13 @@ public class MarkImageDescriptor {
isSameType = type == typeToCheck;
}
if(colorToCheck != null && color != null) {
isSameColor = color.equalsIgnoreCase(colorToCheck) ? true : false;
isSameColor = color.equalsIgnoreCase(colorToCheck);
}
if(shapeToCheck != null && shape != null) {
isSameShape = shape.equalsIgnoreCase(shapeToCheck) ? true : false;
isSameShape = shape.equalsIgnoreCase(shapeToCheck);
}
if(patternToCheck != null && pattern != null) {
isSamePattern = pattern.equalsIgnoreCase(patternToCheck) ? true : false;
isSamePattern = pattern.equalsIgnoreCase(patternToCheck);
}
if(isSameType && isSameColor) {
@@ -74,5 +74,4 @@ public class MarkImageDescriptor {
return result;
}
}
@@ -1,36 +1,38 @@
package com.sap.sailing.racecommittee.app.ui.utils;
import java.util.List;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.common.MarkType;
import java.util.List;
public abstract class MarkImageHelper {
List<MarkImageDescriptor> markImageDescriptors;
protected MarkImageDescriptor defaultCourseMarkDescriptor;
List<MarkImageDescriptor> markImageDescriptors;
public int resolveMarkImage(Mark mark) {
MarkImageDescriptor result = defaultCourseMarkDescriptor;
int highestCompatibilityLevel = -1;
for (MarkImageDescriptor imageDescriptor: markImageDescriptors) {
int compatibilityLevel = imageDescriptor.getCompatibilityLevel(mark.getType(), mark.getColor(), mark.getShape(), mark.getPattern());
if(compatibilityLevel > highestCompatibilityLevel) {
result = imageDescriptor;
highestCompatibilityLevel = compatibilityLevel;
if(highestCompatibilityLevel == 3) {
break;
}
for (MarkImageDescriptor imageDescriptor : markImageDescriptors) {
int compatibilityLevel = imageDescriptor
.getCompatibilityLevel(mark.getType(), mark.getColor(), mark.getShape(), mark.getPattern());
if (compatibilityLevel > highestCompatibilityLevel) {
result = imageDescriptor;
highestCompatibilityLevel = compatibilityLevel;
if (highestCompatibilityLevel == 3) {
break;
}
}
}
return result.getDrawableId();
}
protected MarkImageDescriptor createMarkImageDescriptor(int drawableId, MarkType type, String color, String shape, String pattern) {
protected MarkImageDescriptor createMarkImageDescriptor(int drawableId, MarkType type, String color, String shape,
String pattern) {
MarkImageDescriptor markIconDescriptor = new MarkImageDescriptor(drawableId, type, color, shape, pattern);
markImageDescriptors.add(markIconDescriptor);
return markIconDescriptor;
}