diff --git a/src/main/res/drawable-hdpi/md__category_background.9.png b/src/main/res/drawable-hdpi/md__category_background.9.png
new file mode 100644
index 00000000..43a20adc
Binary files /dev/null and b/src/main/res/drawable-hdpi/md__category_background.9.png differ
diff --git a/src/main/res/drawable-hdpi/md__list_focused_holo.9.png b/src/main/res/drawable-hdpi/md__list_focused_holo.9.png
new file mode 100644
index 00000000..55527084
Binary files /dev/null and b/src/main/res/drawable-hdpi/md__list_focused_holo.9.png differ
diff --git a/src/main/res/drawable-hdpi/md__list_longpressed_holo.9.png b/src/main/res/drawable-hdpi/md__list_longpressed_holo.9.png
new file mode 100644
index 00000000..4ea7afa0
Binary files /dev/null and b/src/main/res/drawable-hdpi/md__list_longpressed_holo.9.png differ
diff --git a/src/main/res/drawable-hdpi/md__list_pressed_holo_dark.9.png b/src/main/res/drawable-hdpi/md__list_pressed_holo_dark.9.png
new file mode 100644
index 00000000..5654cd69
Binary files /dev/null and b/src/main/res/drawable-hdpi/md__list_pressed_holo_dark.9.png differ
diff --git a/src/main/res/drawable-hdpi/md__list_selector_disabled_holo_dark.9.png b/src/main/res/drawable-hdpi/md__list_selector_disabled_holo_dark.9.png
new file mode 100644
index 00000000..f6fd30dc
Binary files /dev/null and b/src/main/res/drawable-hdpi/md__list_selector_disabled_holo_dark.9.png differ
diff --git a/src/main/res/drawable-mdpi/md__category_background.9.png b/src/main/res/drawable-mdpi/md__category_background.9.png
new file mode 100644
index 00000000..af0bc168
Binary files /dev/null and b/src/main/res/drawable-mdpi/md__category_background.9.png differ
diff --git a/src/main/res/drawable-mdpi/md__list_focused_holo.9.png b/src/main/res/drawable-mdpi/md__list_focused_holo.9.png
new file mode 100644
index 00000000..00f05d8c
Binary files /dev/null and b/src/main/res/drawable-mdpi/md__list_focused_holo.9.png differ
diff --git a/src/main/res/drawable-mdpi/md__list_longpressed_holo.9.png b/src/main/res/drawable-mdpi/md__list_longpressed_holo.9.png
new file mode 100644
index 00000000..3bf8e036
Binary files /dev/null and b/src/main/res/drawable-mdpi/md__list_longpressed_holo.9.png differ
diff --git a/src/main/res/drawable-mdpi/md__list_pressed_holo_dark.9.png b/src/main/res/drawable-mdpi/md__list_pressed_holo_dark.9.png
new file mode 100644
index 00000000..6e77525d
Binary files /dev/null and b/src/main/res/drawable-mdpi/md__list_pressed_holo_dark.9.png differ
diff --git a/src/main/res/drawable-mdpi/md__list_selector_disabled_holo_dark.9.png b/src/main/res/drawable-mdpi/md__list_selector_disabled_holo_dark.9.png
new file mode 100644
index 00000000..92da2f0d
Binary files /dev/null and b/src/main/res/drawable-mdpi/md__list_selector_disabled_holo_dark.9.png differ
diff --git a/src/main/res/drawable-xhdpi/md__category_background.9.png b/src/main/res/drawable-xhdpi/md__category_background.9.png
new file mode 100644
index 00000000..942d72e6
Binary files /dev/null and b/src/main/res/drawable-xhdpi/md__category_background.9.png differ
diff --git a/src/main/res/drawable-xhdpi/md__list_focused_holo.9.png b/src/main/res/drawable-xhdpi/md__list_focused_holo.9.png
new file mode 100644
index 00000000..b545f8e5
Binary files /dev/null and b/src/main/res/drawable-xhdpi/md__list_focused_holo.9.png differ
diff --git a/src/main/res/drawable-xhdpi/md__list_longpressed_holo.9.png b/src/main/res/drawable-xhdpi/md__list_longpressed_holo.9.png
new file mode 100644
index 00000000..eda10e61
Binary files /dev/null and b/src/main/res/drawable-xhdpi/md__list_longpressed_holo.9.png differ
diff --git a/src/main/res/drawable-xhdpi/md__list_pressed_holo_dark.9.png b/src/main/res/drawable-xhdpi/md__list_pressed_holo_dark.9.png
new file mode 100644
index 00000000..e4b33935
Binary files /dev/null and b/src/main/res/drawable-xhdpi/md__list_pressed_holo_dark.9.png differ
diff --git a/src/main/res/drawable-xhdpi/md__list_selector_disabled_holo_dark.9.png b/src/main/res/drawable-xhdpi/md__list_selector_disabled_holo_dark.9.png
new file mode 100644
index 00000000..88726b69
Binary files /dev/null and b/src/main/res/drawable-xhdpi/md__list_selector_disabled_holo_dark.9.png differ
diff --git a/src/main/res/drawable/md__list_selector_background_transition_holo_dark.xml b/src/main/res/drawable/md__list_selector_background_transition_holo_dark.xml
new file mode 100644
index 00000000..1d43396d
--- /dev/null
+++ b/src/main/res/drawable/md__list_selector_background_transition_holo_dark.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/src/main/res/drawable/md__list_selector_holo_dark.xml b/src/main/res/drawable/md__list_selector_holo_dark.xml
new file mode 100644
index 00000000..bd71aa8b
--- /dev/null
+++ b/src/main/res/drawable/md__list_selector_holo_dark.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/layout/menu_row_category.xml b/src/main/res/layout/menu_row_category.xml
new file mode 100644
index 00000000..c89e5d96
--- /dev/null
+++ b/src/main/res/layout/menu_row_category.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/src/main/res/layout/menu_row_item.xml b/src/main/res/layout/menu_row_item.xml
new file mode 100644
index 00000000..af2c4b38
--- /dev/null
+++ b/src/main/res/layout/menu_row_item.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/src/main/res/values/colors.xml b/src/main/res/values/colors.xml
index bc48ae9a..c9f62e57 100644
--- a/src/main/res/values/colors.xml
+++ b/src/main/res/values/colors.xml
@@ -22,5 +22,7 @@
#646464
#c8c8c8
#323232
+ #00000000
+ #FF555555
\ No newline at end of file
diff --git a/src/main/res/values/ids.xml b/src/main/res/values/ids.xml
new file mode 100644
index 00000000..925ac058
--- /dev/null
+++ b/src/main/res/values/ids.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/values/styles.xml b/src/main/res/values/styles.xml
index 93e381d0..a2272424 100644
--- a/src/main/res/values/styles.xml
+++ b/src/main/res/values/styles.xml
@@ -29,5 +29,36 @@
- @style/Widget.Holo.Light.CompoundButton.Switch
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala
index 8760a48c..47d83b39 100644
--- a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala
+++ b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala
@@ -46,7 +46,7 @@ import android.os._
import android.preference.{Preference, PreferenceManager}
import android.util.Log
import android.view.{ViewGroup, Gravity, ViewParent, KeyEvent}
-import android.widget.{LinearLayout, CompoundButton, RelativeLayout, TextView}
+import android.widget._
import com.actionbarsherlock.view.Menu
import com.actionbarsherlock.view.MenuItem
import com.google.analytics.tracking.android.EasyTracker
@@ -68,7 +68,11 @@ import scala.concurrent.ops._
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import com.google.ads.{AdRequest, AdSize, AdView}
import net.simonvt.menudrawer.MenuDrawer
-import javax.swing.text.html.ListView
+
+import com.github.shadowsocks.database.{MenuAdapter, Item, Category}
+import scala.collection.mutable.ListBuffer
+import com.github.shadowsocks.database.Category
+import com.github.shadowsocks.database.Item
object Shadowsocks {
@@ -222,6 +226,8 @@ class Shadowsocks
lazy val status = getSharedPreferences(Key.status, Context.MODE_PRIVATE)
lazy val receiver = new StateBroadcastReceiver
lazy val drawer = MenuDrawer.attach(this)
+ lazy val listView = new ListView(this)
+ lazy val menuAdapter = new MenuAdapter(this, getMenuList)
private val handler: Handler = new Handler {
override def handleMessage(msg: Message) {
@@ -399,11 +405,8 @@ class Shadowsocks
setHeaderRes(R.xml.shadowsocks_headers)
super.onCreate(savedInstanceState)
- val menuView = new TextView(this)
- menuView.setTextColor(0xFFFFFFFF)
- menuView.setText("As the drawer opens, the drawer indicator icon becomes smaller.")
- menuView.setGravity(Gravity.CENTER)
- drawer.setMenuView(menuView)
+ listView.setAdapter(menuAdapter)
+ drawer.setMenuView(listView)
// The drawable that replaces the up indicator in the action bar
drawer.setSlideDrawable(R.drawable.ic_drawer)
@@ -440,26 +443,44 @@ class Shadowsocks
handler.sendEmptyMessage(MSG_INITIAL_FINISH)
}
}
+
}
-/* override def onCreateOptionsMenu(menu: Menu): Boolean = {
- val isRoot = status.getBoolean(Key.isRoot, false)
- menu
- .add(0, 0, 0, R.string.recovery)
- .setIcon(android.R.drawable.ic_menu_revert)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT)
- menu
- .add(0, 1, 1, R.string.about)
- .setIcon(android.R.drawable.ic_menu_info_details)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT)
- if (isRoot || Build.VERSION.SDK_INT < 17) {
- menu
- .add(0, 2, 2, R.string.flush_dnscache)
- .setIcon(android.R.drawable.ic_menu_revert)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT)
- }
- true
- }*/
+ def getProfileList: List[Item] = {
+ List[Item]()
+ }
+
+ def getMenuList: List[Any] = {
+
+ val buf = new ListBuffer[Any]()
+
+ buf += new Category("Profiles")
+
+ buf ++= getProfileList
+
+ buf += new Category("Settings")
+
+ buf += new Item(-1, getString(R.string.recovery), android.R.drawable.ic_menu_revert,
+ _ => {
+ EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "reset", getVersionName, 0L)
+ recovery()
+ })
+
+ buf += new Item(-2, getString(R.string.flush_dnscache), android.R.drawable.ic_menu_delete,
+ _ => {
+ EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "flush_dnscache", getVersionName, 0L)
+ flushDnsCache()
+ })
+
+ buf += new Item(-3, getString(R.string.about), android.R.drawable.ic_menu_info_details,
+ _ => {
+ EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "about", getVersionName, 0L)
+ showAbout()
+ })
+
+ buf.toList
+
+ }
override def onKeyDown(keyCode: Int, event: KeyEvent): Boolean = {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount == 0) {
@@ -481,18 +502,6 @@ class Shadowsocks
drawer.toggleMenu()
return true
}
- case 0 => {
- EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "reset", getVersionName, 0L)
- recovery()
- }
- case 1 => {
- EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "about", getVersionName, 0L)
- showAbout()
- }
- case 2 => {
- EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "flush_dnscache", getVersionName, 0L)
- flushDnsCache()
- }
}
super.onOptionsItemSelected(item)
}
diff --git a/src/main/scala/com/github/shadowsocks/database/MenuAdapter.scala b/src/main/scala/com/github/shadowsocks/database/MenuAdapter.scala
new file mode 100644
index 00000000..1554d6a9
--- /dev/null
+++ b/src/main/scala/com/github/shadowsocks/database/MenuAdapter.scala
@@ -0,0 +1,113 @@
+package com.github.shadowsocks.database
+
+import android.content.{DialogInterface, Context}
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.widget.TextView
+import com.github.shadowsocks.R
+import android.view.View.OnClickListener
+
+case class Item(id: Int, title: String, iconRes: Int, action: Int => Unit)
+
+case class Category (title: String)
+
+object MenuAdapter {
+
+ trait MenuListener {
+ def onActiveViewChanged(v: View)
+ }
+
+ val UNDEFINED = -1
+ val CATEGORY = 0
+ val ITEM = 1
+
+}
+
+class MenuAdapter (context: Context, var items: List[Any]) extends BaseAdapter {
+
+ def setListener(listener: MenuAdapter.MenuListener) {
+ mListener = listener
+ }
+
+ def setActivePosition(activePosition: Int) {
+ mActivePosition = activePosition
+ }
+
+ @Override def getCount: Int = {
+ items.size
+ }
+
+ @Override def getItem(position: Int): Object = {
+ items(position).asInstanceOf[Object]
+ }
+
+ @Override def getItemId(position: Int): Long = {
+ position
+ }
+
+ @Override override def getItemViewType(position: Int): Int = {
+ getItem(position) match {
+ case Category => MenuAdapter.CATEGORY
+ case Item => MenuAdapter.ITEM
+ case _ => MenuAdapter.UNDEFINED
+ }
+ }
+
+ @Override override def getViewTypeCount: Int = {
+ 3
+ }
+
+ @Override override def isEnabled(position: Int): Boolean = {
+ getItemViewType(position) != MenuAdapter.UNDEFINED
+ }
+
+ @Override override def areAllItemsEnabled: Boolean = {
+ false
+ }
+
+ @Override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
+ var v: View = convertView
+ val item = getItem(position)
+ item match {
+ case value: Category =>
+ if (v == null) {
+ v = LayoutInflater.from(context).inflate(R.layout.menu_row_category, parent, false)
+ }
+ v.asInstanceOf[TextView].setText(value.title)
+ case value: Item =>
+ if (v == null) {
+ v = LayoutInflater.from(context).inflate(R.layout.menu_row_item, parent, false)
+ }
+ val tv: TextView = v.asInstanceOf[TextView]
+ tv.setText(value.title)
+ tv.setCompoundDrawablesWithIntrinsicBounds(value.iconRes, 0, 0, 0)
+ tv.setOnClickListener(new OnClickListener {
+ def onClick(view: View) {
+ val item = view.getTag(R.id.mdItem).asInstanceOf[Item]
+ item.action(item.id)
+ }
+ })
+
+ v.setTag(R.id.mdItem, value)
+ case _ =>
+ }
+ v.setTag(R.id.mdActiveViewPosition, position)
+
+ if (position == mActivePosition) {
+ if (mListener != null) mListener.onActiveViewChanged(v)
+ }
+ v
+ }
+
+ def updateList(list: List[Any]) {
+ items = list
+ notifyDataSetChanged()
+ }
+
+ private var mListener: MenuAdapter.MenuListener = null
+ private var mActivePosition: Int = 0
+}
+
+