diff options
author | sjtufs <[email protected]> | 2013-08-31 10:16:54 +0800 |
---|---|---|
committer | sjtufs <[email protected]> | 2013-08-31 10:16:54 +0800 |
commit | 69a911d88c0e41f2aafbd6d88d53ea430890b3cd (patch) | |
tree | 338b2978d8d74ebb3eb47907fdd03c46cb385780 /client/Piztor | |
parent | da9358f654ffd5bc5598d61853982631c9bdbd99 (diff) |
add subscribe settings page
Diffstat (limited to 'client/Piztor')
-rw-r--r-- | client/Piztor/res/layout/activity_login.xml | 2 | ||||
-rw-r--r-- | client/Piztor/res/layout/activity_settings.xml | 20 | ||||
-rw-r--r-- | client/Piztor/res/layout/checkindialog.xml | 20 | ||||
-rw-r--r-- | client/Piztor/res/layout/custom_icon_view.xml | 21 | ||||
-rw-r--r-- | client/Piztor/res/layout/subscribe_item.xml | 36 | ||||
-rw-r--r-- | client/Piztor/res/layout/subscribe_settings.xml | 66 | ||||
-rw-r--r-- | client/Piztor/res/values/strings.xml | 2 | ||||
-rw-r--r-- | client/Piztor/src/com/macaroon/piztor/AlertMaker.java | 33 | ||||
-rw-r--r-- | client/Piztor/src/com/macaroon/piztor/Main.java | 80 | ||||
-rw-r--r-- | client/Piztor/src/com/macaroon/piztor/MapMaker.java | 24 | ||||
-rw-r--r-- | client/Piztor/src/com/macaroon/piztor/Rlocation.java | 13 | ||||
-rw-r--r-- | client/Piztor/src/com/macaroon/piztor/SubscribeSettings.java | 122 |
12 files changed, 362 insertions, 77 deletions
diff --git a/client/Piztor/res/layout/activity_login.xml b/client/Piztor/res/layout/activity_login.xml index 670a3dc..a8cf47f 100644 --- a/client/Piztor/res/layout/activity_login.xml +++ b/client/Piztor/res/layout/activity_login.xml @@ -50,7 +50,7 @@ <EditText android:textSize="16.0sp" android:textColor="@android:color/white" - android:textColorHint="#ff666666" + android:textColorHint="#ff666666" android:gravity="center_vertical" android:id="@+id/user_pass" android:background="#00ffffff" diff --git a/client/Piztor/res/layout/activity_settings.xml b/client/Piztor/res/layout/activity_settings.xml index 3bd6fef..49e8dfe 100644 --- a/client/Piztor/res/layout/activity_settings.xml +++ b/client/Piztor/res/layout/activity_settings.xml @@ -98,26 +98,6 @@ android:layout_marginLeft="20dip" android:layout_marginRight="20dip" android:orientation="horizontal"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="#4D4D4D" - android:textColor="#FFFFFF" - android:textSize="25dip" - android:text="company" - android:id="@+id/settings_subscribe_company" - /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="#4D4D4D" - android:textColor="#FFFFFF" - android:textSize="25dip" - android:layout_marginLeft="20dip" - android:text="section" - android:id="@+id/settings_subscribe_section" - /> - <Button android:id="@+id/settings_btn_subscribe" android:layout_width="wrap_content" diff --git a/client/Piztor/res/layout/checkindialog.xml b/client/Piztor/res/layout/checkindialog.xml new file mode 100644 index 0000000..4174deb --- /dev/null +++ b/client/Piztor/res/layout/checkindialog.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" + android:text="Checking in..."/> + + <ProgressBar + android:id="@+id/checkin_progress" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" /> + +</LinearLayout> diff --git a/client/Piztor/res/layout/custom_icon_view.xml b/client/Piztor/res/layout/custom_icon_view.xml new file mode 100644 index 0000000..857288a --- /dev/null +++ b/client/Piztor/res/layout/custom_icon_view.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:background="#ffffff" > + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/circle_red" + /> + <TextView + android:text=" 11" + android:textColor="#000000" + android:textSize="7dip"/> + </FrameLayout> +</LinearLayout> diff --git a/client/Piztor/res/layout/subscribe_item.xml b/client/Piztor/res/layout/subscribe_item.xml new file mode 100644 index 0000000..902da5a --- /dev/null +++ b/client/Piztor/res/layout/subscribe_item.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="horizontal"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/textView1" + android:textSize="20dip" + android:layout_marginLeft="10dip" + android:layout_alignParentLeft="true" + android:text="company section"/> + <Button + android:text="remove" + android:layout_width="100dip" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_marginRight="10dip" + android:textColor="#FFFFFF" + android:background="#DB4437" + android:id="@+id/button_delete" + android:textSize="20dip" + /> + <View + android:layout_width="fill_parent" + android:layout_height="1.0px" + android:layout_below="@+id/button_delete" + android:layout_marginTop="20dip" + android:layout_marginBottom="20dip" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:background="#ffc0c3c4" /> + +</RelativeLayout> diff --git a/client/Piztor/res/layout/subscribe_settings.xml b/client/Piztor/res/layout/subscribe_settings.xml new file mode 100644 index 0000000..c27e3c8 --- /dev/null +++ b/client/Piztor/res/layout/subscribe_settings.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > + <RelativeLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" + android:orientation="horizontal"> + <EditText + android:layout_width="120dip" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_marginLeft="10dip" + android:textSize="20dip" + android:hint="company" + android:phoneNumber="true" + android:id="@+id/subscribe_company"/> + <EditText + android:layout_width="120dip" + android:layout_height="wrap_content" + android:layout_marginLeft="10dip" + android:layout_toRightOf="@+id/subscribe_company" + android:textSize="20dip" + android:hint="section" + android:phoneNumber="true" + android:id="@+id/subscribe_section"/> + <Button + android:layout_width="100dip" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_marginRight="10dip" + android:text="add" + android:textColor="#FFFFFF" + android:background="#0F9D58" + android:textSize="20dip" + android:padding="10dip" + android:id="@+id/button_add"/> + </RelativeLayout> + + <LinearLayout + android:id="@+id/linearLayout1" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + > + <ListView + android:id="@+id/listView1" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layout_weight="0.69" + android:focusable="true"> + </ListView> + </LinearLayout> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/textView1" + android:text="TextView" + android:layout_alignParentBottom="true" + android:layout_centerHorizontal="true" + android:layout_marginBottom="10dp"/> +</LinearLayout> diff --git a/client/Piztor/res/values/strings.xml b/client/Piztor/res/values/strings.xml index 6ff1392..a0843df 100644 --- a/client/Piztor/res/values/strings.xml +++ b/client/Piztor/res/values/strings.xml @@ -24,6 +24,6 @@ <string name="logout">Logout</string> <string name="update_info">My Account</string> <string name="subscribe_info">Subscribe information</string> - <string name="change">更改</string> + <string name="change">Check & Update</string> </resources> diff --git a/client/Piztor/src/com/macaroon/piztor/AlertMaker.java b/client/Piztor/src/com/macaroon/piztor/AlertMaker.java index cc70e62..d7a9d69 100644 --- a/client/Piztor/src/com/macaroon/piztor/AlertMaker.java +++ b/client/Piztor/src/com/macaroon/piztor/AlertMaker.java @@ -3,6 +3,7 @@ package com.macaroon.piztor; import java.util.Calendar; import java.util.Timer; import java.util.TimerTask; +import java.util.zip.Inflater; import android.annotation.SuppressLint; import android.app.AlertDialog; @@ -17,6 +18,7 @@ import android.os.Message; import android.provider.Settings; import android.util.Log; import android.view.KeyEvent; +import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.inputmethod.InputMethodManager; @@ -43,7 +45,8 @@ public class AlertMaker { private Context context; private GeoPoint markerPoint; private MapMaker mapMaker; - + private long timestamp; + public AlertMaker(Context cc, MapMaker mm) { context =cc; mapMaker = mm; @@ -79,6 +82,23 @@ public class AlertMaker { gpsDialog.show(); } + public long toTimestamp(int hour, int minute) { + calendar = Calendar.getInstance(); + int nhour = calendar.get(Calendar.HOUR_OF_DAY); + int nminute = calendar.get(Calendar.MINUTE); + int tmp = 0; + if (hour > nhour) tmp = (hour - nhour) * 60 + minute - nminute; + else if (minute > nminute) tmp = minute - nminute; + timestamp = System.currentTimeMillis() + tmp * 60 * 1000; + return timestamp; + } + + //TODO + public void updateMarkerTime(int hour, int minute) { + Log.d("time", hour + " " + minute); + Log.d("time", " " + toTimestamp(hour, minute)); + } + public void showMarkerAlert(GeoPoint point) { closeBoard(context); @@ -92,8 +112,10 @@ public class AlertMaker { public void onTimeSet(TimePicker view, int hourOfDay, int minute) { ////// at least 2 minutes if ((hourOfDay >= calendar.get(Calendar.HOUR_OF_DAY) && minute >= calendar.get(Calendar.MINUTE)) - || hourOfDay > calendar.get(Calendar.HOUR_OF_DAY)) + || hourOfDay > calendar.get(Calendar.HOUR_OF_DAY)) { mapMaker.DrawMarker(markerPoint); + updateMarkerTime(hourOfDay, minute); + } else { Toast toast = Toast.makeText(context, "Too early! Give me at least 2 minutes!", Toast.LENGTH_LONG); @@ -104,8 +126,13 @@ public class AlertMaker { } } , calendar.get(Calendar.HOUR_OF_DAY) - , calendar.get(Calendar.MINUTE), false); + , calendar.get(Calendar.MINUTE), true); markerDialog.show(); } + public void showCheckinAlter() { + closeBoard(context); + AlertDialog.Builder checkinDialog = new AlertDialog.Builder(context); + } + } diff --git a/client/Piztor/src/com/macaroon/piztor/Main.java b/client/Piztor/src/com/macaroon/piztor/Main.java index 623595b..735b1a4 100644 --- a/client/Piztor/src/com/macaroon/piztor/Main.java +++ b/client/Piztor/src/com/macaroon/piztor/Main.java @@ -10,6 +10,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; +import android.view.Gravity; import android.view.KeyEvent; import android.view.Menu; import android.view.View; @@ -31,7 +32,7 @@ import com.baidu.mapapi.utils.DistanceUtil; import com.baidu.platform.comapi.basestruct.GeoPoint; public class Main extends PiztorAct { - final static int SearchButtonPress = 1; + final static int CheckinButtonPress = 1; final static int FocuseButtonPress = 3; final static int SuccessFetch = 4; final static int FailedFetch = 5; @@ -43,6 +44,7 @@ public class Main extends PiztorAct { private Calendar calendar; GeoPoint markerPoint = null; private MKMapTouchListener mapTouchListener; + private final int checkinRadius = 10; /** * Locating component @@ -55,7 +57,7 @@ public class Main extends PiztorAct { boolean isFirstLocation = true; public static int GPSrefreshrate = 5; - ImageButton btnSearch, btnFetch, btnFocus, btnSettings; + ImageButton btnCheckin, btnFetch, btnFocus, btnSettings; MapInfo mapInfo; Transam transam; @@ -130,8 +132,8 @@ public class Main extends PiztorAct { String cause(int t) { switch (t) { - case SearchButtonPress: - return "Search Button Press"; + case CheckinButtonPress: + return "Checkin Button Press"; case FocuseButtonPress: return "Focuse Button Press"; case SuccessFetch: @@ -192,9 +194,21 @@ public class Main extends PiztorAct { isFirstLocation = false; } int TMP = location.getLocType(); - if (TMP == 61) Toast.makeText(Main.this, "Piztor : Update from GPS result (" + GPSrefreshrate + "s)", 3000).show(); - if (TMP == 161) Toast.makeText(Main.this, "Piztor : Update from Network (" + GPSrefreshrate + "s)" , 3000).show(); - if (TMP == 65) Toast.makeText(Main.this, "Piztor : Update from Cache (" + GPSrefreshrate + "s)", 3000).show(); + if (TMP == 61) { + Toast toast = Toast.makeText(Main.this, "Piztor : Update from GPS result (" + GPSrefreshrate + "s)", 2000); + toast.setGravity(Gravity.TOP, 0, 80); + toast.show(); + } + if (TMP == 161) { + Toast toast = Toast.makeText(Main.this, "Piztor : Update from Network (" + GPSrefreshrate + "s)", 2000); + toast.setGravity(Gravity.TOP, 0, 80); + toast.show(); + } + if (TMP == 65) { + Toast toast = Toast.makeText(Main.this, "Piztor : Update from Cache (" + GPSrefreshrate + "s)", 2000); + toast.setGravity(Gravity.TOP, 0, 80); + toast.show(); + } mapMaker.UpdateLocationOverlay(locData, hasAnimation); LocationClientOption option = new LocationClientOption(); @@ -218,8 +232,7 @@ public class Main extends PiztorAct { void enter(int e) { System.out.println("enter start status!!!!"); if (e == ActMgr.Create) { - System.out.println(Infomation.token + " " - + Infomation.username + " " + Infomation.myInfo.uid); + System.out.println(Infomation.token + " " + Infomation.username + " " + Infomation.myInfo.uid); } if (e == SuccessFetch) flushMap(); @@ -270,6 +283,27 @@ public class Main extends PiztorAct { mMapView.regMapTouchListner(mapTouchListener); } + public void markerCheckin() { + if (mapMaker.getMakerLocation() == null) { + Toast toast = Toast.makeText(Main.this, "No marker now!", 2000); + toast.setGravity(Gravity.TOP, 0, 80); + toast.show(); + return; + } + GeoPoint curPoint = new GeoPoint((int)(locData.latitude * 1E6), (int)(locData.longitude * 1E6)); + double disFromMarker = DistanceUtil.getDistance(curPoint, mapMaker.getMakerLocation()); + if (disFromMarker < locData.accuracy) { + mapMaker.removeMarker(); + Toast toast = Toast.makeText(Main.this, "Marker checked!", 2000); + toast.setGravity(Gravity.TOP, 0, 80); + toast.show(); + } else { + Toast toast = Toast.makeText(Main.this, "Please get closer to the marker!", 2000); + toast.setGravity(Gravity.TOP, 0, 80); + toast.show(); + } + } + @Override protected void onCreate(Bundle savedInstanceState) { id = "Main"; @@ -283,23 +317,10 @@ public class Main extends PiztorAct { mapInfo = AppMgr.mapInfo; ActStatus[] r = new ActStatus[1]; ActStatus startStatus = r[0] = new StartStatus(); - // ActStatus fetchStatus = r[1] = new FetchStatus(); - // ActStatus focusStatus = r[2] = new FocusStatus(); if (transam == null) Log.d(LogInfo.exception, "transam = null"); transam.setHandler(handler); actMgr = new ActMgr(this, startStatus, r); - // actMgr.add(startStatus, FocuseButtonPress, focusStatus); - // actMgr.add(startStatus, Fetch, fetchStatus); - // actMgr.add(startStatus, SuccessFetch, startStatus); - // actMgr.add(startStatus, Fetch, startStatus); - // actMgr.add(fetchStatus, Fetch, startStatus); - // actMgr.add(fetchStatus, FailedFetch, startStatus); - // actMgr.add(fetchStatus, SuccessFetch, startStatus); - // actMgr.add(focusStatus, FocuseButtonPress, startStatus); - // actMgr.add(focusStatus, mapViewtouched, startStatus); - // actMgr.add(focusStatus, SuccessFetch, focusStatus); - // actMgr.add(focusStatus, Fetch, focusStatus); setContentView(R.layout.activity_main); mMapView = (MapView) findViewById(R.id.bmapView); @@ -330,17 +351,22 @@ public class Main extends PiztorAct { InputMethodManager.HIDE_NOT_ALWAYS); } - /* - * public boolean onTap(int index) { OverlayItem item = getItem(index); - * mCurItem = item; if () } - */ @Override protected void onStart() { super.onStart(); btnFetch = (ImageButton) findViewById(R.id.footbar_btn_fetch); btnFocus = (ImageButton) findViewById(R.id.footbar_btn_focus); - btnSearch = (ImageButton) findViewById(R.id.footbar_btn_search); + btnCheckin = (ImageButton) findViewById(R.id.footbar_btn_checkin); btnSettings = (ImageButton) findViewById(R.id.footbar_btn_settings); + + btnCheckin.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View arg0) { + markerCheckin(); + } + }); + btnFetch.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { diff --git a/client/Piztor/src/com/macaroon/piztor/MapMaker.java b/client/Piztor/src/com/macaroon/piztor/MapMaker.java index ef79f73..8df1f8a 100644 --- a/client/Piztor/src/com/macaroon/piztor/MapMaker.java +++ b/client/Piztor/src/com/macaroon/piztor/MapMaker.java @@ -370,18 +370,6 @@ public class MapMaker extends Activity { } /** - * Update marker - * - public void UpdateMarker() { - mOverlay.addItem(nowMarker); - if (mMapView != null) { - mMapView.getOverlays().add(mOverlay); - mMapView.refresh(); - } - } - */ - - /** * Draw a marker */ public void DrawMarker(GeoPoint markerPoint) { @@ -401,6 +389,18 @@ public class MapMaker extends Activity { mMapController.animateTo(markerPoint); } + public GeoPoint getMakerLocation() { + if (nowMarker == null) return null; + else return nowMarker.getPoint(); + } + + public void removeMarker() { + if (nowMarker == null) return; + mOverlay.removeItem(nowMarker); + nowMarker = null; + mMapView.refresh(); + } + /** * Remove all other users */ diff --git a/client/Piztor/src/com/macaroon/piztor/Rlocation.java b/client/Piztor/src/com/macaroon/piztor/Rlocation.java deleted file mode 100644 index c2d429c..0000000 --- a/client/Piztor/src/com/macaroon/piztor/Rlocation.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.macaroon.piztor;
-
-class Rlocation{
- int id; //id
- double latitude; //latitude
- double longitude; //longitude
-
- Rlocation(int i,double lat,double lot){
- id = i;
- latitude = lat;
- longitude = lot;
- }
-}
\ No newline at end of file diff --git a/client/Piztor/src/com/macaroon/piztor/SubscribeSettings.java b/client/Piztor/src/com/macaroon/piztor/SubscribeSettings.java new file mode 100644 index 0000000..3716549 --- /dev/null +++ b/client/Piztor/src/com/macaroon/piztor/SubscribeSettings.java @@ -0,0 +1,122 @@ +package com.macaroon.piztor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.TextView; + +import com.macaroon.piztor.RGroup; + +public class SubscribeSettings extends Activity { + + private static final int BUTTON_ADD = 1; + private static final int BUTTON_DELETE = 2; + + private ListView mListView; + private ArrayList<HashMap<String, Object>> mList; + private TextView mShowInfo; + private EditText edit_company; + private EditText edit_section; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.subscribe_settings); + + mListView = (ListView) findViewById(R.id.listView1); + edit_company = (EditText) findViewById(R.id.subscribe_company); + edit_section = (EditText) findViewById(R.id.subscribe_section); + mList = new ArrayList<HashMap<String, Object>>(); + final MySimpleAdapter simpleAdapter = new MySimpleAdapter(this, mList, + R.layout.subscribe_item, new String[] {"subscribe_text", "btnadd"}, new int[] {R.id.textView1, R.id.button_add}); + mListView.setAdapter(simpleAdapter); + //TODO get current subscribe + for (RGroup i : Infomation.sublist) { + HashMap<String, Object> map = new HashMap<String, Object>(); + int cc = i.company; + int ss = i.section; + map.put("subscribe_text", cc+ "连 " + ss + "班"); + } + Button btnadd = (Button)findViewById(R.id.button_add); + btnadd.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + int cc = Integer.parseInt(edit_company.getText().toString()); + int ss = Integer.parseInt(edit_section.getText().toString()); + simpleAdapter.notifyDataSetChanged(); + HashMap<String, Object> map = new HashMap<String, Object>(); + map.put("subscribe_text", cc + "连 " + ss + "班"); + mList.add(map); + mShowInfo.setText("添加了一条订阅"); + } + }); + mShowInfo = (TextView) findViewById(R.id.textView1); + } + + private class MySimpleAdapter extends SimpleAdapter { + + public MySimpleAdapter(Context context, + List<? extends Map<String, ?>> data, int resource, + String[] from, int[] to) { + super(context, data, resource, from, to); + // TODO Auto-generated constructor stub + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + // TODO Auto-generated method stub + final int mPosition = position; + convertView = super.getView(position, convertView, parent); + Button buttonDelete = (Button) convertView + .findViewById(R.id.button_delete); + buttonDelete.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + mHandler.obtainMessage(BUTTON_DELETE, mPosition, 0).sendToTarget(); + } + }); + return convertView; + } + + private Handler mHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + // TODO Auto-generated method stub + super.handleMessage(msg); + switch (msg.what) { + case BUTTON_ADD: + HashMap<String, Object> map = new HashMap<String, Object>(); + mList.add(map); + notifyDataSetChanged(); + break; + + case BUTTON_DELETE: + mList.remove(msg.arg1); + notifyDataSetChanged(); + mShowInfo.setText("删除了第" + (msg.arg1 + 1) + "条订阅"); + break; + } + } + + }; + + } +}
\ No newline at end of file |