Fix bug in notifying connection point not found
authorMarco Incalcaterra <marco.incalcaterra@thinksoft.it>
Sun, 17 Aug 2014 11:31:06 +0000 (13:31 +0200)
committerMarco Incalcaterra <marco.incalcaterra@thinksoft.it>
Sun, 17 Aug 2014 11:31:06 +0000 (13:31 +0200)
Fix bug in computing interface expanded list size (removed hardcoded
values)
Added manage, unmanage, set expected state (up, down, ignore) and find
switch port to interface list
Fix aesthetic problems in expandable list (graphs and interfaces list)
Integration of new support library
Target to new API version (20)

21 files changed:
android/src/agent/AndroidManifest.xml
android/src/agent/libs/android-support-v4.jar
android/src/console/AndroidManifest.xml
android/src/console/libs/android-support-v4.jar
android/src/console/res/drawable/expander_close.9.png [new file with mode: 0644]
android/src/console/res/drawable/expander_open.9.png [new file with mode: 0644]
android/src/console/res/drawable/group_indicator.xml [new file with mode: 0644]
android/src/console/res/layout/alarms_fragment.xml
android/src/console/res/layout/graph_view.xml
android/src/console/res/layout/graph_view_child_layout.xml
android/src/console/res/layout/graph_view_group_layout.xml
android/src/console/res/layout/interfaces_child.xml
android/src/console/res/layout/interfaces_fragment.xml
android/src/console/res/layout/interfaces_group.xml
android/src/console/res/menu/interface_actions.xml [new file with mode: 0644]
android/src/console/res/values/strings.xml
android/src/console/src/org/netxms/ui/android/main/activities/ConnectionPointBrowser.java
android/src/console/src/org/netxms/ui/android/main/activities/DrawGraph.java
android/src/console/src/org/netxms/ui/android/main/adapters/InterfacesAdapter.java
android/src/console/src/org/netxms/ui/android/main/adapters/LastValuesAdapter.java
android/src/console/src/org/netxms/ui/android/main/fragments/InterfacesFragment.java

index 7888fb4..b80cb0c 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-      package="org.netxms.agent.android" android:versionName="1.2.16" android:versionCode="3">
-       <uses-sdk android:targetSdkVersion="19" android:minSdkVersion="8"></uses-sdk>
+      package="org.netxms.agent.android" android:versionName="1.2.17" android:versionCode="4">
+       <uses-sdk android:targetSdkVersion="20" android:minSdkVersion="8"></uses-sdk>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
index cf12d28..c31cede 100644 (file)
Binary files a/android/src/agent/libs/android-support-v4.jar and b/android/src/agent/libs/android-support-v4.jar differ
index 32a03c9..234711d 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-      package="org.netxms.ui.android" android:versionName="1.2.16" android:versionCode="9">
-       <uses-sdk android:targetSdkVersion="19" android:minSdkVersion="8"></uses-sdk>
+      package="org.netxms.ui.android" android:versionName="1.2.17" android:versionCode="10">
+       <uses-sdk android:targetSdkVersion="20" android:minSdkVersion="8"></uses-sdk>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
index cf12d28..c31cede 100644 (file)
Binary files a/android/src/console/libs/android-support-v4.jar and b/android/src/console/libs/android-support-v4.jar differ
diff --git a/android/src/console/res/drawable/expander_close.9.png b/android/src/console/res/drawable/expander_close.9.png
new file mode 100644 (file)
index 0000000..22c0c8d
Binary files /dev/null and b/android/src/console/res/drawable/expander_close.9.png differ
diff --git a/android/src/console/res/drawable/expander_open.9.png b/android/src/console/res/drawable/expander_open.9.png
new file mode 100644 (file)
index 0000000..ca3e1ac
Binary files /dev/null and b/android/src/console/res/drawable/expander_open.9.png differ
diff --git a/android/src/console/res/drawable/group_indicator.xml b/android/src/console/res/drawable/group_indicator.xml
new file mode 100644 (file)
index 0000000..f9a7b5e
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+       <item android:state_empty="true" android:drawable="@drawable/expander_open" />
+       <item android:state_expanded="true" android:drawable="@drawable/expander_close" />
+       <item android:drawable="@drawable/expander_open" />
+</selector>
index 87c876f..a46361e 100644 (file)
@@ -30,7 +30,7 @@
                android:background="@color/item_body">
                <ListView android:id="@android:id/list"
                    android:layout_width="fill_parent"
-                       android:textColor="@color/text_color"
+                       android:textColor="@color/text_no_items"
                        android:background="@color/item_body"
                        android:cacheColorHint="@color/item_body" 
                    android:listSelector="@drawable/list_selection"
index 38c192e..8576143 100644 (file)
@@ -10,6 +10,7 @@
            android:layout_height="fill_parent" 
                android:textColor="@color/text_color"
                android:background="@color/item_body" 
-               android:cacheColorHint="@color/item_body" >
+               android:cacheColorHint="@color/item_body"
+               android:groupIndicator="@drawable/group_indicator" >
        </ExpandableListView>
 </LinearLayout>
index 8c79040..3053524 100644 (file)
@@ -8,8 +8,10 @@
                android:textIsSelectable="false"
            android:layout_width="fill_parent"
                android:layout_height="36dp"
-               android:paddingLeft="5dp"
+               android:paddingLeft="36dp"
+               android:paddingStart="36dp"
                android:paddingRight="5dp"
+               android:paddingEnd="5dp"
                android:gravity="center_vertical"
                android:textSize="17sp"
                android:textColor="@color/text_color"
index 40379b7..62c461f 100644 (file)
@@ -4,13 +4,16 @@
     android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_centerVertical="true" >
+
     <TextView
            android:id="@+id/tvGroup"
                android:textIsSelectable="false"
                android:layout_width="match_parent"
-           android:layout_height="36dip"
+           android:layout_height="36dp"
            android:paddingLeft="36dip"
+           android:paddingStart="36dip"
            android:paddingRight="5dip"
+           android:paddingEnd="5dip"
            android:gravity="center_vertical"
            android:textSize="17sp"
                android:textColor="@color/text_color"
index 01af97a..080026d 100644 (file)
@@ -2,13 +2,15 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/interface_view_child_layout"
     android:layout_width="fill_parent"
-       android:layout_height="fill_parent">
+       android:layout_height="wrap_content">
        <ListView 
                android:id="@+id/interfacesChild"
            android:layout_width="fill_parent"
-               android:layout_height="fill_parent"
-               android:paddingLeft="20dip"
+               android:layout_height="36dp"
+               android:paddingLeft="36dip"
+               android:paddingStart="36dip"
                android:paddingRight="5dip"
+               android:paddingEnd="5dip"
                android:gravity="center_vertical"
                android:textColor="@color/text_color"
                android:cacheColorHint="@color/item_body"
index 993aa6c..5771456 100644 (file)
@@ -35,7 +35,8 @@
                    android:layout_height="fill_parent" 
                        android:textColor="@color/text_color"
                        android:background="@color/item_body" 
-                       android:cacheColorHint="@color/item_body" >
+                       android:cacheColorHint="@color/item_body"
+                       android:groupIndicator="@drawable/group_indicator"  >
                </ExpandableListView>
 
         <TextView
index 9717bd8..091a66d 100644 (file)
@@ -1,12 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
     <TextView xmlns:android="http://schemas.android.com/apk/res/android"
         android:drawableLeft="@drawable/status_normal"
+        android:drawableStart="@drawable/status_normal"
         android:textIsSelectable="false"
            android:id="@+id/interface_text"
                android:layout_width="match_parent"
-           android:layout_height="48dip"
+           android:layout_height="36dp"
                android:paddingLeft="36dp"
+               android:paddingStart="36dp"
            android:paddingRight="5dip"
+           android:paddingEnd="5dip"
            android:paddingTop="10dip"
            android:paddingBottom="10dip"
            android:gravity="center_vertical"
diff --git a/android/src/console/res/menu/interface_actions.xml b/android/src/console/res/menu/interface_actions.xml
new file mode 100644 (file)
index 0000000..6ae929b
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+       <item android:id="@+id/manage" android:visible="true" android:checkable="false" android:enabled="true" android:checked="false" android:title="@string/if_manage"></item>
+       <item android:id="@+id/unmanage" android:visible="true" android:checkable="false" android:enabled="true" android:checked="false" android:title="@string/if_unmanage"></item>
+       <item android:id="@+id/if_expected_state" android:title="@string/if_expected_state">
+               <menu>
+                       <item android:id="@+id/if_expected_state_up" android:visible="true" android:checkable="false" android:enabled="true" android:checked="false" android:title="@string/if_expected_state_up"></item>
+                       <item android:id="@+id/if_expected_state_down" android:visible="true" android:checkable="false" android:enabled="true" android:checked="false" android:title="@string/if_expected_state_down"></item>
+                       <item android:id="@+id/if_expected_state_ignore" android:visible="true" android:checkable="false" android:enabled="true" android:checked="false" android:title="@string/if_expected_state_ignore"></item>
+               </menu>
+       </item>
+    <item android:id="@+id/find_switch_port" android:enabled="true" android:visible="true" android:title="@string/connection_point_find_switch_port"></item>
+</menu>
index fc87b3a..5995dfe 100644 (file)
        <string name="table_value_placeholder">&lt;&lt; TABLE &gt;&gt;</string>
        <string name="table_last_values">Table last values</string>
 
+       <string name="if_manage">Manage</string>
+       <string name="if_unmanage">Unmanage</string>
+       <string name="if_expected_state">Change expected state</string>
+       <string name="if_expected_state_up">UP</string>
+       <string name="if_expected_state_down">DOWN</string>
+       <string name="if_expected_state_ignore">IGNORE</string>
+                                               
        <string name="connection_point_title">MAC address search</string>
        <string name="connection_point_hint_type_macaddress">Type or scan MAC address&#8230;</string>
        <string name="connection_point_invalid">MAC Address &quot;%1$s&quot; is invalid</string>
        <string name="connection_point_notfound">Connection point not found</string>
        <string name="connection_point_macaddress_notfound">Connection point for MAC address %1$s not found</string>
-       <string name="connection_point_nodeid_notfound">Connection point for node %1$s not found</string>
+       <string name="connection_point_info_notfound">Connection point information cannot be found</string>
        <string name="connection_point_info">Node%1$s with MAC address %2$s is connected to network switch %3$s on port %4$s</string>
        <string name="connection_point_delete_one">Delete item</string>
        <string name="connection_point_delete_all">Delete all items</string>
index e7f875e..f7ff90b 100644 (file)
@@ -277,6 +277,7 @@ public class ConnectionPointBrowser extends AbstractClientActivity
                        }
                        catch (JSONException e)
                        {
+                               Log.e(TAG, "JSONException in retrievePreferences...", e);
                                e.printStackTrace();
                        }
                return values;
@@ -342,11 +343,6 @@ public class ConnectionPointBrowser extends AbstractClientActivity
                                                        bridge = (Node)session.findObjectById(cp.getNodeId());
                                                        iface = (Interface)session.findObjectById(cp.getInterfaceId());
                                                }
-                                               else
-                                               {
-                                                       session.syncMissingObjects(new long[] { nodeId }, false, NXCSession.OBJECT_SYNC_WAIT);
-                                                       host = (Node)session.findObjectById(nodeId);
-                                               }
                                        }
                                        catch (MacAddressFormatException e)
                                        {
@@ -362,10 +358,10 @@ public class ConnectionPointBrowser extends AbstractClientActivity
                                                Log.e(TAG, "IOException while executing syncMissingObjects", e);
                                        }
 
-                                       if ((bridge != null) && (iface != null))
+                                       if ((host != null) && (bridge != null) && (iface != null))
                                                string = r.getString(R.string.connection_point_info, host != null ? " " + host.getObjectName() : "", cp.getLocalMacAddress().toString(), bridge.getObjectName(), iface.getObjectName());
-                                       else if (host != null)
-                                               string = r.getString(R.string.connection_point_nodeid_notfound, host.getObjectName());
+                                       else
+                                               string = r.getString(R.string.connection_point_info_notfound);
                                }
                        }
                        return string;
index 052a75a..93b44e1 100644 (file)
@@ -61,7 +61,7 @@ public class DrawGraph extends AbstractClientActivity
                sp = PreferenceManager.getDefaultSharedPreferences(this);
                dialog = new ProgressDialog(this);
                setContentView(R.layout.graphics);
-               boolean showLegend = getIntent().getBooleanExtra("showLegend", true);
+               //boolean showLegend = getIntent().getBooleanExtra("showLegend", true);
                numGraphs = getIntent().getIntExtra("numGraphs", 0);
                if (numGraphs > 0)
                {
index 1ddf8ce..6e7d4fe 100644 (file)
@@ -9,6 +9,7 @@ import org.netxms.client.constants.Severity;
 import org.netxms.client.objects.Interface;
 import org.netxms.ui.android.R;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -84,6 +85,7 @@ public class InterfacesAdapter extends BaseExpandableListAdapter
                return childPosition;
        }
 
+       @SuppressLint("InflateParams")
        private ViewGroup getViewGroupChild(View convertView, ViewGroup parent)
        {
                // The parent will be our ListView from the ListActivity 
@@ -105,16 +107,18 @@ public class InterfacesAdapter extends BaseExpandableListAdapter
                InterfaceDetailsAdapter idAdapter = new InterfaceDetailsAdapter(parent.getContext());
                idAdapter.setValues((Interface)getChild(groupPosition, childPosition));
                label.setAdapter(idAdapter);
-
-               //////// TODO: FIX ASAP, REMOVE HARDCODED VALUES!!!
-               final int rowHeightDp = 24;
-               final int rowCount = 13;
-               // convert the dp values to pixels 
-               final float ROW_HEIGHT = context.getResources().getDisplayMetrics().density * rowHeightDp;
-               // set the height of the current grid 
-               label.getLayoutParams().height = Math.round(rowCount * ROW_HEIGHT);
-               //////// TODO: FIX ASAP, REMOVE HARDCODED VALUES!!!
-
+               TextView tv = (TextView)parent.findViewById(R.id.interface_text);
+               int totalHeight = tv != null ? tv.getMeasuredHeight() : 0;
+               for (int i = 0; i < idAdapter.getCount(); i++)
+               {
+                       View listItem = idAdapter.getView(i, null, label);
+                       listItem.measure(0, 0);
+                       totalHeight += listItem.getMeasuredHeight();
+               }
+               ViewGroup.LayoutParams params = label.getLayoutParams();
+               params.height = totalHeight + (label.getDividerHeight() * (idAdapter.getCount() - 1));
+               label.setLayoutParams(params);
+               label.requestLayout();
                return item;
        }
 
@@ -144,6 +148,7 @@ public class InterfacesAdapter extends BaseExpandableListAdapter
                return groupPosition;
        }
 
+       @SuppressLint("InflateParams")
        @Override
        public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
        {
@@ -156,6 +161,7 @@ public class InterfacesAdapter extends BaseExpandableListAdapter
                TextView tv = (TextView)convertView.findViewById(R.id.interface_text);
                tv.setText(" " + i.getObjectName());
                tv.setCompoundDrawablesWithIntrinsicBounds(parent.getResources().getDrawable(getInterfaceStatusIcon(i.getStatus())), null, null, null);
+
                return convertView;
        }
 
index 6f3316e..874bb82 100644 (file)
@@ -133,6 +133,7 @@ public class LastValuesAdapter extends BaseAdapter
         * @see android.widget.Adapter#getView(int, android.view.View,
         * android.view.ViewGroup)
         */
+       @SuppressLint("RtlHardcoded")
        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
index e33aa34..379126a 100644 (file)
@@ -3,22 +3,37 @@
  */
 package org.netxms.ui.android.main.fragments;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
+import org.netxms.client.NXCException;
+import org.netxms.client.NXCObjectModificationData;
+import org.netxms.client.NXCSession;
 import org.netxms.client.objects.AbstractObject;
 import org.netxms.client.objects.Interface;
 import org.netxms.ui.android.R;
 import org.netxms.ui.android.loaders.GenericObjectChildrenLoader;
+import org.netxms.ui.android.main.activities.ConnectionPointBrowser;
 import org.netxms.ui.android.main.adapters.InterfacesAdapter;
 
+import android.content.Intent;
 import android.os.Bundle;
 import android.support.v4.app.LoaderManager;
 import android.support.v4.content.Loader;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
 import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ExpandableListView;
+import android.widget.ListView;
 
 /**
  * Fragment for last values info
@@ -29,8 +44,14 @@ import android.view.ViewGroup;
 
 public class InterfacesFragment extends ExpandableListFragment implements LoaderManager.LoaderCallbacks<Set<AbstractObject>>
 {
+       private ListView lv = null;
        private InterfacesAdapter adapter = null;
        private final GenericObjectChildrenLoader loader = null;
+       private AbstractObject selectedObject = null;
+       private static final int IF_EXPECTED_STATE_UP = 0;
+       private static final int IF_EXPECTED_STATE_DOWN = 1;
+       private static final int IF_EXPECTED_STATE_IGNORE = 2;
+       private static final String TAG = "nxclient/InterfacesFragment";
 
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -55,8 +76,21 @@ public class InterfacesFragment extends ExpandableListFragment implements Loader
                        loader.setClassFilter(AbstractObject.OBJECT_INTERFACE);
                        loader.setService(service);
                }
+               lv = getListView();
+               registerForContextMenu(lv);
+               lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
+               {
+                       @Override
+                       public boolean onItemLongClick(AdapterView<?> arg0, View v, int position, long id)
+                       {
+                               if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_GROUP)
+                               {
+                                       selectedObject = (AbstractObject)adapter.getChild(ExpandableListView.getPackedPositionGroup(id), 0);
+                               }
+                               return false;
+                       }
+               });
        }
-
        @Override
        public void refresh()
        {
@@ -104,4 +138,106 @@ public class InterfacesFragment extends ExpandableListFragment implements Loader
        public void onLoaderReset(Loader<Set<AbstractObject>> arg0)
        {
        }
+
+       @Override
+       public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
+       {
+               android.view.MenuInflater inflater = getActivity().getMenuInflater();
+               inflater.inflate(R.menu.interface_actions, menu);
+       }
+
+       @Override
+       public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
+       {
+               inflater.inflate(R.menu.interface_actions, menu);
+               super.onCreateOptionsMenu(menu, inflater);
+       }
+
+       @Override
+       public void onPrepareOptionsMenu(Menu menu)
+       {
+               super.onPrepareOptionsMenu(menu);
+       }
+
+       @Override
+       public boolean onContextItemSelected(MenuItem item)
+       {
+               if (handleItemSelection(item))
+                       return true;
+               return super.onContextItemSelected(item);
+       }
+
+       @Override
+       public boolean onOptionsItemSelected(MenuItem item)
+       {
+               if (handleItemSelection(item))
+                       return true;
+               return super.onOptionsItemSelected(item);
+       }
+
+       /**
+        * Handles menu item selection for both Option and Context menus
+        * @param item  Menu item to handle
+        * @return true if menu has been properly handled
+        */
+       private boolean handleItemSelection(MenuItem item)
+       {
+               switch (item.getItemId())
+               {
+                       case R.id.manage:
+                               if (selectedObject != null)
+                                       service.setObjectMgmtState(selectedObject.getObjectId(), true);
+                               return true;
+                       case R.id.unmanage:
+                               if (selectedObject != null)
+                                       service.setObjectMgmtState(selectedObject.getObjectId(), false);
+                               return true;
+                       case R.id.if_expected_state_up:
+                               return modifyExpectedState(IF_EXPECTED_STATE_UP);
+                       case R.id.if_expected_state_down:
+                               return modifyExpectedState(IF_EXPECTED_STATE_DOWN);
+                       case R.id.if_expected_state_ignore:
+                               return modifyExpectedState(IF_EXPECTED_STATE_IGNORE);
+                       case R.id.find_switch_port:
+                               Intent fspIntent = new Intent(getActivity(), ConnectionPointBrowser.class);
+                               fspIntent.putExtra("nodeId", (int)selectedObject.getObjectId());
+                               startActivity(fspIntent);
+                               return true;
+               }
+               return false;
+       }
+
+       /**
+        * Modifies expected state of the selected interface
+        * @param newState      The new infterface state
+        * @return true if the command can be issued properly
+        */
+       private boolean modifyExpectedState(int newState)
+       {
+               if (selectedObject != null)
+               {
+                       NXCSession session = service.getSession();
+                       if (session != null)
+                       {
+                               NXCObjectModificationData md = new NXCObjectModificationData(selectedObject.getObjectId());
+                               md.setExpectedState(newState);
+                               try
+                               {
+                                       session.modifyObject(md);
+                               }
+                               catch (NXCException e)
+                               {
+                                       Log.e(TAG, "NXCException in modifyState...", e);
+                                       e.printStackTrace();
+                               }
+                               catch (IOException e)
+                               {
+                                       Log.e(TAG, "IOException in modifyState...", e);
+                                       e.printStackTrace();
+                               }
+                               return true;
+                       }
+               }
+               return false;
+       }
 }