[Libreoffice-commits] core.git: android/source

Ximeng Zu uznomis at yahoo.com
Mon Aug 7 12:41:36 UTC 2017


 android/source/res/layout/calc_header_popup.xml                            |   90 ++++
 android/source/res/values/strings.xml                                      |   17 
 android/source/src/java/org/libreoffice/InvalidationHandler.java           |   10 
 android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java       |    5 
 android/source/src/java/org/libreoffice/canvas/AdjustLengthLine.java       |  105 +++++
 android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java |  113 ++++++
 android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java       |  181 +++++++---
 android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java       |    8 
 android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java   |   32 +
 9 files changed, 521 insertions(+), 40 deletions(-)

New commits:
commit f45cdbc9f3dd877a2ebda1e2718c59e83faf3c6a
Author: Ximeng Zu <uznomis at yahoo.com>
Date:   Wed Jul 12 09:20:56 2017 -0500

    [Android Viewer] Add header funcs to Calc
    
    Added insert/delete/hide/show/optimal width or height
    /adjust width or heigth  to Calc. These options
    show in a floating menu near the headers when the
    user taps on the headers. Also added selection on
    headers, i.e., user can drag on headers to select
    multiple columns/rows.
    
    Change-Id: I7e1994d1fa81d80c110def035c2c065e838b49ac
    Reviewed-on: https://gerrit.libreoffice.org/40684
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/android/source/res/layout/calc_header_popup.xml b/android/source/res/layout/calc_header_popup.xml
new file mode 100644
index 000000000000..8e563af27d0a
--- /dev/null
+++ b/android/source/res/layout/calc_header_popup.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/doorhanger_background_dark">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <Button
+                android:id="@+id/calc_header_popup_insert"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="?android:attr/buttonBarButtonStyle"
+                android:text="@string/calc_insert_before"/>
+
+            <Button
+                android:id="@+id/calc_header_popup_delete"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="?android:attr/buttonBarButtonStyle"
+                android:text="@string/calc_delete"/>
+
+            <Button
+                android:id="@+id/calc_header_popup_hide"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="?android:attr/buttonBarButtonStyle"
+                android:text="@string/calc_hide"/>
+
+            <Button
+                android:id="@+id/calc_header_popup_show"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="?android:attr/buttonBarButtonStyle"
+                android:text="@string/calc_show"/>
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <Button
+                android:id="@+id/calc_header_popup_optimal_length"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="?android:attr/buttonBarButtonStyle"
+                android:text="@string/calc_optimal_length"/>
+
+            <Button
+                android:id="@+id/calc_header_popup_adjust_length"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="?android:attr/buttonBarButtonStyle"
+                android:text="@string/calc_adjust_length"/>
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/calc_header_popup_optimal_length_dialog"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:visibility="gone">
+
+            <EditText
+                android:id="@+id/calc_header_popup_optimal_length_text"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:inputType="numberDecimal"
+                android:hint="@string/calc_optimal_length_default_text"/>
+
+            <Button
+                android:id="@+id/calc_header_popup_optimal_length_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text = "@string/calc_optimal_length_confirm"/>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/android/source/res/values/strings.xml b/android/source/res/values/strings.xml
index ad4d2699684a..04f1be3cc029 100644
--- a/android/source/res/values/strings.xml
+++ b/android/source/res/values/strings.xml
@@ -130,9 +130,26 @@
     <!-- Create New Document Dialog Strings -->
     <string name="create_new_document_title">Enter file name</string>
     <string name="action_create">CREATE</string>
+
+    <!-- Presentation Mode Strings -->
     <string name="action_presentation">Slide show</string>
     <string name="alert_copy_svg_slide_show_to_clipboard">Your Android device doesn\'t support in-app svg slideshow. We copied the slideshow link to clipboard. Please press home button, open a modern web browser, paste in the address bar, and go.</string>
     <string name="alert_copy_svg_slide_show_to_clipboard_dismiss">OK</string>
     <string name="slideshow_action_back">Back</string>
 
+    <!-- Calc Header Menu Strings -->
+    <string name="calc_insert_before">Insert</string>
+    <string name="calc_delete">Delete</string>
+    <string name="calc_hide">Hide</string>
+    <string name="calc_show">Show</string>
+    <string name="calc_optimal_length">Optimal Length</string>
+    <string name="calc_adjust_length">Adjust Length</string>
+    <string name="calc_adjust_height">Adjust Height</string>
+    <string name="calc_adjust_width">Adjust Width</string>
+    <string name="calc_optimal_height">Optimal Height</string>
+    <string name="calc_optimal_width">Optimal Width</string>
+    <string name="calc_optimal_length_confirm">OK</string>
+    <string name="calc_optimal_length_default_text">Enter Extra Length in 100th/mm</string>
+    <string name="calc_alert_double_click_optimal_length">Hint: Double tap on a header sets optimal width/height.</string>
+
 </resources>
diff --git a/android/source/src/java/org/libreoffice/InvalidationHandler.java b/android/source/src/java/org/libreoffice/InvalidationHandler.java
index e5fdf05b120f..92769bcd619c 100644
--- a/android/source/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/source/src/java/org/libreoffice/InvalidationHandler.java
@@ -94,11 +94,18 @@ public class InvalidationHandler implements Document.MessageCallback {
             case Document.CALLBACK_CELL_CURSOR:
                 invalidateCellCursor(payload);
                 break;
+            case Document.CALLBACK_INVALIDATE_HEADER:
+                invalidateHeader();
+                break;
             default:
                 Log.d(LOGTAG, "LOK_CALLBACK uncaught: " + messageID + " : " + payload);
         }
     }
 
+    private void invalidateHeader() {
+        LOKitShell.sendEvent(new LOEvent(LOEvent.UPDATE_CALC_HEADERS));
+    }
+
     private void invalidateCellCursor(String payload) {
         RectF cellCursorRect = convertPayloadToRectangle(payload);
 
@@ -378,6 +385,9 @@ public class InvalidationHandler implements Document.MessageCallback {
                 changeStateTo(OverlayState.TRANSITION);
             }
             mDocumentOverlay.changeSelections(Collections.EMPTY_LIST);
+            if (mContext.isSpreadsheet()) {
+                mDocumentOverlay.showHeaderSelection(null);
+            }
         } else {
             List<RectF> rectangles = convertPayloadToRectangles(payload);
             if (mState != OverlayState.SELECTION) {
diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index b16812f0bc97..6ae49935a5c2 100755
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -694,6 +694,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
 
     public void initializeCalcHeaders() {
         mCalcHeadersController = new CalcHeadersController(this, mLayerClient.getView());
+        mCalcHeadersController.setupHeaderPopupView();
         LOKitShell.getMainHandler().post(new Runnable() {
             @Override
             public void run() {
@@ -712,6 +713,10 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
         return mIsSpreadsheet;
     }
 
+    public void setDocumentChanged (boolean changed) {
+        isDocumentChanged = changed;
+    }
+
     private class DocumentPartClickListener implements android.widget.AdapterView.OnItemClickListener {
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
diff --git a/android/source/src/java/org/libreoffice/canvas/AdjustLengthLine.java b/android/source/src/java/org/libreoffice/canvas/AdjustLengthLine.java
new file mode 100644
index 000000000000..f0120bcbb5dc
--- /dev/null
+++ b/android/source/src/java/org/libreoffice/canvas/AdjustLengthLine.java
@@ -0,0 +1,105 @@
+package org.libreoffice.canvas;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.RectF;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.libreoffice.LOEvent;
+import org.libreoffice.LOKitShell;
+import org.libreoffice.LibreOfficeMainActivity;
+import org.libreoffice.overlay.CalcHeadersView;
+import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
+
+import static org.libreoffice.overlay.CalcHeadersView.addProperty;
+
+public class AdjustLengthLine extends CommonCanvasElement {
+
+    private static final float STROKE_WIDTH = 4f;
+    private static final float TOUCH_VICINITY_RADIUS = 24f;
+
+    private LibreOfficeMainActivity mContext;
+    private CalcHeadersView mCalcHeadersView;
+    private boolean mIsRow;
+    private PointF mScreenPosition;
+    private float mWidth;
+    private float mHeight;
+    private Paint mPaint;
+    private PointF mStartScreenPosition;
+    private int mIndex;
+
+    public AdjustLengthLine(LibreOfficeMainActivity context, CalcHeadersView view, boolean isRow, float width, float height) {
+        super();
+        mContext = context;
+        mCalcHeadersView = view;
+        mIsRow = isRow;
+        mWidth = width;
+        mHeight = height;
+        mPaint = new Paint();
+        mPaint.setColor(Color.BLACK);
+        mPaint.setStrokeWidth(STROKE_WIDTH);
+    }
+
+    @Override
+    public boolean onHitTest(float x, float y) {
+        if (mIsRow) {
+            return mScreenPosition.y - TOUCH_VICINITY_RADIUS < y &&
+                    y < mScreenPosition.y + TOUCH_VICINITY_RADIUS;
+        } else {
+            return mScreenPosition.x - TOUCH_VICINITY_RADIUS < x &&
+                    x < mScreenPosition.x + TOUCH_VICINITY_RADIUS;
+        }
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        if (mIsRow) {
+            canvas.drawLine(0f, mScreenPosition.y, mWidth, mScreenPosition.y, mPaint);
+        } else {
+            canvas.drawLine(mScreenPosition.x, 0f, mScreenPosition.x, mHeight, mPaint);
+        }
+    }
+
+    public void dragStart(PointF point) {
+    }
+
+    public void dragging(PointF point) {
+        mScreenPosition = point;
+    }
+
+    public void dragEnd(PointF point) {
+        ImmutableViewportMetrics viewportMetrics = mContext.getLayerClient().getViewportMetrics();
+        float zoom = viewportMetrics.zoomFactor;
+
+        PointF documentDistance = new PointF(pixelToTwip((point.x-mStartScreenPosition.x)/zoom, LOKitShell.getDpi(mContext)),
+                pixelToTwip((point.y-mStartScreenPosition.y)/zoom, LOKitShell.getDpi(mContext)));
+
+        try {
+            JSONObject rootJson = new JSONObject();
+            if (mIsRow) {
+                addProperty(rootJson, "Row", "long", String.valueOf(mIndex));
+                addProperty(rootJson, "Height", "unsigned short", String.valueOf(documentDistance.y > 0 ? documentDistance.y : 0));
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:RowHeight", rootJson.toString()));
+            } else {
+                addProperty(rootJson, "Column", "long", String.valueOf(mIndex));
+                addProperty(rootJson, "Width", "unsigned short", String.valueOf(documentDistance.x > 0 ? documentDistance.x : 0));
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:ColumnWidth", rootJson.toString()));
+            }
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void setScreenRect(RectF position) {
+        mScreenPosition = new PointF(position.right, position.bottom);
+        mStartScreenPosition = new PointF(position.left, position.top);
+        mIndex = 1 + mCalcHeadersView.getIndexFromPointOfTouch(new PointF(position.centerX(), position.centerY()));
+    }
+
+    private static float pixelToTwip(float input, float dpi) {
+        return (input / dpi) * 1440.0f;
+    }
+}
diff --git a/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java b/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java
index ced93381f0ce..954277c20ed2 100644
--- a/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java
+++ b/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java
@@ -1,8 +1,18 @@
 package org.libreoffice.overlay;
 
+import android.content.Context;
+import android.graphics.PointF;
 import android.graphics.RectF;
+import android.graphics.drawable.ColorDrawable;
+import android.support.design.widget.Snackbar;
 import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.PopupWindow;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -39,10 +49,113 @@ public class CalcHeadersController {
             @Override
             public void onClick(View v) {
                 LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SelectAll"));
+                if (mCalcColumnHeadersView == null) return;
+                mCalcColumnHeadersView.showHeaderPopup(new PointF());
             }
         });
     }
 
+    public void setupHeaderPopupView() {
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        String[] rowOrColumn = {"Row","Column"};
+        CalcHeadersView[] headersViews= {mCalcRowHeadersView, mCalcColumnHeadersView};
+        for (int i = 0; i < rowOrColumn.length; i++) {
+            // create popup window
+            final String tempName = rowOrColumn[i];
+            final CalcHeadersView tempView = headersViews[i];
+            final View headerPopupView = inflater.inflate(R.layout.calc_header_popup, null);
+            final PopupWindow popupWindow = new PopupWindow(headerPopupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+            popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
+                @Override
+                public void onDismiss() {
+                    headerPopupView.findViewById(R.id.calc_header_popup_optimal_length_dialog).setVisibility(View.GONE);
+                    popupWindow.setFocusable(false);
+                }
+            });
+            popupWindow.setOutsideTouchable(true);
+            popupWindow.setBackgroundDrawable(new ColorDrawable());
+            popupWindow.setAnimationStyle(android.R.style.Animation_Dialog);
+            tempView.setHeaderPopupWindow(popupWindow);
+            // set up child views in the popup window
+            headerPopupView.findViewById(R.id.calc_header_popup_insert).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Insert"+tempName+"s"));
+                    tempView.dismissPopupWindow();
+                    mContext.setDocumentChanged(true);
+                }
+            });
+            headerPopupView.findViewById(R.id.calc_header_popup_delete).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Delete"+tempName+"s"));
+                    tempView.dismissPopupWindow();
+                    mContext.setDocumentChanged(true);
+                }
+            });
+            headerPopupView.findViewById(R.id.calc_header_popup_hide).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Hide"+tempName));
+                    tempView.dismissPopupWindow();
+                    mContext.setDocumentChanged(true);
+                }
+            });
+            headerPopupView.findViewById(R.id.calc_header_popup_show).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Show"+tempName));
+                    tempView.dismissPopupWindow();
+                    mContext.setDocumentChanged(true);
+                }
+            });
+            headerPopupView.findViewById(R.id.calc_header_popup_optimal_length).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    View view = headerPopupView.findViewById(R.id.calc_header_popup_optimal_length_dialog);
+                    if (view.getVisibility() == View.VISIBLE) {
+                        view.setVisibility(View.GONE);
+                        popupWindow.setFocusable(false);
+                        popupWindow.update();
+                    } else {
+                        popupWindow.dismiss();
+                        view.setVisibility(View.VISIBLE);
+                        popupWindow.setFocusable(true);
+                        popupWindow.showAtLocation(tempView, Gravity.CENTER, 0, 0);
+                        LOKitShell.getMainHandler().post(new Runnable() {
+                            @Override
+                            public void run() {
+                                Snackbar.make(tempView, R.string.calc_alert_double_click_optimal_length, Snackbar.LENGTH_LONG).show();
+                            }
+                        });
+                    }
+                }
+            });
+            headerPopupView.findViewById(R.id.calc_header_popup_optimal_length_button).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    String text = ((EditText)headerPopupView.findViewById(R.id.calc_header_popup_optimal_length_text)).getText().toString();
+                    tempView.sendOptimalLengthRequest(text);
+                    tempView.dismissPopupWindow();
+                    mContext.setDocumentChanged(true);
+                }
+            });
+            headerPopupView.findViewById(R.id.calc_header_popup_adjust_length).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mContext.getDocumentOverlay().showAdjustLengthLine(tempView == mCalcRowHeadersView, tempView);
+                    tempView.dismissPopupWindow();
+                    mContext.setDocumentChanged(true);
+                }
+            });
+            ((Button)headerPopupView.findViewById(R.id.calc_header_popup_adjust_length))
+                    .setText(tempView == mCalcRowHeadersView ? R.string.calc_adjust_height : R.string.calc_adjust_width);
+            ((Button)headerPopupView.findViewById(R.id.calc_header_popup_optimal_length))
+                    .setText(tempView == mCalcRowHeadersView ? R.string.calc_optimal_height : R.string.calc_optimal_width);
+
+        }
+    }
+
     public void setHeaders(String headers) {
         HeaderInfo parsedHeaders = parseHeaderInfo(headers);
         if (parsedHeaders != null) {
diff --git a/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java b/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java
index 7485b6c0cb6d..bc74bab04f77 100644
--- a/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java
+++ b/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java
@@ -4,22 +4,27 @@ import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.PointF;
 import android.graphics.RectF;
+import android.support.v4.view.GestureDetectorCompat;
 import android.util.AttributeSet;
+import android.view.GestureDetector.SimpleOnGestureListener;
 import android.view.MotionEvent;
 import android.view.View;
+import android.widget.PopupWindow;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.libreoffice.LOEvent;
 import org.libreoffice.LOKitShell;
+import org.libreoffice.LibreOfficeMainActivity;
 import org.libreoffice.canvas.CalcHeaderCell;
+import org.libreoffice.kit.Document;
 import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
 import org.mozilla.gecko.gfx.LayerView;
 
 import java.util.ArrayList;
 import java.util.Collections;
 
-public class CalcHeadersView extends View implements View.OnTouchListener {
+public class CalcHeadersView extends View {
     private static final String LOGTAG = CalcHeadersView.class.getSimpleName();
 
     private boolean mInitialized;
@@ -28,8 +33,10 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
     private ArrayList<String> mLabels;
     private ArrayList<Float> mDimens;
     private RectF mCellCursorRect;
-    private PointF pointOfTouch;
     private boolean mPendingRowOrColumnSelectionToShowUp;
+    private GestureDetectorCompat mDetector;
+    private PopupWindow mPopupWindow;
+    private int mPrevScrollIndex = -1;
 
     public CalcHeadersView(Context context) {
         super(context);
@@ -45,10 +52,26 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
 
     public void initialize(LayerView layerView, boolean isRow) {
         if (!mInitialized) {
-            setOnTouchListener(this);
             mLayerView = layerView;
             mIsRow = isRow;
 
+            LOKitShell.getMainHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    mDetector = new GestureDetectorCompat(getContext(), new HeaderGestureListener());
+                }
+            });
+
+            setOnTouchListener(new View.OnTouchListener() {
+                @Override
+                public boolean onTouch(View v, MotionEvent event) {
+                    if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+                        mPrevScrollIndex = -1;  // clear mPrevScrollIndex to default
+                    }
+                    return mDetector.onTouchEvent(event);
+                }
+            });
+
             mInitialized = true;
         }
     }
@@ -70,6 +93,7 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
         boolean inRangeOfVisibleHeaders = false; // a helper variable for skipping unnecessary onDraw()'s
         float top,bottom,left,right;
         for (int i = 1; i < mLabels.size(); i++) {
+            if (mDimens.get(i).equals(mDimens.get(i-1))) continue;
             if (mIsRow) {
                 top = -origin.y + zoom*mDimens.get(i-1);
                 bottom = -origin.y + zoom*mDimens.get(i);
@@ -106,46 +130,19 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
     }
 
     /**
-     * Handle the triggered touch event.
-     */
-    @Override
-    public boolean onTouch(View view, MotionEvent event) {
-        PointF point = new PointF(event.getX(), event.getY());
-        switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN:
-                pointOfTouch = point;
-                return true;
-            case MotionEvent.ACTION_UP:
-                if (pointOfTouch != null) {
-                    highlightRowOrColumn();
-                }
-        }
-        return false;
-    }
-
-    /**
      * Handle a single tap event on a header cell.
      * Selects whole row/column.
      */
-    private void highlightRowOrColumn() {
-        int searchedIndex, index;
-        ImmutableViewportMetrics metrics = mLayerView.getViewportMetrics();
-        float zoom = metrics.getZoomFactor();
-        PointF origin = metrics.getOrigin();
-        if (mIsRow) {
-            searchedIndex = Collections.binarySearch(mDimens, (pointOfTouch.y+origin.y)/zoom);
-        } else {
-            searchedIndex = Collections.binarySearch(mDimens, (pointOfTouch.x+origin.x)/zoom);
-        }
-        // converting searched index to real index on headers
-        if (searchedIndex < 0) {
-            index = - searchedIndex - 2;
-        } else {
-            index = searchedIndex;
-        }
+    private void highlightRowOrColumn(PointF point, boolean shift) {
+        int index = getIndexFromPointOfTouch(point);
         try {
             JSONObject rootJson = new JSONObject();
-            addProperty(rootJson, "Modifier", "unsigned short", "0");
+            if (shift) {
+                addProperty(rootJson, "Modifier", "unsigned short",
+                        String.valueOf(Document.KEYBOARD_MODIFIER_SHIFT));
+            } else {
+                addProperty(rootJson, "Modifier", "unsigned short", "0");
+            }
             if (mIsRow) {
                 addProperty(rootJson, "Row", "unsigned short", String.valueOf(index));
                 LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SelectRow", rootJson.toString()));
@@ -161,7 +158,25 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
         // The second will override the first on headers which is not wanted.
         // setPendingRowOrColumnSelectionToShowUp(true) will skip the second call.
         setPendingRowOrColumnSelectionToShowUp(true);
-        pointOfTouch = null;
+    }
+
+    public int getIndexFromPointOfTouch(PointF point) {
+        int searchedIndex, index;
+        ImmutableViewportMetrics metrics = mLayerView.getViewportMetrics();
+        float zoom = metrics.getZoomFactor();
+        PointF origin = metrics.getOrigin();
+        if (mIsRow) {
+            searchedIndex = Collections.binarySearch(mDimens, (point.y+origin.y)/zoom);
+        } else {
+            searchedIndex = Collections.binarySearch(mDimens, (point.x+origin.x)/zoom);
+        }
+        // converting searched index to real index on headers
+        if (searchedIndex < 0) {
+            index = - searchedIndex - 2;
+        } else {
+            index = searchedIndex;
+        }
+        return index;
     }
 
     public void setPendingRowOrColumnSelectionToShowUp(boolean b) {
@@ -172,7 +187,7 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
         return mPendingRowOrColumnSelectionToShowUp;
     }
 
-    private void addProperty(JSONObject json, String parentValue, String type, String value) throws JSONException {
+    public static void addProperty(JSONObject json, String parentValue, String type, String value) throws JSONException {
         JSONObject child = new JSONObject();
         child.put("type", type);
         child.put("value", value);
@@ -187,4 +202,90 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
     public void setHeaderSelection(RectF cellCursorRect) {
         mCellCursorRect = cellCursorRect;
     }
+
+    public void showHeaderPopup(PointF point) {
+        if (mPopupWindow == null ||
+                !LibreOfficeMainActivity.isExperimentalMode()) return;
+        if (mIsRow) {
+            mPopupWindow.showAsDropDown(this, getWidth()*3/2, -getHeight()+(int)point.y);
+        } else {
+            mPopupWindow.showAsDropDown(this, (int)point.x, getHeight()/2);
+        }
+    }
+
+    public void dismissPopupWindow() {
+        if (mPopupWindow == null) return;
+        mPopupWindow.dismiss();
+    }
+
+    public void setHeaderPopupWindow(PopupWindow popupWindow) {
+        if (mPopupWindow != null) return;
+        mPopupWindow = popupWindow;
+    }
+
+    public void sendOptimalLengthRequest(String text) {
+        JSONObject rootJson = new JSONObject();
+        if (mIsRow) {
+            try {
+                addProperty(rootJson, "aExtraHeight", "unsigned short", text);
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SetOptimalRowHeight", rootJson.toString()));
+            } catch (JSONException ex) {
+                ex.printStackTrace();
+            }
+        } else {
+            try {
+                addProperty(rootJson, "aExtraWidth", "unsigned short", text);
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SetOptimalColumnWidth", rootJson.toString()));
+            } catch (JSONException ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    private class HeaderGestureListener extends SimpleOnGestureListener {
+
+        @Override
+        public boolean onDown(MotionEvent e) {
+            return true;
+        }
+
+        @Override
+        public boolean onSingleTapConfirmed(MotionEvent e) {
+            PointF pointOfTouch = new PointF(e.getX(), e.getY());
+            highlightRowOrColumn(pointOfTouch, false);
+            showHeaderPopup(pointOfTouch);
+            return true;
+        }
+
+        @Override
+        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+            PointF point2 = new PointF(e2.getX(), e2.getY());
+            if (mPrevScrollIndex != getIndexFromPointOfTouch(point2)) {
+                mPrevScrollIndex = getIndexFromPointOfTouch(point2);
+                highlightRowOrColumn(point2, true);
+                dismissPopupWindow();
+                showHeaderPopup(point2);
+            }
+            return true;
+        }
+
+        @Override
+        public boolean onDoubleTap(MotionEvent e) {
+            PointF pointOfTouch = new PointF(e.getX(), e.getY());
+            highlightRowOrColumn(pointOfTouch, false);
+            if (mIsRow) {
+                JSONObject rootJson = new JSONObject();
+                try {
+                    addProperty(rootJson, "aExtraHeight", "unsigned short", String.valueOf(0));
+                } catch (JSONException ex) {
+                    ex.printStackTrace();
+                }
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND,".uno:SetOptimalRowHeight", rootJson.toString()));
+            } else {
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND,".uno:SetOptimalColumnWidthDirect"));
+            }
+            showHeaderPopup(pointOfTouch);
+            return true;
+        }
+    }
 }
diff --git a/android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java b/android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java
index 47669797fb1c..127972d998d4 100644
--- a/android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java
+++ b/android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java
@@ -258,6 +258,14 @@ public class DocumentOverlay {
         });
     }
 
+    public void showAdjustLengthLine(final boolean isRow, final CalcHeadersView view) {
+        LOKitShell.getMainHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                mDocumentOverlayView.showAdjustLengthLine(isRow, view);
+            }
+        });
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java b/android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java
index d5cfcaa3edc3..aed4432f0ad8 100644
--- a/android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java
+++ b/android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java
@@ -19,6 +19,7 @@ import android.view.MotionEvent;
 import android.view.View;
 
 import org.libreoffice.LibreOfficeMainActivity;
+import org.libreoffice.canvas.AdjustLengthLine;
 import org.libreoffice.canvas.CalcSelectionBox;
 import org.libreoffice.canvas.Cursor;
 import org.libreoffice.canvas.GraphicSelection;
@@ -72,6 +73,8 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
 
     private CalcSelectionBox mCalcSelectionBox;
     private boolean mCalcSelectionBoxDragging;
+    private AdjustLengthLine mAdjustLengthLine;
+    private boolean mAdjustLengthLineDragging;
 
     public DocumentOverlayView(Context context) {
         super(context);
@@ -234,6 +237,10 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
         if (mCalcHeadersController != null) {
             mCalcHeadersController.showHeaders();
         }
+
+        if (mAdjustLengthLine != null) {
+            mAdjustLengthLine.draw(canvas);
+        }
     }
 
     /**
@@ -360,6 +367,10 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
         PointF point = new PointF(event.getX(), event.getY());
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN: {
+                if (mAdjustLengthLine != null && !mAdjustLengthLine.contains(point.x, point.y)) {
+                    mAdjustLengthLine.setVisible(false);
+                    invalidate();
+                }
                 if (mGraphicSelection.isVisible()) {
                     // Check if inside graphic selection was hit
                     if (mGraphicSelection.contains(point.x, point.y)) {
@@ -387,6 +398,11 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
                         mCalcSelectionBox.dragStart(point);
                         mCalcSelectionBoxDragging = true;
                         return true;
+                    } else if (mAdjustLengthLine != null &&
+                            mAdjustLengthLine.contains(point.x, point.y)) {
+                        mAdjustLengthLine.dragStart(point);
+                        mAdjustLengthLineDragging = true;
+                        return true;
                     }
                 }
             }
@@ -402,6 +418,10 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
                 } else if (mCalcSelectionBoxDragging) {
                     mCalcSelectionBox.dragEnd(point);
                     mCalcSelectionBoxDragging = false;
+                } else if (mAdjustLengthLineDragging) {
+                    mAdjustLengthLine.dragEnd(point);
+                    mAdjustLengthLineDragging = false;
+                    invalidate();
                 }
             }
             case MotionEvent.ACTION_MOVE: {
@@ -413,6 +433,9 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
                     mDragHandle.dragging(point);
                 } else if (mCalcSelectionBoxDragging) {
                     mCalcSelectionBox.dragging(point);
+                } else if (mAdjustLengthLineDragging) {
+                    mAdjustLengthLine.dragging(point);
+                    invalidate();
                 }
             }
         }
@@ -509,6 +532,15 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
         if (mCalcHeadersController == null) return;
         mCalcHeadersController.showHeaderSelection(rect);
     }
+
+    public void showAdjustLengthLine(boolean isRow, final CalcHeadersView view) {
+        mAdjustLengthLine = new AdjustLengthLine((LibreOfficeMainActivity) getContext(), view, isRow, getWidth(), getHeight());
+        ImmutableViewportMetrics metrics = mLayerView.getViewportMetrics();
+        RectF position = convertToScreen(mCalcSelectionBox.mDocumentPosition, metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
+        mAdjustLengthLine.setScreenRect(position);
+        mAdjustLengthLine.setVisible(true);
+        invalidate();
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list