diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java index c70f172..91a6ff4 100644 --- a/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java +++ b/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java @@ -31,6 +31,12 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic private ProgressBar progressBar; private List<String> databases; + @Override + public void onResume() { + super.onResume(); + Static.asyncDatabaseConnector.setDatabaseInUse(null); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ //Inflate the layout for this fragment diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java b/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java index c88c75f..3eeb667 100644 --- a/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java +++ b/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java @@ -48,7 +48,7 @@ public class ListActivity extends Activity { Static.startSettings(this); return true; } else if (id == R.id.action_sql){ - Static.startSQL(this); + Static.startSQL(this, getIntent().getExtras().getString(Static.DATABASE_NAME_ARG)); } return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java new file mode 100644 index 0000000..4c1af95 --- /dev/null +++ b/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java @@ -0,0 +1,245 @@ +package info.nerull7.mysqlbrowser; + +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.HorizontalScrollView; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.ScrollView; +import android.widget.TableLayout; +import android.widget.TableRow; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector; + +/** + * Created by nerull7 on 15.07.14. + * + * Fragment for showing elements + */ +public class SQLEntriesFragment extends Fragment implements AsyncDatabaseConnector.MatrixReturnListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.OnPostExecuteListener, AsyncDatabaseConnector.StringReturnListener { + private static final int HEADER_PADDING_TOP = 15; + private static final int HEADER_PADDING_BOTTOM = 15; + private static final int HEADER_PADDING_LEFT = 15; + private static final int HEADER_PADDING_RIGHT = 15; + private static final int ENTRIES_PADDING_TOP = 30; + private static final int ENTRIES_PADDING_BOTTOM = 30; + private static final int ENTRIES_PADDING_LEFT = 15; + private static final int ENTRIES_PADDING_RIGHT = 15; + + private TableLayout entriesTable; + private ScrollView entriesScrollView; + private FrameLayout headerFrame; + private HorizontalScrollView horizontalScrollView; + private TableRow.LayoutParams layoutParams; + + private ProgressBar progressBar; + private CustomScrollView fakeScrollView; + private View dummyView; + private boolean showError; + + private Menu menu; + private TableRow headerRow; + private int[] maxWidth; + + private boolean isFirstCreate; + private String errorMessage; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_entries, container, false); + initViewItems(rootView); + showError = false; + return rootView; + } + + private void initViewItems(View rootView){ + headerFrame = (FrameLayout) rootView.findViewById(R.id.headerFrame); + entriesScrollView = (ScrollView) rootView.findViewById(R.id.entriesScrollView); + fakeScrollView = (CustomScrollView) rootView.findViewById(R.id.fakeScroll); + progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar); + dummyView = rootView.findViewById(R.id.dummyView); + horizontalScrollView = (HorizontalScrollView) rootView.findViewById(R.id.horizontalScrollView); + entriesTable = new TableLayout(getActivity()); + + fakeScrollView.setOnTouchEventListener(new CustomScrollView.OnTouchEventListener() { + @Override + public boolean onTouchEvent(MotionEvent ev) { + ev.offsetLocation(0, headerFrame.getHeight()); + horizontalScrollView.dispatchTouchEvent(ev); + return true; + } + }); + + layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.MATCH_PARENT); + } + + private void setLoading(boolean isLoading){ + if(menu != null) { + menu.findItem(R.id.action_next).setEnabled(!isLoading); + menu.findItem(R.id.action_previous).setEnabled(!isLoading); + } + progressBar.setVisibility(isLoading ? View.VISIBLE : View.INVISIBLE); + } + + @Override + public void onMatrixReturn(List<List<String>> rows) { + // Now we get Rows + if(rows!=null) { + int background; + for (int i = 0; i < rows.size(); i++) { + List<String> elements = rows.get(i); + TableRow newRow = new TableRow(getActivity()); + + if( i%2 == 0 ){ // Two backgrounds for lines for better visibility + background=R.drawable.entries_element_1; + } else { + background=R.drawable.entries_element_2; + } + + for (int j = 0; j < elements.size(); j++) { // elements.size can be the same as in header so maybe some one number or not + TextView textView = new TextView(getActivity()); + textView.setText(elements.get(j)); + textView.setLayoutParams(layoutParams); + textView.setPadding(ENTRIES_PADDING_LEFT, ENTRIES_PADDING_TOP, ENTRIES_PADDING_RIGHT, ENTRIES_PADDING_BOTTOM); + textView.setBackgroundResource(background); + textView.setId(j); + newRow.addView(textView); + } + newRow.setClickable(false); + entriesTable.addView(newRow); + syncWidthsFirstStage(); + } + } else { + entriesTable = null; + } + + } + + @Override + public void onListReturn(List<String> fieldList) { + // First we need header + headerRow = new TableRow(getActivity()); + headerRow.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)); + for (String aFieldList : fieldList) { + TextView textView = new TextView(getActivity()); + textView.setText(aFieldList); + textView.setTypeface(null, Typeface.BOLD); + textView.setLayoutParams(layoutParams); + textView.setBackgroundResource(R.drawable.background_header); + textView.setPadding(HEADER_PADDING_LEFT, HEADER_PADDING_TOP, HEADER_PADDING_RIGHT, HEADER_PADDING_BOTTOM); + headerRow.addView(textView); + } + } + + private void syncWidthsFirstStage() { // TODO: Merge with adding columns maybe? Loops -= 3 should be quicker + maxWidth = new int[headerRow.getChildCount()]; + for (int i = 0; i < headerRow.getChildCount(); i++) { + TextView textView = (TextView) headerRow.getChildAt(i); + textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + maxWidth[i] = textView.getMeasuredWidth(); + } + + for (int i = 0; i < entriesTable.getChildCount(); i++) { + TableRow tableRow = (TableRow) entriesTable.getChildAt(i); + for (int j = 0; j < tableRow.getChildCount(); j++) { + TextView textView = (TextView) tableRow.getChildAt(j); + textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + int width = textView.getMeasuredWidth(); + if (width > maxWidth[j]) + maxWidth[j] = width; + } + } + } + + private void syncWidthsSecondStage() { + for(int i=0;i<headerRow.getChildCount();i++){ + TableRow entriesRow = (TableRow) entriesTable.getChildAt(0); + + TextView tmpEntries = (TextView) entriesRow.getChildAt(i); + TextView tmpHeader = (TextView) headerRow.getChildAt(i); + + tmpEntries.setWidth(maxWidth[i]); + tmpHeader.setWidth(maxWidth[i]); + } + } + + private void fakeScroll(){ + entriesScrollView.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED); + int height = entriesScrollView.getMeasuredHeight(); + dummyView.setMinimumHeight(height); + + RelativeLayout.LayoutParams fakeScrollLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + headerFrame.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + fakeScrollLayout.setMargins(0,headerFrame.getMeasuredHeight(),0,0); + + fakeScrollView.setLayoutParams(fakeScrollLayout); + } + +// @Override +// public void onResume() { +// super.onResume(); +// if(!isFirstCreate) { +// getActivity().finish(); +// } else { +// isFirstCreate = false; +// } +// } + + @Override + public void onPostExecute() { + if(!showError) { + if (headerFrame.getChildCount() == 0) // You can have only one child + headerFrame.addView(headerRow); + if (entriesTable != null) { + syncWidthsSecondStage(); + entriesScrollView.addView(entriesTable); + fakeScroll(); + } else { + TextView errorMessage = new TextView(getActivity()); + errorMessage.setText(R.string.error_no_entries); + errorMessage.setTypeface(null, Typeface.ITALIC); + errorMessage.setClickable(false); + entriesScrollView.addView(errorMessage); + } + setLoading(false); + } else { + setLoading(false); + final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(errorMessage); + builder.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + getActivity().finish(); + } + }); + builder.setTitle(R.string.info); + builder.setIcon(R.drawable.ic_action_info); + builder.create(); + builder.show(); + } + } + + @Override + public void onStringReturn(String data) { + errorMessage = data; + showError = true; + } +} diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java index 0ba7079..c67bc2e 100644 --- a/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java +++ b/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java @@ -2,6 +2,7 @@ package info.nerull7.mysqlbrowser; import android.app.Activity; import android.app.Fragment; +import android.app.FragmentTransaction; import android.content.Context; import android.os.Bundle; import android.util.Log; @@ -14,12 +15,16 @@ import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector; + /** * Created by nerull7 on 30.09.14. */ -public class SQLFragment extends Fragment{ +public class SQLFragment extends Fragment implements AsyncDatabaseConnector.OnPostExecuteListener { private EditText sqlEditText; private InputMethodManager inputMethodManager; + private SQLEntriesFragment sqlEntriesFragment; + private FragmentTransaction fragmentTransaction; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -66,7 +71,20 @@ public class SQLFragment extends Fragment{ String sqlQuery = String.valueOf(sqlEditText.getText()); Log.d("SQLQUERY", sqlQuery); - Static.asyncDatabaseConnector.setOnPostExecuteListener(null); - Static.asyncDatabaseConnector.executeSQL(null /*FIXME*/, sqlQuery); + fragmentTransaction = getFragmentManager().beginTransaction(); + sqlEntriesFragment = new SQLEntriesFragment(); + fragmentTransaction.replace(R.id.container, sqlEntriesFragment); + fragmentTransaction.commit(); + + Static.asyncDatabaseConnector.setStringReturnListener(sqlEntriesFragment); + Static.asyncDatabaseConnector.setListReturnListener(sqlEntriesFragment); + Static.asyncDatabaseConnector.setMatrixReturnListener(sqlEntriesFragment); + Static.asyncDatabaseConnector.setOnPostExecuteListener(this); + Static.asyncDatabaseConnector.executeSQL(getActivity().getIntent().getExtras().getString(Static.DATABASE_NAME_ARG), sqlQuery); + } + + @Override + public void onPostExecute() { + sqlEntriesFragment.onPostExecute(); } } diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/Static.java b/app/src/main/java/info/nerull7/mysqlbrowser/Static.java index 01d7d35..ca0281e 100644 --- a/app/src/main/java/info/nerull7/mysqlbrowser/Static.java +++ b/app/src/main/java/info/nerull7/mysqlbrowser/Static.java @@ -52,8 +52,9 @@ public class Static { builder.show(); } - public static void startSQL(Context context) { + public static void startSQL(Context context, String database) { Intent intent = new Intent(context, SQLActivity.class); + intent.putExtra(Static.DATABASE_NAME_ARG, database); context.startActivity(intent); } } diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java index 42a8e04..0162ca8 100644 --- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java +++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java @@ -360,20 +360,29 @@ public class AsyncDatabaseConnector { public void onFinished(String data, String error) { String []response = data.split("\n"); - List<String>headerList = null; - try { - headerList = parseListFromJSON(response[1]); - } catch (JSONException e) { e.printStackTrace(); } - if(listReturnListener!=null) { - listReturnListener.onListReturn(headerList); - } + if(response[0].equals("OK")) { + List<String> headerList = null; + try { + headerList = parseListFromJSON(response[1]); + } catch (JSONException e) { + e.printStackTrace(); + } + if (listReturnListener != null) { + listReturnListener.onListReturn(headerList); + } - List<List<String>> dataMatrix = null; - try { - dataMatrix = parseMatrixFromJSON(response[2]); - } catch (JSONException e) { e.printStackTrace(); } - if(matrixReturnListener!=null) - matrixReturnListener.onMatrixReturn(dataMatrix); + List<List<String>> dataMatrix = null; + try { + dataMatrix = parseMatrixFromJSON(response[2]); + } catch (JSONException e) { + e.printStackTrace(); + } + if (matrixReturnListener != null) + matrixReturnListener.onMatrixReturn(dataMatrix); + } else { + if(stringReturnListener!=null) + stringReturnListener.onStringReturn(data); + } } }, onPostExecuteListener, resources); downloader.execute(request); diff --git a/app/src/main/res/drawable-hdpi/ic_action_info.png b/app/src/main/res/drawable-hdpi/ic_action_info.png new file mode 100644 index 0000000..75ecc18 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_info.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_info.png b/app/src/main/res/drawable-mdpi/ic_action_info.png new file mode 100644 index 0000000..944ab3d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_info.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_info.png b/app/src/main/res/drawable-xhdpi/ic_action_info.png new file mode 100644 index 0000000..6e10fde Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_info.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_info.png b/app/src/main/res/drawable-xxhdpi/ic_action_info.png new file mode 100644 index 0000000..6835e8f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_info.png differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d4c83cb..e431c16 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -58,5 +58,6 @@ <string name="hint_sql_query">SQL Query</string> <string name="action_cancel">Cancel</string> <string name="action_execute">Execute</string> + <string name="info">Information</string> </resources>