diff options
author | Ximeng Zu <uznomis@yahoo.com> | 2017-07-12 09:20:56 -0500 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2017-08-07 14:41:02 +0200 |
commit | f45cdbc9f3dd877a2ebda1e2718c59e83faf3c6a (patch) | |
tree | 8b0e7d388883cc5a0a74dc2bf30bf7ca31dbd5e1 /android | |
parent | 3e493d337819204ca9c7302efbd7b34c282956a2 (diff) |
[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@libreoffice.org>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'android')
9 files changed, 521 insertions, 40 deletions
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: */ |