[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>
This commit is contained in:
committed by
Tomaž Vajngerl
parent
3e493d3378
commit
f45cdbc9f3
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
@@ -105,47 +129,20 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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: */
|
||||
|
||||
Reference in New Issue
Block a user