1 package org
.libreoffice
.overlay
;
3 import android
.content
.Context
;
4 import android
.graphics
.PointF
;
5 import android
.graphics
.RectF
;
6 import android
.graphics
.drawable
.ColorDrawable
;
7 import com
.google
.android
.material
.snackbar
.Snackbar
;
8 import android
.util
.Log
;
9 import android
.view
.KeyEvent
;
10 import android
.view
.Gravity
;
11 import android
.view
.LayoutInflater
;
12 import android
.view
.View
;
13 import android
.view
.ViewGroup
.LayoutParams
;
14 import android
.view
.inputmethod
.EditorInfo
;
15 import android
.widget
.EditText
;
16 import android
.widget
.Button
;
17 import android
.widget
.PopupWindow
;
18 import android
.widget
.TextView
;
20 import org
.json
.JSONArray
;
21 import org
.json
.JSONException
;
22 import org
.json
.JSONObject
;
23 import org
.libreoffice
.LOEvent
;
24 import org
.libreoffice
.LOKitShell
;
25 import org
.libreoffice
.LibreOfficeMainActivity
;
26 import org
.libreoffice
.R
;
27 import org
.mozilla
.gecko
.gfx
.LayerView
;
29 import java
.math
.BigDecimal
;
30 import java
.util
.ArrayList
;
32 import static org
.libreoffice
.SearchController
.addProperty
;
34 public class CalcHeadersController
{
35 private static final String LOGTAG
= CalcHeadersController
.class.getSimpleName();
37 private final CalcHeadersView mCalcRowHeadersView
;
38 private final CalcHeadersView mCalcColumnHeadersView
;
40 private LibreOfficeMainActivity mContext
;
42 public CalcHeadersController(LibreOfficeMainActivity context
, final LayerView layerView
) {
44 mContext
.getDocumentOverlay().setCalcHeadersController(this);
45 mCalcRowHeadersView
= context
.findViewById(R
.id
.calc_header_row
);
46 mCalcColumnHeadersView
= context
.findViewById(R
.id
.calc_header_column
);
47 if (mCalcColumnHeadersView
== null || mCalcRowHeadersView
== null) {
48 Log
.e(LOGTAG
, "Failed to initialize Calc headers - View is null");
50 mCalcRowHeadersView
.initialize(layerView
, true);
51 mCalcColumnHeadersView
.initialize(layerView
, false);
53 LOKitShell
.sendEvent(new LOEvent(LOEvent
.UPDATE_CALC_HEADERS
));
54 context
.findViewById(R
.id
.calc_header_top_left
).setOnClickListener(new View
.OnClickListener() {
56 public void onClick(View v
) {
57 LOKitShell
.sendEvent(new LOEvent(LOEvent
.UNO_COMMAND
, ".uno:SelectAll"));
58 if (mCalcColumnHeadersView
== null) return;
59 mCalcColumnHeadersView
.showHeaderPopup(new PointF());
62 ((EditText
)context
.findViewById(R
.id
.calc_address
)).setOnEditorActionListener(new TextView
.OnEditorActionListener() {
64 public boolean onEditorAction(TextView v
, int actionId
, KeyEvent event
) {
65 if (actionId
== EditorInfo
.IME_ACTION_DONE
|| actionId
== EditorInfo
.IME_ACTION_GO
) {
66 String text
= v
.getText().toString();
67 JSONObject rootJson
= new JSONObject();
69 addProperty(rootJson
, "ToPoint", "string", text
);
70 } catch (JSONException e
) {
73 LOKitShell
.sendEvent(new LOEvent(LOEvent
.UNO_COMMAND
, ".uno:GoToCell", rootJson
.toString()));
74 mContext
.hideSoftKeyboard();
75 layerView
.requestFocus();
80 ((EditText
)context
.findViewById(R
.id
.calc_formula
)).setOnEditorActionListener(new TextView
.OnEditorActionListener() {
82 public boolean onEditorAction(TextView v
, int actionId
, KeyEvent event
) {
83 if (actionId
== EditorInfo
.IME_ACTION_DONE
|| actionId
== EditorInfo
.IME_ACTION_GO
) {
84 String text
= v
.getText().toString();
85 JSONObject rootJson
= new JSONObject();
87 addProperty(rootJson
, "StringName", "string", text
);
88 addProperty(rootJson
, "DontCommit", "boolean", String
.valueOf(false));
89 } catch (JSONException e
) {
92 LOKitShell
.sendEvent(new LOEvent(LOEvent
.UNO_COMMAND
, ".uno:EnterString", rootJson
.toString()));
93 mContext
.hideSoftKeyboard();
94 layerView
.requestFocus();
95 mContext
.setDocumentChanged(true);
100 // manually select A1 for address bar and formula bar to update when calc first opens
101 JSONObject rootJson
= new JSONObject();
103 addProperty(rootJson
, "ToPoint", "string", "A1");
104 } catch (JSONException e
) {
107 LOKitShell
.sendEvent(new LOEvent(LOEvent
.UNO_COMMAND
, ".uno:GoToCell", rootJson
.toString()));
110 public void setupHeaderPopupView() {
111 LayoutInflater inflater
= (LayoutInflater
) mContext
.getSystemService(Context
.LAYOUT_INFLATER_SERVICE
);
112 String
[] rowOrColumn
= {"Row","Column"};
113 CalcHeadersView
[] headersViews
= {mCalcRowHeadersView
, mCalcColumnHeadersView
};
114 for (int i
= 0; i
< rowOrColumn
.length
; i
++) {
115 // create popup window
116 final String tempName
= rowOrColumn
[i
];
117 final CalcHeadersView tempView
= headersViews
[i
];
118 final View headerPopupView
= inflater
.inflate(R
.layout
.calc_header_popup
, null);
119 final PopupWindow popupWindow
= new PopupWindow(headerPopupView
, LayoutParams
.WRAP_CONTENT
, LayoutParams
.WRAP_CONTENT
);
120 popupWindow
.setOnDismissListener(new PopupWindow
.OnDismissListener() {
122 public void onDismiss() {
123 headerPopupView
.findViewById(R
.id
.calc_header_popup_optimal_length_dialog
).setVisibility(View
.GONE
);
124 popupWindow
.setFocusable(false);
127 popupWindow
.setOutsideTouchable(true);
128 popupWindow
.setBackgroundDrawable(new ColorDrawable());
129 popupWindow
.setAnimationStyle(android
.R
.style
.Animation_Dialog
);
130 tempView
.setHeaderPopupWindow(popupWindow
);
131 // set up child views in the popup window
132 headerPopupView
.findViewById(R
.id
.calc_header_popup_insert
).setOnClickListener(new View
.OnClickListener() {
134 public void onClick(View v
) {
135 LOKitShell
.sendEvent(new LOEvent(LOEvent
.UNO_COMMAND
, ".uno:Insert"+tempName
+"s"));
136 tempView
.dismissPopupWindow();
137 mContext
.setDocumentChanged(true);
140 headerPopupView
.findViewById(R
.id
.calc_header_popup_delete
).setOnClickListener(new View
.OnClickListener() {
142 public void onClick(View v
) {
143 LOKitShell
.sendEvent(new LOEvent(LOEvent
.UNO_COMMAND
, ".uno:Delete"+tempName
+"s"));
144 tempView
.dismissPopupWindow();
145 mContext
.setDocumentChanged(true);
148 headerPopupView
.findViewById(R
.id
.calc_header_popup_hide
).setOnClickListener(new View
.OnClickListener() {
150 public void onClick(View v
) {
151 LOKitShell
.sendEvent(new LOEvent(LOEvent
.UNO_COMMAND
, ".uno:Hide"+tempName
));
152 tempView
.dismissPopupWindow();
153 mContext
.setDocumentChanged(true);
156 headerPopupView
.findViewById(R
.id
.calc_header_popup_show
).setOnClickListener(new View
.OnClickListener() {
158 public void onClick(View v
) {
159 LOKitShell
.sendEvent(new LOEvent(LOEvent
.UNO_COMMAND
, ".uno:Show"+tempName
));
160 tempView
.dismissPopupWindow();
161 mContext
.setDocumentChanged(true);
164 headerPopupView
.findViewById(R
.id
.calc_header_popup_optimal_length
).setOnClickListener(new View
.OnClickListener() {
166 public void onClick(View v
) {
167 View view
= headerPopupView
.findViewById(R
.id
.calc_header_popup_optimal_length_dialog
);
168 if (view
.getVisibility() == View
.VISIBLE
) {
169 view
.setVisibility(View
.GONE
);
170 popupWindow
.setFocusable(false);
171 popupWindow
.update();
173 popupWindow
.dismiss();
174 view
.setVisibility(View
.VISIBLE
);
175 popupWindow
.setFocusable(true);
176 popupWindow
.showAtLocation(tempView
, Gravity
.CENTER
, 0, 0);
177 LOKitShell
.getMainHandler().post(new Runnable() {
180 Snackbar
.make(tempView
, R
.string
.calc_alert_double_click_optimal_length
, Snackbar
.LENGTH_LONG
).show();
186 headerPopupView
.findViewById(R
.id
.calc_header_popup_optimal_length_button
).setOnClickListener(new View
.OnClickListener() {
188 public void onClick(View v
) {
189 String text
= ((EditText
)headerPopupView
.findViewById(R
.id
.calc_header_popup_optimal_length_text
)).getText().toString();
190 tempView
.sendOptimalLengthRequest(text
);
191 tempView
.dismissPopupWindow();
192 mContext
.setDocumentChanged(true);
195 headerPopupView
.findViewById(R
.id
.calc_header_popup_adjust_length
).setOnClickListener(new View
.OnClickListener() {
197 public void onClick(View v
) {
198 mContext
.getDocumentOverlay().showAdjustLengthLine(tempView
== mCalcRowHeadersView
, tempView
);
199 tempView
.dismissPopupWindow();
200 mContext
.setDocumentChanged(true);
203 ((Button
)headerPopupView
.findViewById(R
.id
.calc_header_popup_adjust_length
))
204 .setText(tempView
== mCalcRowHeadersView ? R
.string
.calc_adjust_height
: R
.string
.calc_adjust_width
);
205 ((Button
)headerPopupView
.findViewById(R
.id
.calc_header_popup_optimal_length
))
206 .setText(tempView
== mCalcRowHeadersView ? R
.string
.calc_optimal_height
: R
.string
.calc_optimal_width
);
211 public void setHeaders(String headers
) {
212 HeaderInfo parsedHeaders
= parseHeaderInfo(headers
);
213 if (parsedHeaders
!= null) {
214 mCalcRowHeadersView
.setHeaders(parsedHeaders
.rowLabels
, parsedHeaders
.rowDimens
);
215 mCalcColumnHeadersView
.setHeaders(parsedHeaders
.columnLabels
, parsedHeaders
.columnDimens
);
218 Log
.e(LOGTAG
, "Parse header info JSON failed.");
222 public void showHeaders() {
223 LOKitShell
.getMainHandler().post(new Runnable() {
226 mCalcColumnHeadersView
.invalidate();
227 mCalcRowHeadersView
.invalidate();
232 private HeaderInfo
parseHeaderInfo(String headers
) {
233 HeaderInfo headerInfo
= new HeaderInfo();
235 JSONObject collectiveResult
= new JSONObject(headers
);
236 JSONArray rowResult
= collectiveResult
.getJSONArray("rows");
237 for (int i
= 0; i
< rowResult
.length(); i
++) {
238 headerInfo
.rowLabels
.add(rowResult
.getJSONObject(i
).getString("text"));
239 headerInfo
.rowDimens
.add(BigDecimal
.valueOf(rowResult
.getJSONObject(i
).getLong("size")).floatValue());
241 JSONArray columnResult
= collectiveResult
.getJSONArray("columns");
242 for (int i
= 0; i
< columnResult
.length(); i
++) {
243 headerInfo
.columnLabels
.add(columnResult
.getJSONObject(i
).getString("text"));
244 headerInfo
.columnDimens
.add(BigDecimal
.valueOf(columnResult
.getJSONObject(i
).getLong("size")).floatValue());
247 } catch (JSONException e
) {
253 public void showHeaderSelection(RectF cellCursorRect
) {
254 mCalcRowHeadersView
.setHeaderSelection(cellCursorRect
);
255 mCalcColumnHeadersView
.setHeaderSelection(cellCursorRect
);
259 public void setPendingRowOrColumnSelectionToShowUp(boolean b
) {
260 mCalcRowHeadersView
.setPendingRowOrColumnSelectionToShowUp(b
);
261 mCalcColumnHeadersView
.setPendingRowOrColumnSelectionToShowUp(b
);
264 public boolean pendingRowOrColumnSelectionToShowUp() {
265 return mCalcColumnHeadersView
.pendingRowOrColumnSelectionToShowUp()
266 || mCalcRowHeadersView
.pendingRowOrColumnSelectionToShowUp();
269 private class HeaderInfo
{
270 ArrayList
<String
> rowLabels
;
271 ArrayList
<Float
> rowDimens
;
272 ArrayList
<String
> columnLabels
;
273 ArrayList
<Float
> columnDimens
;
274 private HeaderInfo() {
275 rowLabels
= new ArrayList
<String
>();
276 rowDimens
= new ArrayList
<Float
>();
277 columnDimens
= new ArrayList
<Float
>();
278 columnLabels
= new ArrayList
<String
>();