/* * Geopaparazzi - Digital field mapping on Android based devices * Copyright (C) 2016 HydroloGIS (www.hydrologis.com) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package eu.geopaparazzi.spatialite.database.spatial.activities.databasesview; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Typeface; import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.BaseExpandableListAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.PopupMenu; import android.widget.Spinner; import android.widget.TextView; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; import eu.geopaparazzi.library.core.activities.GeocodeActivity; import eu.geopaparazzi.library.core.dialogs.ColorStrokeDialogFragment; import eu.geopaparazzi.library.core.dialogs.InsertCoordinatesDialogFragment; import eu.geopaparazzi.library.core.dialogs.LabelDialogFragment; import eu.geopaparazzi.library.core.dialogs.StrokeDashDialogFragment; import eu.geopaparazzi.library.core.dialogs.ZoomlevelDialogFragment; import eu.geopaparazzi.library.core.maps.SpatialiteMap; import eu.geopaparazzi.library.core.maps.SpatialiteMapOrderComparator; import eu.geopaparazzi.library.database.GPLog; import eu.geopaparazzi.library.style.ColorStrokeObject; import eu.geopaparazzi.library.style.ColorUtilities; import eu.geopaparazzi.library.style.LabelObject; import eu.geopaparazzi.library.util.GPDialogs; import eu.geopaparazzi.library.util.LibraryConstants; import eu.geopaparazzi.spatialite.R; import eu.geopaparazzi.spatialite.database.spatial.SpatialiteSourcesManager; import eu.geopaparazzi.spatialite.database.spatial.core.databasehandlers.SpatialiteDatabaseHandler; import eu.geopaparazzi.spatialite.database.spatial.core.tables.SpatialVectorTable; import eu.geopaparazzi.library.style.Style; import jsqlite.Exception; /** * Expandable list for tile sources. * * @author Andrea Antonello (www.hydrologis.com) */ public class SpatialiteDatabasesExpandableListAdapter extends BaseExpandableListAdapter { private Activity activity; private List<String> folderList; private List<List<SpatialiteMap>> tablesList; private int count = 0; private final String[] orderArray; private final HashMap<SpatialiteMap, ViewHolder> spatialiteMaps2Viewholders = new HashMap<>(); private List<SpatialiteMap> allSpatialiteMaps = new ArrayList<>(); private volatile boolean ignoreSpinnerEvents = false; private SpatialiteMap currentPropertiesEditedSpatialiteMap; /** * @param activity activity to use. * @param folder2TablesMap the folder and table map. */ public SpatialiteDatabasesExpandableListAdapter(Activity activity, LinkedHashMap<String, List<SpatialiteMap>> folder2TablesMap) { this.activity = activity; folderList = new ArrayList<String>(); tablesList = new ArrayList<>(); for (Entry<String, List<SpatialiteMap>> entry : folder2TablesMap.entrySet()) { folderList.add(entry.getKey()); List<SpatialiteMap> spatialiteMaps = entry.getValue(); tablesList.add(spatialiteMaps); allSpatialiteMaps.addAll(spatialiteMaps); } for (SpatialiteMap spatialiteMap : allSpatialiteMaps) { count++; } orderArray = new String[count]; for (int i = 0; i < count; i++) { orderArray[i] = String.valueOf(i); } orderSpatialiteMaps(); } private void orderSpatialiteMaps() { Collections.sort(allSpatialiteMaps, new SpatialiteMapOrderComparator()); for (int i = 0; i < allSpatialiteMaps.size(); i++) { allSpatialiteMaps.get(i).order = i; } } public Object getChild(int groupPosition, int childPosititon) { List<SpatialiteMap> list = tablesList.get(groupPosition); SpatialiteMap spatialiteMap = list.get(childPosititon); return spatialiteMap; } public long getChildId(int groupPosition, int childPosition) { return childPosition; } private static class ViewHolder { Spinner orderSpinner; CheckBox isVibileCheckbox; TextView tableNameView; TextView tableTypeView; Button moreButton; View view; } public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { final SpatialiteMap spatialiteMap = (SpatialiteMap) getChild(groupPosition, childPosition); ViewHolder viewHolder = spatialiteMaps2Viewholders.get(spatialiteMap); if (viewHolder == null) { viewHolder = new ViewHolder(); LayoutInflater infalInflater = (LayoutInflater) this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); viewHolder.view = infalInflater.inflate(R.layout.spatialitedatabases_list_item, null); spatialiteMaps2Viewholders.put(spatialiteMap, viewHolder); } convertView = viewHolder.view; viewHolder.orderSpinner = (Spinner) convertView.findViewById(R.id.orderSpinner); ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this.activity, android.R.layout.simple_spinner_item, orderArray); spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); viewHolder.orderSpinner.setAdapter(spinnerArrayAdapter); viewHolder.orderSpinner.setSelection((int) spatialiteMap.order); final Spinner orderSpinner = viewHolder.orderSpinner; viewHolder.orderSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (ignoreSpinnerEvents) return; String item = orderSpinner.getSelectedItem().toString(); double newOrder = count + 1; try { newOrder = Double.parseDouble(item); } catch (NumberFormatException e) { GPLog.error(this, null, e); } if (spatialiteMap.order == newOrder) { return; } else if (spatialiteMap.order < newOrder) { newOrder = newOrder + 0.1; } else { newOrder = newOrder - 0.1; } spatialiteMap.order = newOrder; // reorder orderSpatialiteMaps(); ignoreSpinnerEvents = true; // fix combos for (Entry<SpatialiteMap, ViewHolder> entry : spatialiteMaps2Viewholders.entrySet()) { int order = (int) entry.getKey().order; entry.getValue().orderSpinner.setSelection(order); } new Thread(new Runnable() { public void run() { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } ignoreSpinnerEvents = false; } }).start(); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); viewHolder.isVibileCheckbox = (CheckBox) convertView.findViewById(R.id.isVisibleCheckbox); viewHolder.isVibileCheckbox.setChecked(spatialiteMap.isVisible); viewHolder.isVibileCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { spatialiteMap.isVisible = isChecked; } }); viewHolder.tableNameView = (TextView) convertView.findViewById(R.id.source_header_titletext); viewHolder.tableNameView.setText(spatialiteMap.tableName); viewHolder.tableTypeView = (TextView) convertView.findViewById(R.id.source_header_descriptiontext); viewHolder.tableTypeView.setText("[" + spatialiteMap.geometryType + "]"); viewHolder.moreButton = (Button) convertView.findViewById(R.id.moreButton); final ViewHolder finalViewHolder = viewHolder; viewHolder.moreButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { openMoreMenu(finalViewHolder.moreButton, spatialiteMap); } }); return viewHolder.view; } private void openMoreMenu(Button button, final SpatialiteMap spatialiteMap) { final String zoomToTitle = "Zoom to"; final String labellingTitle = "Labelling"; final String propertiesTitle = "Properties"; final String extrasTitle = "Extras"; PopupMenu popup = new PopupMenu(this.activity, button); popup.getMenu().add(zoomToTitle); popup.getMenu().add(labellingTitle); popup.getMenu().add(propertiesTitle); popup.getMenu().add(extrasTitle); popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { String actionName = item.getTitle().toString(); try { if (actionName.equals(zoomToTitle)) { zoomTo(spatialiteMap); } else if (actionName.equals(labellingTitle)) { labelling(spatialiteMap); } else if (actionName.equals(propertiesTitle)) { properties(spatialiteMap); } else if (actionName.equals(extrasTitle)) { extras(spatialiteMap); } } catch (Exception e) { GPLog.error(this, null, e); } return true; } }); popup.show(); } private void extras(final SpatialiteMap spatialiteMap) { String[] items = new String[]{"Stroke Dash", "Zoomlevel visibility"};//, "Decimation"}; new AlertDialog.Builder(activity).setSingleChoiceItems(items, 0, null) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { dialog.dismiss(); currentPropertiesEditedSpatialiteMap = spatialiteMap; SpatialVectorTable spatialVectorTable = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2TablesMap().get(spatialiteMap); Style style = spatialVectorTable.getStyle(); int selectedPosition = ((AlertDialog) dialog).getListView().getCheckedItemPosition(); if (selectedPosition == 0) { float[] dash = Style.dashFromString(style.dashPattern); StrokeDashDialogFragment strokeDashDialogFragment; if (dash != null && dash.length > 2) { float[] dashPart = Style.getDashOnly(dash); strokeDashDialogFragment = StrokeDashDialogFragment.newInstance(dashPart, Style.getDashShift(dash)); } else { strokeDashDialogFragment = StrokeDashDialogFragment.newInstance(null, 0); } strokeDashDialogFragment.show(((AppCompatActivity) activity).getSupportFragmentManager(), "Stroke Dash Dialog"); } else if (selectedPosition == 1) { int[] minMaxZoomlevel = {style.minZoom, style.maxZoom}; ZoomlevelDialogFragment zoomlevelDialogFragment = ZoomlevelDialogFragment.newInstance(minMaxZoomlevel); zoomlevelDialogFragment.show(((AppCompatActivity) activity).getSupportFragmentManager(), "Zoomlevel Dialog"); } else if (selectedPosition == 2) { // TODO decimation } } }).show(); } private void properties(SpatialiteMap spatialiteMap) { currentPropertiesEditedSpatialiteMap = spatialiteMap; SpatialVectorTable spatialVectorTable = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2TablesMap().get(spatialiteMap); Style style = spatialVectorTable.getStyle(); ColorStrokeObject colorStrokeObject = new ColorStrokeObject(); boolean isPoint = spatialVectorTable.isPoint(); boolean isLine = spatialVectorTable.isLine(); boolean isPolygon = spatialVectorTable.isPolygon(); if (isPolygon || isPoint) { colorStrokeObject.hasFill = true; colorStrokeObject.fillColor = ColorUtilities.toColor(style.fillcolor); colorStrokeObject.fillAlpha = (int) (style.fillalpha * 255); } if (isPolygon || isLine || isPoint) { colorStrokeObject.hasStroke = true; colorStrokeObject.strokeColor = ColorUtilities.toColor(style.strokecolor); colorStrokeObject.strokeAlpha = (int) (style.strokealpha * 255); colorStrokeObject.hasStrokeWidth = true; colorStrokeObject.strokeWidth = (int) style.width; } if (isPoint) { colorStrokeObject.hasShape = true; colorStrokeObject.shapeWKT = style.shape; colorStrokeObject.shapeSize = (int) style.size; } ColorStrokeDialogFragment colorStrokeDialogFragment = ColorStrokeDialogFragment.newInstance(colorStrokeObject); colorStrokeDialogFragment.show(((AppCompatActivity) activity).getSupportFragmentManager(), "Color Stroke Dialog"); } public void onPropertiesChanged(ColorStrokeObject newColorStrokeObject) { if (currentPropertiesEditedSpatialiteMap != null) { SpatialVectorTable spatialVectorTable = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2TablesMap().get(currentPropertiesEditedSpatialiteMap); Style style = spatialVectorTable.getStyle(); boolean isPoint = spatialVectorTable.isPoint(); boolean isLine = spatialVectorTable.isLine(); boolean isPolygon = spatialVectorTable.isPolygon(); if (isPolygon || isPoint) { style.fillcolor = ColorUtilities.getHex(newColorStrokeObject.fillColor); style.fillalpha = newColorStrokeObject.fillAlpha / 255f; } if (isPolygon || isLine || isPoint) { style.strokecolor = ColorUtilities.getHex(newColorStrokeObject.strokeColor); style.strokealpha = newColorStrokeObject.strokeAlpha / 255f; style.width = newColorStrokeObject.strokeWidth; } if (isPoint) { style.shape = newColorStrokeObject.shapeWKT; style.size = newColorStrokeObject.shapeSize; } HashMap<SpatialiteMap, SpatialiteDatabaseHandler> spatialiteMaps2DbHandlersMap = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2DbHandlersMap(); SpatialiteDatabaseHandler spatialiteDatabaseHandler = spatialiteMaps2DbHandlersMap.get(currentPropertiesEditedSpatialiteMap); try { spatialiteDatabaseHandler.updateStyle(style); } catch (jsqlite.Exception e) { GPLog.error(this, null, e); } } } private void labelling(SpatialiteMap spatialiteMap) { if (spatialiteMap != null) { currentPropertiesEditedSpatialiteMap = spatialiteMap; SpatialVectorTable spatialVectorTable = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2TablesMap().get(spatialiteMap); Style style = spatialVectorTable.getStyle(); LabelObject labelObject = new LabelObject(); labelObject.hasLabel = style.labelvisible == 1; labelObject.labelFieldsList = spatialVectorTable.getTableFieldNamesList(); labelObject.label = style.labelfield; labelObject.labelSize = (int) style.labelsize; LabelDialogFragment labelDialogFragment = LabelDialogFragment.newInstance(labelObject); labelDialogFragment.show(((AppCompatActivity) activity).getSupportFragmentManager(), "Label Dialog"); } } public void onPropertiesChanged(LabelObject newLabelObject) { if (currentPropertiesEditedSpatialiteMap != null) { SpatialVectorTable spatialVectorTable = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2TablesMap().get(currentPropertiesEditedSpatialiteMap); Style style = spatialVectorTable.getStyle(); style.labelvisible = newLabelObject.hasLabel ? 1 : 0; style.labelfield = newLabelObject.label; style.labelsize = newLabelObject.labelSize; HashMap<SpatialiteMap, SpatialiteDatabaseHandler> spatialiteMaps2DbHandlersMap = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2DbHandlersMap(); SpatialiteDatabaseHandler spatialiteDatabaseHandler = spatialiteMaps2DbHandlersMap.get(currentPropertiesEditedSpatialiteMap); try { spatialiteDatabaseHandler.updateStyle(style); } catch (jsqlite.Exception e) { GPLog.error(this, null, e); } } } public void onPropertiesChanged(int minZoomlevel, int maxZoomlevel) { if (currentPropertiesEditedSpatialiteMap != null) { SpatialVectorTable spatialVectorTable = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2TablesMap().get(currentPropertiesEditedSpatialiteMap); Style style = spatialVectorTable.getStyle(); style.minZoom = minZoomlevel; style.maxZoom = maxZoomlevel; HashMap<SpatialiteMap, SpatialiteDatabaseHandler> spatialiteMaps2DbHandlersMap = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2DbHandlersMap(); SpatialiteDatabaseHandler spatialiteDatabaseHandler = spatialiteMaps2DbHandlersMap.get(currentPropertiesEditedSpatialiteMap); try { spatialiteDatabaseHandler.updateStyle(style); } catch (jsqlite.Exception e) { GPLog.error(this, null, e); } } } public void onDashChanged(float[] dash, float shift) { if (currentPropertiesEditedSpatialiteMap != null) { SpatialVectorTable spatialVectorTable = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2TablesMap().get(currentPropertiesEditedSpatialiteMap); Style style = spatialVectorTable.getStyle(); style.dashPattern = Style.dashToString(dash, shift); HashMap<SpatialiteMap, SpatialiteDatabaseHandler> spatialiteMaps2DbHandlersMap = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2DbHandlersMap(); SpatialiteDatabaseHandler spatialiteDatabaseHandler = spatialiteMaps2DbHandlersMap.get(currentPropertiesEditedSpatialiteMap); try { spatialiteDatabaseHandler.updateStyle(style); } catch (jsqlite.Exception e) { GPLog.error(this, null, e); } } } private void zoomTo(SpatialiteMap spatialiteMap) throws Exception { HashMap<SpatialiteMap, SpatialiteDatabaseHandler> spatialiteMaps2DbHandlersMap = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2DbHandlersMap(); SpatialiteDatabaseHandler spatialiteDatabaseHandler = spatialiteMaps2DbHandlersMap.get(spatialiteMap); HashMap<SpatialiteMap, SpatialVectorTable> spatialiteMaps2TablesMap = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps2TablesMap(); SpatialVectorTable spatialVectorTable = spatialiteMaps2TablesMap.get(spatialiteMap); if (spatialiteDatabaseHandler != null) { float[] tableBounds = spatialiteDatabaseHandler.getTableBounds(spatialVectorTable); double lat = tableBounds[1] + (tableBounds[0] - tableBounds[1]) / 2.0; double lon = tableBounds[3] + (tableBounds[2] - tableBounds[3]) / 2.0; Intent intent = activity.getIntent(); intent.putExtra(LibraryConstants.LATITUDE, lat); intent.putExtra(LibraryConstants.LONGITUDE, lon); intent.putExtra(LibraryConstants.ZOOMLEVEL, 16); activity.setResult(Activity.RESULT_OK, intent); activity.finish(); } } public int getChildrenCount(int groupPosition) { List<SpatialiteMap> list = tablesList.get(groupPosition); return list.size(); } public Object getGroup(int groupPosition) { return folderList.get(groupPosition); } public int getGroupCount() { return folderList.size(); } public long getGroupId(int groupPosition) { return groupPosition; } public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { String folder = (String) getGroup(groupPosition); if (convertView == null) { LayoutInflater infalInflater = (LayoutInflater) this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = infalInflater.inflate(R.layout.spatialitedatabases_list_header, null); } File dbFile = new File(folder); TextView dbName = (TextView) convertView.findViewById(R.id.sources_header_nametext); dbName.setTypeface(null, Typeface.BOLD); dbName.setText(dbFile.getName()); TextView folderName = (TextView) convertView.findViewById(R.id.sources_header_pathtext); folderName.setText(dbFile.getParent()); return convertView; } public boolean hasStableIds() { return false; } public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } }