diff options
author | Iain Billett <iainbillett@gmail.com> | 2012-07-30 17:11:43 +0100 |
---|---|---|
committer | Michael Meeks <michael.meeks@suse.com> | 2012-08-07 15:23:54 +0100 |
commit | 779baa0572f5d2593e2347600b95a6db5f693bc5 (patch) | |
tree | 7ce57e4d92b115e41f5a54521485884aec7e7d0f /android/experimental | |
parent | cbddf975d3a52e34b9b9773789e2ff3a4954c4a8 (diff) |
Changed folder icon to show thumbnails of docs within folder.
Change-Id: I8ec061a3daafef733b8786c34269165697c2b443
Diffstat (limited to 'android/experimental')
5 files changed, 599 insertions, 4 deletions
diff --git a/android/experimental/LibreOffice4Android/res/layout/file_explorer_folder_icon.xml b/android/experimental/LibreOffice4Android/res/layout/file_explorer_folder_icon.xml new file mode 100644 index 000000000000..60dd9b9e2d81 --- /dev/null +++ b/android/experimental/LibreOffice4Android/res/layout/file_explorer_folder_icon.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + This file is part of the LibreOffice project. + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <org.libreoffice.ui.FolderIconView + android:id="@+id/folder_icon" + android:layout_width="100dp" + android:layout_height="142dp" + android:paddingTop="15dp" + android:paddingBottom="10dp" + android:layout_gravity="center" > + </org.libreoffice.ui.FolderIconView> + + <TextView + android:id="@+id/grid_item_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@+id/label" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:layout_gravity="center" + android:textSize="15dp" + android:textStyle="bold" + android:maxLines="2"> + </TextView> + +</LinearLayout>
\ No newline at end of file diff --git a/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/FileUtilities.java b/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/FileUtilities.java index 71e67c1df3fc..4f1036328367 100644 --- a/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/FileUtilities.java +++ b/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/FileUtilities.java @@ -195,6 +195,18 @@ public class FileUtilities { return; } + static boolean isHidden( File file ){ + if( file.getName().startsWith(".") ) + return true; + return false; + } + + static boolean isThumbnail( File file ){ + if( isHidden(file) && file.getName().endsWith(".png") ) + return true; + return false; + } + static boolean hasThumbnail(File file) { String filename = file.getName(); diff --git a/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/FolderIconView.java b/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/FolderIconView.java new file mode 100644 index 000000000000..4f518ed22e8f --- /dev/null +++ b/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/FolderIconView.java @@ -0,0 +1,197 @@ +package org.libreoffice.ui; + +import org.libreoffice.R; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Color; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; + +import java.io.File; +import java.util.Stack; + +public class FolderIconView extends View{ + private String TAG = "FolderIconView"; + + private Paint mPaintBlack; + private Paint mPaintGray; + private Paint mPaintShadow; + + private File dir; + + public FolderIconView(Context context ) { + super(context); + initialisePaints(); + } + public FolderIconView(Context context, AttributeSet attrs) { + super(context, attrs); + initialisePaints(); + } + public FolderIconView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initialisePaints(); + } + + private void initialisePaints(){ + mPaintBlack = new Paint(); + mPaintBlack.setColor( Color.DKGRAY );//Can also use parseColor( String "#aarrggbb") + mPaintBlack.setAntiAlias( true ); + + mPaintGray = new Paint(); + mPaintGray.setColor( Color.GRAY );//Can also use parseColor( String "#aarrggbb") + mPaintGray.setAntiAlias( true ); + + mPaintShadow = new Paint(); + mPaintShadow.setColor( Color.parseColor( "#88888888") ); + mPaintShadow.setAntiAlias( true ); + } + + public void setDir( File dir ){ + this.dir = dir; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + Log.d( TAG, "onDraw"); + //float width = (float)canvas.getWidth(); + //float height = (float)canvas.getHeight(); + float width = (float)this.getWidth(); + float height = (float)this.getHeight(); + float centerX = width*0.5f;// centered on horz axis + float centerY = height*0.5f; + float outterRadius = 0.8f*0.5f* width; + float innerRadius = 0.7f*0.5f* width; + float thumbHeight = outterRadius*1.25f; + float thumbWidth = thumbHeight*(float)(1/Math.sqrt(2)); + float DZx = 0.2f*outterRadius; + float DZy = 0.2f*outterRadius; + //Bitmap blankPage = BitmapFactory.decodeResource( getResources() , R.drawable.page ); + Log.i( TAG , Float.toString( width ) + " X " + Float.toString( height ) ); + canvas.drawCircle( centerX , centerY , outterRadius , mPaintGray ); + canvas.drawCircle( centerX , centerY , innerRadius , mPaintBlack ); + //Either get thumbs from directory or use generic page images + //For now just get the first 4 thumbs -> add some checks later + if( dir == null ) + return;//TODO + File[] contents = dir.listFiles();//TODO consider filtering thumbs to match grid. + Stack<Bitmap> thumbs = new Stack<Bitmap>(); + BitmapFactory factory = new BitmapFactory(); + for( File file : contents ){ + if( !FileUtilities.isThumbnail(file) ) + continue; + thumbs.push( factory.decodeFile( file.getAbsolutePath() ) );//TODO switch to push for semantics + if( thumbs.size() > 3 ) + break; + } + /*while( thumbs.size() < 4 ){// padd out with blanks? + thumbs.push( blankPage ); + }*/ + Log.i( TAG, Integer.toString( thumbs.size() ) ); + //should handle empty folders better + // options: + // don't show? + // show generic LO icons for writer etc + // Show a generic blank page icon + if( thumbs.isEmpty() ) + return; + /*float left = centerX ;//+ 0.25f*outterRadius; + float top = centerY - 0.5f*outterRadius; + float right = left + thumbs.get(0).getWidth()*0.4f; + float bottom = top + thumbs.get(0).getHeight()*0.4f; + RectF dest = new RectF( left, top , right , bottom ); + RectF shadowBox = new RectF(dest); + shadowBox.inset( -1 , -1 ); + int size = thumbs.size(); + for( int i = 1 ; i <= size ; i++ ){ + canvas.drawRect( shadowBox , mPaintShadow); + canvas.drawBitmap( thumbs.pop() , null , dest , null); + dest.offset( -outterRadius*0.2f , outterRadius*0.1f ); + shadowBox.offset( -outterRadius*0.2f , outterRadius*0.1f ); + }*/ + float left; + float top; + float right; + float bottom; + RectF dest; + RectF shadowBox; + int size; + switch( thumbs.size() ){ + case 0: + break; + case 1: + left = centerX - 0.5f*thumbWidth; + top = centerY - 0.5f*thumbHeight; + right = left + thumbWidth; + bottom = top + thumbHeight; + dest = new RectF( left, top , right , bottom ); + shadowBox = new RectF(dest); + shadowBox.inset( -1 , -1 ); + canvas.drawRect( shadowBox , mPaintShadow); + canvas.drawBitmap( thumbs.pop() , null , dest , null); + break; + case 2: + left = centerX - 0.5f*thumbWidth + 0.5f*DZx; + top = centerY - 0.5f*thumbHeight - 0.5f*DZy; + right = left + thumbWidth; + bottom = top + thumbHeight; + dest = new RectF( left, top , right , bottom ); + shadowBox = new RectF(dest); + shadowBox.inset( -1 , -1 ); + size = thumbs.size(); + for( int i = 1 ; i <= size ; i++ ){ + canvas.drawRect( shadowBox , mPaintShadow); + canvas.drawBitmap( thumbs.pop() , null , dest , null); + dest.offset( -DZx , DZy ); + shadowBox.offset( -DZx , DZy ); + } + break; + case 3: + left = centerX - 0.5f*thumbWidth + DZx; + top = centerY - 0.5f*thumbHeight - DZy; + right = left + thumbWidth; + bottom = top + thumbHeight; + dest = new RectF( left, top , right , bottom ); + shadowBox = new RectF(dest); + shadowBox.inset( -1 , -1 ); + size = thumbs.size(); + for( int i = 1 ; i <= size ; i++ ){ + canvas.drawRect( shadowBox , mPaintShadow); + canvas.drawBitmap( thumbs.pop() , null , dest , null); + dest.offset( -DZx , DZy ); + shadowBox.offset( -DZx , DZy ); + } + break; + case 4: + left = centerX - 0.5f*thumbWidth + 1.5f*DZx; + top = centerY - 0.5f*thumbHeight - 1.5f*DZy; + right = left + thumbWidth; + bottom = top + thumbHeight; + dest = new RectF( left, top , right , bottom ); + shadowBox = new RectF(dest); + shadowBox.inset( -1 , -1 ); + size = thumbs.size(); + for( int i = 1 ; i <= size ; i++ ){ + canvas.drawRect( shadowBox , mPaintShadow); + canvas.drawBitmap( thumbs.pop() , null , dest , null); + dest.offset( -DZx , DZy ); + shadowBox.offset( -DZx , DZy ); + } + break; + default: + break; + } + //test + + return; + } + +} diff --git a/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/GridItemAdapter.java b/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/GridItemAdapter.java index e2e26b4b9d09..983aba914783 100644 --- a/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/GridItemAdapter.java +++ b/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/GridItemAdapter.java @@ -89,9 +89,16 @@ public class GridItemAdapter extends BaseAdapter{ .findViewById(R.id.grid_item_image); if( filePaths[position].isDirectory() ) // Is a folder { - // Eventually have thumbnails of each sub file on a black circle - // For now just a folder icon + // Default view is a generic folder icon. imageView.setImageResource(R.drawable.folder); + // How should we handle empty folders / folders with no thumbnails? -> new files + gridView = inflater.inflate(R.layout.file_explorer_folder_icon, null); + org.libreoffice.ui.FolderIconView icon = + (org.libreoffice.ui.FolderIconView)gridView.findViewById(R.id.folder_icon); + icon.setDir( filePaths[position]); + textView = (TextView) gridView.findViewById(R.id.grid_item_label); + textView.setText(filePaths[position].getName()); + return gridView; } else { diff --git a/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/LibreOfficeUIActivity.java index dfb28d1ce0da..8a9b1cbd340e 100644 --- a/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/LibreOfficeUIActivity.java +++ b/android/experimental/LibreOffice4Android/src/org/libreoffice/ui/LibreOfficeUIActivity.java @@ -10,6 +10,7 @@ package org.libreoffice.ui; import org.libreoffice.R; import org.libreoffice.android.DocumentLoader; +import org.libreoffice.android.Bootstrap; import java.io.File; import java.io.FileFilter; @@ -35,6 +36,8 @@ import android.graphics.Shader.TileMode; import android.app.ActionBar.OnNavigationListener; import android.app.Activity; +import android.os.AsyncTask; +import android.graphics.Bitmap; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -57,6 +60,28 @@ import android.widget.ListView; import android.widget.SpinnerAdapter; import android.widget.TextView; +import com.sun.star.awt.Size; +import com.sun.star.awt.XBitmap; +import com.sun.star.awt.XControl; +import com.sun.star.awt.XDevice; +import com.sun.star.awt.XToolkit2; +import com.sun.star.beans.PropertyValue; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XController; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XModel; +import com.sun.star.lang.XEventListener; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.uno.Type; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.view.XRenderable; + +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + public class LibreOfficeUIActivity extends SherlockActivity implements ActionBar.OnNavigationListener { private String tag = "file_manager"; private SharedPreferences prefs; @@ -84,6 +109,20 @@ public class LibreOfficeUIActivity extends SherlockActivity implements ActionBar GridView gv; ListView lv; + private static final String TAG = "ThumbnailGenerator"; + private static final int SMALLSIZE = 128; + + long timingOverhead; + XComponentContext context; + XMultiComponentFactory mcf; + XComponentLoader componentLoader; + XToolkit2 toolkit; + XDevice dummySmallDevice; + Object doc; + int pageCount; + int currentPage; + XRenderable renderable; + @Override public void onCreate(Bundle savedInstanceState) { @@ -173,7 +212,11 @@ public class LibreOfficeUIActivity extends SherlockActivity implements ActionBar fileNames = new String[ filePaths.length ]; FileUtilities.sortFiles( filePaths, sortMode ); for( int i = 0; i < fileNames.length; i++){ - fileNames[ i ] = filePaths[ i ].getName(); + fileNames[ i ] = filePaths[ i ].getName(); + if( !FileUtilities.hasThumbnail( filePaths[ i ] ) ) + { + //new ThumbnailGenerator( filePaths[ i ] ); + } } if( viewMode == GRID_VIEW){ gv.setAdapter( new GridItemAdapter(getApplicationContext(), currentDirectory, filePaths ) ); @@ -583,8 +626,309 @@ class ListItemAdapter implements ListAdapter{ return false; } - } + } + + class ThumbnailGenerator{ + private File file; + + ThumbnailGenerator( File file ){ + this.file = file; + try { + long t0 = System.currentTimeMillis(); + long t1 = System.currentTimeMillis(); + timingOverhead = t1 - t0; + + Bootstrap.setup(LibreOfficeUIActivity.this); + + Bootstrap.putenv("SAL_LOG=yes"); + + // Load a lot of shlibs here explicitly in advance because that + // makes debugging work better, sigh + Bootstrap.dlopen("libvcllo.so"); + Bootstrap.dlopen("libmergedlo.so"); + Bootstrap.dlopen("libswdlo.so"); + Bootstrap.dlopen("libswlo.so"); + + // Log.i(TAG, "Sleeping NOW"); + // Thread.sleep(20000); + + context = com.sun.star.comp.helper.Bootstrap.defaultBootstrap_InitialComponentContext(); + + Log.i(TAG, "context is" + (context!=null ? " not" : "") + " null"); + + mcf = context.getServiceManager(); + + Log.i(TAG, "mcf is" + (mcf!=null ? " not" : "") + " null"); + + String input = file.getAbsolutePath(); + if (input == null) + input = "/assets/test1.odt"; + + // We need to fake up an argv, and the argv[0] even needs to + // point to some file name that we can pretend is the "program". + // setCommandArgs() will prefix argv[0] with the app's data + // directory. + + String[] argv = { "lo-document-loader", input }; + + Bootstrap.setCommandArgs(argv); + + Bootstrap.initVCL(); + + Object desktop = mcf.createInstanceWithContext + ("com.sun.star.frame.Desktop", context); + + Log.i(TAG, "desktop is" + (desktop!=null ? " not" : "") + " null"); + + Bootstrap.initUCBHelper(); + + componentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, desktop); + + Log.i(TAG, "componentLoader is" + (componentLoader!=null ? " not" : "") + " null"); + // Load the wanted document + new DocumentLoadTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, "file://" + input); + } + catch (Exception e) { + e.printStackTrace(System.err); + } + } + + class DocumentLoadTask + extends AsyncTask<String, Void, Integer> + { + + ByteBuffer renderPage(int number, int width , int height) + { + try { + // Use dummySmallDevice with no scale of offset just to find out + // the paper size of this page. + + PropertyValue renderProps[] = new PropertyValue[3]; + renderProps[0] = new PropertyValue(); + renderProps[0].Name = "IsPrinter"; + renderProps[0].Value = new Boolean(true); + renderProps[1] = new PropertyValue(); + renderProps[1].Name = "RenderDevice"; + renderProps[1].Value = dummySmallDevice; + renderProps[2] = new PropertyValue(); + renderProps[2].Name = "View"; + renderProps[2].Value = new MyXController(); + + // getRenderer returns a set of properties that include the PageSize + long t0 = System.currentTimeMillis(); + PropertyValue rendererProps[] = renderable.getRenderer(number, doc, renderProps); + long t1 = System.currentTimeMillis(); + Log.i(TAG, "w,h getRenderer took " + ((t1-t0)-timingOverhead) + " ms"); + + int pageWidth = 0, pageHeight = 0; + for (int i = 0; i < rendererProps.length; i++) { + if (rendererProps[i].Name.equals("PageSize")) { + pageWidth = ((Size) rendererProps[i].Value).Width; + pageHeight = ((Size) rendererProps[i].Value).Height; + Log.i(TAG, " w,h PageSize: " + pageWidth + "x" + pageHeight); + } + } + + // Create a new device with the correct scale and offset + ByteBuffer bb = ByteBuffer.allocateDirect(width*height*4); + long wrapped_bb = Bootstrap.new_byte_buffer_wrapper(bb); + + XDevice device; + if (pageWidth == 0) { + // Huh? + device = toolkit.createScreenCompatibleDeviceUsingBuffer(width, height, 1, 1, 0, 0, wrapped_bb); + } else { + + // Scale so that it fits our device which has a resolution of 96/in (see + // SvpSalGraphics::GetResolution()). The page size returned from getRenderer() is in 1/mm * 100. + + int scaleNumerator, scaleDenominator; + + // If the view has a wider aspect ratio than the page, fit + // height; otherwise, fit width + if ((double) width / height > (double) pageWidth / pageHeight) { + scaleNumerator = height; + scaleDenominator = pageHeight / 2540 * 96; + } else { + scaleNumerator = width; + scaleDenominator = pageWidth / 2540 * 96; + } + Log.i(TAG, "w,h Scaling with " + scaleNumerator + "/" + scaleDenominator); + + device = toolkit.createScreenCompatibleDeviceUsingBuffer(width, height, + scaleNumerator, scaleDenominator, + 0, 0, + wrapped_bb); + } + + // Update the property that points to the device + renderProps[1].Value = device; + + t0 = System.currentTimeMillis(); + renderable.render(number, doc, renderProps); + t1 = System.currentTimeMillis(); + Log.i(TAG, "w,h Rendering page " + number + " took " + ((t1-t0)-timingOverhead) + " ms"); + + Bootstrap.force_full_alpha_bb(bb, 0, width * height * 4); + return bb; + } + catch (Exception e) { + e.printStackTrace(System.err); + finish(); + } + + return null; + } + + protected void onPreExecute (){ + //TODO put doc loading & set-up here? + } + + protected Integer doInBackground(String... params) + { + try { + String url = params[0]; + Log.i(TAG, "Attempting to load " + url); + + PropertyValue loadProps[] = new PropertyValue[3]; + loadProps[0] = new PropertyValue(); + loadProps[0].Name = "Hidden"; + loadProps[0].Value = new Boolean(true); + loadProps[1] = new PropertyValue(); + loadProps[1].Name = "ReadOnly"; + loadProps[1].Value = new Boolean(true); + loadProps[2] = new PropertyValue(); + loadProps[2].Name = "Preview"; + loadProps[2].Value = new Boolean(true); + + long t0 = System.currentTimeMillis(); + doc = componentLoader.loadComponentFromURL(url, "_blank", 0, loadProps); + long t1 = System.currentTimeMillis(); + Log.i(TAG, "Loading took " + ((t1-t0)-timingOverhead) + " ms"); + + Object toolkitService = mcf.createInstanceWithContext + ("com.sun.star.awt.Toolkit", context); + toolkit = (XToolkit2) UnoRuntime.queryInterface(XToolkit2.class, toolkitService); + + renderable = (XRenderable) UnoRuntime.queryInterface(XRenderable.class, doc); + + // Set up dummySmallDevice and use it to find out the number + // of pages ("renderers"). + ByteBuffer smallbb = ByteBuffer.allocateDirect(SMALLSIZE*SMALLSIZE*4); + long wrapped_smallbb = Bootstrap.new_byte_buffer_wrapper(smallbb); + dummySmallDevice = toolkit.createScreenCompatibleDeviceUsingBuffer(SMALLSIZE, SMALLSIZE, 1, 1, 0, 0, wrapped_smallbb); + + PropertyValue renderProps[] = new PropertyValue[3]; + renderProps[0] = new PropertyValue(); + renderProps[0].Name = "IsPrinter"; + renderProps[0].Value = new Boolean(true); + renderProps[1] = new PropertyValue(); + renderProps[1].Name = "RenderDevice"; + renderProps[1].Value = dummySmallDevice; + renderProps[2] = new PropertyValue(); + renderProps[2].Name = "View"; + renderProps[2].Value = new MyXController(); + + Log.i(TAG, "Document is" + (doc!=null ? " not" : "") + " null"); + t0 = System.currentTimeMillis(); + pageCount = renderable.getRendererCount(doc, renderProps); + t1 = System.currentTimeMillis(); + Log.i(TAG, "getRendererCount: " + pageCount + ", took " + ((t1-t0)-timingOverhead) + " ms"); + } + catch (Exception e) { + e.printStackTrace(System.err); + finish(); + } + return new Integer( 0 ); + } + + protected void onPostExecute(Integer result){ + int widthInPx = 120; + int heightInPx = 120; + ByteBuffer bb = renderPage( 0 , widthInPx , heightInPx); + Bitmap bm = Bitmap.createBitmap( widthInPx , heightInPx , Bitmap.Config.ARGB_8888); + bm.copyPixelsFromBuffer(bb); + File dir = file.getParentFile(); + File thumbnailFile = new File( dir , "." + file.getName().split("[.]")[0] + ".png"); + try { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + bm.compress(Bitmap.CompressFormat.PNG, 40, bytes); + thumbnailFile.createNewFile(); + FileOutputStream fo = new FileOutputStream( thumbnailFile ); + fo.write(bytes.toByteArray()); + } catch (IOException e) { + // TODO: handle exception + } + } + } + + class MyXController + implements XController + { + + XFrame frame; + XModel model; + + public void attachFrame(XFrame frame) + { + Log.i(TAG, "attachFrame"); + this.frame = frame; + } + + public boolean attachModel(XModel model) + { + Log.i(TAG, "attachModel"); + this.model = model; + return true; + } + + public boolean suspend(boolean doSuspend) + { + Log.i(TAG, "suspend"); + return false; + } + + public Object getViewData() + { + Log.i(TAG, "getViewData"); + return null; + } + + public void restoreViewData(Object data) + { + Log.i(TAG, "restoreViewData"); + } + + public XModel getModel() + { + Log.i(TAG, "getModel"); + return model; + } + + public XFrame getFrame() + { + Log.i(TAG, "getFrame"); + return frame; + } + + public void dispose() + { + Log.i(TAG, "dispose"); + } + + public void addEventListener(XEventListener listener) + { + Log.i(TAG, "addEventListener"); + } + + public void removeEventListener(XEventListener listener) + { + Log.i(TAG, "removeEventListener"); + } + } + + } } |