/* @file SketchWindow.java
*
* @author marco corvi
* @date jan 2013
*
* @brief TopoDroid main 3d sketch activity
* --------------------------------------------------------
* Copyright This sowftare is distributed under GPL-3.0 or later
* See the file COPYING.
* --------------------------------------------------------
*/
package com.topodroid.DistoX;
import android.app.Activity;
import android.content.Context;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.content.pm.PackageManager;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.PointF;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.SubMenu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.KeyEvent;
// for FRAGMENT
import android.view.ViewGroup;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.Button;
import android.widget.ZoomControls;
import android.widget.ZoomButton;
import android.widget.ZoomButtonsController;
import android.widget.ZoomButtonsController.OnZoomListener;
import android.widget.Toast;
import android.widget.ListView;
import android.widget.ArrayAdapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.hardware.SensorManager;
import java.io.File;
import java.io.FileWriter;
// import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.util.List;
import java.util.ArrayList;
// import java.util.Locale;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.util.Log;
/**
*/
public class SketchWindow extends ItemDrawer
implements View.OnTouchListener
, View.OnClickListener
, OnItemClickListener
// , View.OnLongClickListener
// , DrawingPointPickerDialog.OnPointSelectedListener FIXME
// , DrawingLinePickerDialog.OnLineSelectedListener
// , DrawingAreaPickerDialog.OnAreaSelectedListener
// , OnZoomListener
, ILabelAdder
, ILister
, IBearingAndClino
, IExporter
{
static final String TAG = "DistoX";
private TopoDroidApp mApp;
private DataDownloader mDataDownloader;
private Sketch3dInfo mInfo;
private SketchPainter mPainter;
private SketchDrawingSurface mSketchSurface;
private DrawingLinePath mCurrentLinePath;
// private DrawingAreaPath mCurrentAreaPath;
private static final long mType = PlotInfo.PLOT_SKETCH_3D;
// private boolean canRedo;
private DistoXNum mNum;
private float mDecl;
private int mPointCnt; // counter of points in the currently drawing line
// private boolean mAllSymbols; // whether the library has all the symbols of the plot
// private boolean mDoMakeSurface; // whether a surface can be safely made
// private int mSectionType; // current section type
// private boolean mIsInSection; // whether the user is drawing a section curve
// private Button selectBtn;
private Button[] mButton1; // primary: draw edit select refs surface download note info one step ( shot join )
private Button[] mButton2; // draw: draw edit select undo redo symbol
private Button[] mButton3; // edit draw edit select refineC refineS cut stretch extrude
private Button[] mButton4; // select draw edit select next prev cutP refineP
HorizontalButtonView mButtonView1;
HorizontalButtonView mButtonView2;
HorizontalButtonView mButtonView3;
HorizontalButtonView mButtonView4;
private int mNrButton1 = 7; // main-primary
private int mNrButton2 = 4; // draw
private int mNrButton3 = 6; // edit
private int mNrButton4 = 5; // select
HorizontalListView mListView;
ListView mMenu;
Button mImage;
// HOVER
// MyMenuAdapter mMenuAdapter;
ArrayAdapter< String > mMenuAdapter;
boolean onMenu;
private static int izons[] = {
R.drawable.iz_move, // 0
R.drawable.iz_edit, // 1
R.drawable.iz_contour,
R.drawable.iz_select,
R.drawable.iz_one, // 4
R.drawable.iz_mode, // 5
R.drawable.iz_plan, //
R.drawable.iz_download, //
R.drawable.iz_note,
R.drawable.iz_info, // 9
R.drawable.iz_undo, // 10<--
R.drawable.iz_redo,
R.drawable.iz_list, // 12
R.drawable.iz_refinet, // 13
R.drawable.iz_refinec, // 14
R.drawable.iz_refines,
R.drawable.iz_cut,
R.drawable.iz_stretch, // 16
R.drawable.iz_back, // 18
R.drawable.iz_forw,
R.drawable.iz_refinep,
R.drawable.iz_note // 21 Point: delete(cut), Leg: step
};
private static int menus[] = {
R.string.menu_export, // 21 <-- menus
R.string.menu_palette,
R.string.menu_delete,
R.string.menu_options,
R.string.menu_head,
R.string.menu_help // 26
};
private static int help_icons[] = {
R.string.help_move,
R.string.help_draw,
R.string.help_contour,
R.string.help_edit,
R.string.help_one_model,
R.string.help_refs,
R.string.help_surface,
R.string.help_download,
R.string.help_note,
R.string.help_stats, // ---------------
R.string.help_undo,
R.string.help_redo, //
R.string.help_symbol_plot, // ----------------
R.string.help_refine_triangle,
R.string.help_refine_center,
R.string.help_refine_sides,
R.string.help_cut_model,
R.string.help_stretch_model,
R.string.help_previous,
R.string.help_next,
R.string.help_refine_point,
R.string.help_note_plot
};
private static int help_menus[] = {
R.string.help_save_model, // 21 menus
R.string.help_symbol, // 22
R.string.help_trash_model,
R.string.help_prefs,
R.string.help_head_model,
R.string.help_help
};
private DrawingBrush mCurrentBrush;
// private Path mCurrentPath;
private String mFullName;
TimerTask mTimer;
// ZoomButtonsController mZoomBtnsCtrl;
// View mZoomView;
// ZoomControls mZoomCtrl;
private float oldDist; // zoom pointer-spacing
public int mMode = SketchDef.MODE_MOVE;
private int mTouchMode = SketchDef.TOUCH_MOVE;
private int mEdit = SketchDef.EDIT_NONE;
// private int mSelect = SketchDef.SELECT_NONE;
private float mSaveX;
private float mSaveY;
private float mStartX; // start point (scene coords)
private float mStartY;
private boolean mMoveSelected; // whether it is moving the selected vertex/point
private DataHelper mData;
private long mSid; // survey id
private long mPid; // sketch id
private SketchModel mModel;
// private SketchCompassSensor mCompass;
// ---------------------------------------------------------------------------
// helper private methods
/*
private void setSymbolButton()
{
Resources res = getResources();
switch ( mSymbol ) {
case Symbol.POINT:
symbolBtn.setText( res.getString(R.string.btn_point ) );
break;
case Symbol.AREA:
symbolBtn.setText( res.getString(R.string.btn_area ) );
break;
// case Symbol.LINE:
default:
symbolBtn.setText( res.getString(R.string.btn_line ) );
break;
}
}
*/
@Override
public void setTheTitle()
{
Resources res = getResources();
// String dir = mInfo.getDirectionString();
String symbol_name = // ( mIsInSection) ? "section" :
( mSymbol == Symbol.POINT )? res.getString(R.string.POINT) + BrushManager.mPointLib.getSymbolName( mCurrentPoint )
: ( mSymbol == Symbol.LINE )? res.getString(R.string.LINE)
: res.getString(R.string.AREA) + BrushManager.mAreaLib.getSymbolName( mCurrentArea );
setTitle( String.format( res.getString( R.string.title_sketch),
mInfo.getShotString(),
mInfo.getDirectionString(),
( mMode == SketchDef.MODE_MOVE )? res.getString( R.string.title_move )
: ( mMode == SketchDef.MODE_DRAW )? res.getString( R.string.title_draw )
: ( mMode == SketchDef.MODE_EDIT )? res.getString( R.string.title_contour )
: ( mMode == SketchDef.MODE_SELECT )? res.getString( R.string.title_select )
: ( mMode == SketchDef.MODE_STEP )? res.getString( R.string.title_step )
// : ( mMode == SketchDef.MODE_HEAD )? res.getString( R.string.title_head )
: "--",
( mMode == SketchDef.MODE_DRAW )? symbol_name : ""
) );
// switch ( mSelect ) {
// case SketchDef.SELECT_SECTION:
// selectBtn.setText( res.getString(R.string.btn_section ) );
// // selectBtn.setBackgroundColor( 0xff99ff99 );
// break;
// case SketchDef.SELECT_STEP:
// selectBtn.setText( res.getString(R.string.btn_step ) );
// // selectBtn.setBackgroundColor( 0xffff9999 );
// break;
// case SketchDef.SELECT_SHOT:
// selectBtn.setText( res.getString(R.string.btn_shot ) );
// // selectBtn.setBackgroundColor( 0xffff3333 );
// break;
// case SketchDef.SELECT_JOIN:
// selectBtn.setText( res.getString(R.string.btn_join ) );
// // selectBtn.setBackgroundColor( 0xffff3333 );
// break;
// }
switch ( mMode ) {
case SketchDef.MODE_MOVE:
mListView.setAdapter( mButtonView1.mAdapter );
break;
case SketchDef.MODE_DRAW:
mListView.setAdapter( mButtonView2.mAdapter );
break;
case SketchDef.MODE_EDIT:
mSymbol = Symbol.LINE;
mListView.setAdapter( mButtonView3.mAdapter );
break;
case SketchDef.MODE_SELECT:
mListView.setAdapter( mButtonView4.mAdapter );
break;
case SketchDef.MODE_STEP:
mListView.setAdapter( mButtonView4.mAdapter );
break;
// case SketchDef.MODE_HEAD:
// mListView.setAdapter( mButtonView1.mAdapter );
// break;
}
mListView.invalidate();
}
void setMode( int mode )
{
mMode = mode;
mModel.mActivityMode = mMode;
setTheTitle();
}
private void alertMakeSurface( )
{
TopoDroidAlertDialog.makeAlert( mActivity, getResources(), R.string.make_surface,
new DialogInterface.OnClickListener() {
@Override
public void onClick( DialogInterface dialog, int btn ) {
// doMakeSurfaceDialog( );
doMakeSurface( );
}
}
);
}
// private void alertMissingSymbols()
// {
// TopoDroidAlertDialog.makeAlert( mActivity, getResources(), R.string.missing-symbols,
// new DialogInterface.OnClickListener() {
// @Override
// public void onClick( DialogInterface dialog, int btn ) {
// mAllSymbols = true;
// }
// } );
// }
// -------------------------------------------------------------------------
// SYMBOL-CHOICE methods
public void areaSelected( int k, boolean update_recent )
{
if ( k >= 0 && k < BrushManager.mAreaLib.mSymbolNr ) {
mSymbol = Symbol.AREA;
mCurrentArea = k;
}
setTheTitle();
}
public void lineSelected( int k, boolean update_recent )
{
if ( k >= 0 && k < BrushManager.mLineLib.mSymbolNr ) {
mSymbol = Symbol.LINE;
mCurrentLine = k;
}
setTheTitle();
}
public void pointSelected( int p, boolean update_recent )
{
if ( p >= 0 && p < BrushManager.mPointLib.mSymbolNr ) {
mSymbol = Symbol.POINT;
mCurrentPoint = p;
}
setTheTitle();
}
// ---------------------------------------------------------------
// ZOOM button controls - and methods
// @Override
// public void onVisibilityChanged(boolean visible)
// {
// mZoomBtnsCtrl.setVisible( visible );
// }
// private void rotateInfoBy( float angle )
// { mInfo.azimuth += angle; }
// private void tiltInfoBy( float clino )
// {
// clino += mInfo.clino;
// if ( clino > 90 ) clino = 90;
// if ( clino < -90 ) clino = -90;
// mInfo.clino = clino;
// }
private void changeZoom( float f )
{
mInfo.changeZoom3d( f ); // , mDisplayCenter );
mModel.setTransform( mInfo.xoffset_3d, mInfo.yoffset_3d, mInfo.zoom_3d );
}
/** set info offsets and zoom
* and set the model transform (matrix) accordingly
*/
private void resetZoom()
{
mInfo.resetZoom3d( mApp.mDisplayWidth/(10*mApp.mScaleFactor),
mApp.mDisplayHeight/(10*mApp.mScaleFactor),
10 * mApp.mScaleFactor );
mModel.setTransform( mInfo.xoffset_3d, mInfo.yoffset_3d, mInfo.zoom_3d );
}
// public void zoomIn() { changeZoom( SketchDef.ZOOM_INC ); }
// public void zoomOut() { changeZoom( SketchDef.ZOOM_DEC ); }
public void zoomOne() { resetZoom( ); }
// @Override
// public void onZoom( boolean zoomin )
// {
// if ( zoomin ) {
// zoomIn();
// } else {
// zoomOut();
// }
// }
// -----------------------------------------------------------------------------------
// OUTPUT
// void savePng()
// {
// Bitmap bitmap = mSketchSurface.getBitmap();
// if ( bitmap == null ) {
// Toast.makeText( mActivity, R.string.null_bitmap, Toast.LENGTH_SHORT ).show();
// } else {
// new ExportBitmapToFile( mActivity, mSaveHandler, mSketchSurface.getBitmap(), mFullName ).execute();
// Toast.makeText( mActivity, getString(R.string.saved_file_1) + mFullName + ".png", Toast.LENGTH_SHORT ).show();
// }
// }
// private class ExportBitmapToFile extends AsyncTask<Intent,Void,Boolean>
// {
// private Context mContext;
// private Handler mHandler;
// private Bitmap mBitmap;
// private String mFullName;
// public ExportBitmapToFile( Context context, Handler handler, Bitmap bitmap, String name )
// {
// mContext = context;
// mBitmap = bitmap;
// mHandler = handler;
// mFullName = name;
// // TDLog.Log( TDLog.LOG_PLOT, "ExportBitmapToFile " + mFullName );
// }
// @Override
// protected Boolean doInBackground(Intent... arg0)
// {
// try {
// String filename = mApp.getPngFileWithExt( mFullName );
// TDPath.checkPath( filename );
// final FileOutputStream out = new FileOutputStream( filename );
// mBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
// out.flush();
// out.close();
// return true;
// } catch (Exception e) {
// e.printStackTrace();
// }
// //mHandler.post(completeRunnable);
// return false;
// }
// @Override
// protected void onPostExecute(Boolean bool) {
// super.onPostExecute(bool);
// if ( bool ){
// mHandler.sendEmptyMessage(1);
// }
// }
// }
void saveTh3()
{
if ( doSaveTh3( false /* ! mAllSymbols */ ) ) {
Toast.makeText( mActivity, getString(R.string.saved_file_1) + " " + mFullName + ".th2", Toast.LENGTH_SHORT ).show();
}
}
private class SaveTh3File extends AsyncTask<Intent,Void,Boolean>
{
private Context mContext;
private Handler mHandler;
private SketchModel mModel;
private String mFullName;
public SaveTh3File( Context context, Handler handler, SketchModel model, String name )
{
mContext = context;
mHandler = handler;
mModel = model;
mFullName = name;
// TDLog.Log( TDLog.LOG_PLOT, "SaveTh3File " + mFullName );
}
@Override
protected Boolean doInBackground(Intent... arg0)
{
try {
String filename = TDPath.getTh3FileWithExt( mFullName );
TDPath.checkPath( filename );
FileWriter writer = new FileWriter( filename );
BufferedWriter out = new BufferedWriter( writer );
mModel.exportTherion( out, mFullName, PlotInfo.projName[ (int)mType ] );
out.flush();
out.close();
return true;
} catch (Exception e) {
e.printStackTrace();
}
//mHandler.post(completeRunnable);
return false;
}
@Override
protected void onPostExecute(Boolean bool) {
super.onPostExecute(bool);
if ( bool ){
mHandler.sendEmptyMessage(1);
}
}
}
// void doSaveTh3AndReload()
// {
// if ( mFullName != null && mSketchSurface != null ) {
// Toast.makeText( mActivity, "save th3 and reload ... wait", Toast.LENGTH_SHORT ).show();
// Handler saveHandler = new Handler(){
// @Override
// public void handleMessage(Message msg) {
// String filename = TDPath.getTh3FileWithExt( mFullName );
// mModel.loadTh3( filename, null, mPainter );
// mSketchSurface.setModel( mModel );
// mSketchSurface.isDrawing = true;
// Toast.makeText( mSketchSurface.getContext(), "save th3 and reload done", Toast.LENGTH_SHORT ).show();
// }
// };
// new SaveTh3File(this, saveHandler, mModel, mFullName ).execute();
// } else {
// Toast.makeText( mActivity, "FAIL save th3 and reload", Toast.LENGTH_SHORT ).show();
// }
// }
static Handler mSaveHandler = new Handler();
// {
// @Override
// public void handleMessage(Message msg) { }
// } ;
boolean doSaveTh3( boolean not_all_symbols )
{
// TDLog.Log( TDLog.LOG_PLOT, " savingTh3 " + mFullName );
if ( mFullName != null && mSketchSurface != null ) {
new SaveTh3File( mActivity, mSaveHandler, mModel, mFullName ).execute();
}
return false;
}
private class SaveDxfFile extends AsyncTask<Intent,Void,Boolean>
{
private Context mContext;
private Handler mHandler;
private SketchModel mModel;
private String mFullName;
public SaveDxfFile( Context context, Handler handler, SketchModel model, String name )
{
mContext = context;
mHandler = handler;
mModel = model;
mFullName = name;
// TDLog.Log( TDLog.LOG_PLOT, "SaveDxfFile " + mFullName );
}
@Override
protected Boolean doInBackground(Intent... arg0)
{
try {
String filename = TDPath.getDxfFileWithExt( mFullName );
TDPath.checkPath( filename );
FileWriter writer = new FileWriter( filename );
PrintWriter out = new PrintWriter( writer );
SketchDxf.write( out, mFullName, mModel );
out.flush();
out.close();
return true;
} catch (Exception e) {
e.printStackTrace();
}
//mHandler.post(completeRunnable);
return false;
}
@Override
protected void onPostExecute(Boolean bool) {
super.onPostExecute(bool);
if ( bool ){
mHandler.sendEmptyMessage(1);
}
}
}
void doSaveDxf()
{
if ( mFullName != null && mSketchSurface != null ) {
// if ( not_all_symbols ) {
// alertMissingSymbols();
// }
// if ( mAllSymbols ) {
new SaveDxfFile( mActivity, mSaveHandler, mModel, mFullName ).execute();
// }
}
}
// -----------------------------------------------------------------------------------
// LIFECYCLE of the activity
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_PORTRAIT );
mPainter = new SketchPainter();
setContentView(R.layout.sketch_activity);
mApp = (TopoDroidApp)getApplication();
mDataDownloader = null; // FIXME set the DataDownloader
mActivity = this;
// mInfo.zoom = mApp.mScaleFactor; // canvas zoom
// setCurrentPaint();
mCurrentBrush = new DrawingPenBrush();
mCurrentPoint = 0; // BrushManager.POINT_LABEL;
mCurrentLine = 0; // BrushManager.mLineLib.mLineWallIndex;
mCurrentArea = 0; // BrushManager.AREA_WATER;
// mSectionType = SketchSection.SECTION_NONE;
// mIsInSection = false;
mSketchSurface = (SketchDrawingSurface) findViewById(R.id.sketchSurface);
mSketchSurface.previewPath = new DrawingPath( DrawingPath.DRAWING_PATH_LINE, null );
mSketchSurface.previewPath.mPath = new Path();
mSketchSurface.previewPath.setPaint( mPainter.previewPaint );
mSketchSurface.setOnTouchListener(this);
// mSketchSurface.setOnLongClickListener(this);
// mSketchSurface.setBuiltInZoomControls(true);
BrushManager.makePaths( getResources() );
mData = mApp.mData; // new DataHelper( this );
Bundle extras = getIntent().getExtras();
mSid = extras.getLong( TDTag.TOPODROID_SURVEY_ID );
String name = extras.getString( TDTag.TOPODROID_SKETCH_NAME );
mFullName = mApp.mySurvey + "-" + name;
// mCompass = null;
// mDecl = mData.getSurveyDeclination( mSid );
mDecl = 0.0f;
mInfo = mData.getSketch3dInfo( mSid, name );
mPid = mInfo.id;
mInfo.xcenter = mApp.mDisplayWidth/2;
mInfo.ycenter = mApp.mDisplayHeight/2;
List<DistoXDBlock> list = mData.selectAllShots( mSid, TopoDroidApp.STATUS_NORMAL );
if ( list.size() == 0 ) {
Toast.makeText( mActivity, R.string.few_data, Toast.LENGTH_SHORT ).show();
finish();
} else {
prepareReferences( list );
computeReferenceFrame( false );
// mAllSymbols = true; // by default there are all the symbols
// now try to load drawings from therion file
String filename = TDPath.getTh3FileWithExt( mFullName );
// SymbolsPalette missingSymbols = new SymbolsPalette();
// mAllSymbols =
mModel.loadTh3( filename, null /* missingSymbols */, mPainter );
// if ( ! mAllSymbols ) {
// // FIXME FIXME
// String msg = missingSymbols.getMessage( getResources() );
// (new MissingDialog( mActivity, msg )).show();
// }
setSurfaceTransform( 0, 0 );
// mSketchSurface.refresh(); // do not do this --> segfault
mSketchSurface.setThreadRunning( true );
}
// setSymbolButton();
// selectBtn = (Button) findViewById( R.id.btn_select );
// selectBtn.setOnClickListener( this );
mListView = (HorizontalListView) findViewById(R.id.listview);
int size = mApp.setListViewHeight( mListView );
Resources res = getResources();
mButton1 = new Button[ mNrButton1 ];
int off = 3;
int ic = 0;
for ( int k=0; k<mNrButton1; ++k ) {
ic = ( k == 0 )? 0 : off+k;
mButton1[k] = MyButton.getButton( mActivity, this, izons[ic] );
}
mButton2 = new Button[ mNrButton2 ];
off = 2 + mNrButton1;
for ( int k=0; k<mNrButton2; ++k ) {
ic = ( k == 0 )? 1 : off+k;
mButton2[k] = MyButton.getButton( mActivity, this, izons[ic] );
}
mButton3 = new Button[ mNrButton3 ];
off = 1 + mNrButton1 + mNrButton2;
for ( int k=0; k<mNrButton3; ++k ) {
ic = ( k == 0 )? 2 : off+k;
mButton3[k] = MyButton.getButton( mActivity, this, izons[ic] );
}
mButton4 = new Button[ mNrButton4 ];
off = 0 + mNrButton1 + mNrButton2 + mNrButton3;
for ( int k=0; k<mNrButton4; ++k ) {
ic = ( k == 0 )? 3 : off+k;
mButton4[k] = MyButton.getButton( mActivity, this, izons[ic] );
}
mButtonView1 = new HorizontalButtonView( mButton1 ); // MOVE
mButtonView2 = new HorizontalButtonView( mButton2 ); // DRAW
mButtonView3 = new HorizontalButtonView( mButton3 ); // EDIT
mButtonView4 = new HorizontalButtonView( mButton4 ); // SELECT
// mListView.setAdapter( mButtonView1.mAdapter ); // done by setTheTitle
setTheTitle();
mInfo.resetDirection(); // azi = 0, clino = 0, and compute triad versors
resetZoom();
if ( mModel.mCurrentSurface == null ) {
doMakeSurface( );
}
mImage = (Button) findViewById( R.id.handle );
mImage.setOnClickListener( this );
mImage.setBackgroundDrawable( MyButton.getButtonBackground( mApp, res, R.drawable.iz_menu ) );
mMenu = (ListView) findViewById( R.id.menu );
setMenuAdapter( res );
closeMenu();
// HOVER
mMenu.setOnItemClickListener( this );
mTimer = null;
if ( mDataDownloader != null ) {
mApp.registerLister( this );
}
}
// @Override
// protected synchronized void onStart()
// {
// super.onStart();
// }
@Override
protected synchronized void onResume()
{
super.onResume();
mSketchSurface.isDrawing = true;
}
@Override
protected synchronized void onPause()
{
mSketchSurface.isDrawing = false;
mData.updateSketch( mPid, mSid, mInfo.st1, mInfo.st2,
mInfo.xoffset_top, mInfo.yoffset_top, mInfo.zoom_top,
mInfo.xoffset_side, mInfo.yoffset_side, mInfo.zoom_side,
mInfo.xoffset_3d, mInfo.yoffset_3d, mInfo.zoom_3d,
mInfo.east, mInfo.south, mInfo.vert,
mInfo.azimuth, mInfo.clino );
// Toast.makeText( this, R.string.saving_wait, Toast.LENGTH_SHORT ).show();
// if ( mAllSymbols ) {
doSaveTh3( false ); // do not alert-dialog on mAllSymbols: in case do not save
// } else {
// Toast.makeText( this, R.string.missing_save, Toast.LENGTH_SHORT ).show();
// }
super.onPause();
}
@Override
protected synchronized void onStop()
{
if ( mDataDownloader != null ) {
// mApp.unregisterLister( this );
mDataDownloader.onStop();
mApp.disconnectRemoteDevice( false );
}
super.onStop();
}
@Override
protected synchronized void onDestroy()
{
if ( mDataDownloader != null ) {
mApp.unregisterLister( this );
}
super.onDestroy();
}
// ----------------------------------------------------------------------
// ADD ITEMS
@Override
public void addLabel( String label, float x, float y )
{
if ( label != null && label.length() > 0 ) {
mModel.setLabelToLastPoint( label );
}
}
private void addStationName( NumStation st )
{
// mSketchSurface.addStation( st.name, st.e, st.s, st.v );
SketchStationName stn = new SketchStationName( st.name, st.e, st.s, st.v );
stn.mPaint = BrushManager.fixedStationPaint;
mModel.addFixedStation( stn );
}
// convert coordinates relative to base point (e,s,v) of the sketch info
// x east rightward
// y south downward
// z vertical downward
// on input (x1,y1,z1) and (x2,y2,z2) are world coords (as computed by num)
// then they are referred to the mInfo origin
private void addFixed( float x1, float y1, float z1,
float x2, float y2, float z2,
DistoXDBlock blk, boolean splay, boolean is_reference )
{
x1 = Sketch3dInfo.mXScale * (x1 - mInfo.east);
x2 = Sketch3dInfo.mXScale * (x2 - mInfo.east);
y1 = Sketch3dInfo.mXScale * (y1 - mInfo.south);
y2 = Sketch3dInfo.mXScale * (y2 - mInfo.south);
z1 = Sketch3dInfo.mXScale * (z1 - mInfo.vert);
z2 = Sketch3dInfo.mXScale * (z2 - mInfo.vert);
SketchFixedPath path = null;
if ( splay ) {
path = new SketchFixedPath( DrawingPath.DRAWING_PATH_SPLAY, blk,
BrushManager.fixedSplayPaint,
null );
} else {
path = new SketchFixedPath( DrawingPath.DRAWING_PATH_FIXED, blk,
is_reference? BrushManager.highlightPaint : BrushManager.fixedShotPaint,
BrushManager.fixedBluePaint );
}
if ( path != null ) {
// path.setEndPoints( x1, y1, x2, y2 ); // scene coords
path.set3dMidpoint( (x1+x2)/2, (y1+y2)/2, (z1+z2)/2 );
path.addPoint( x1, y1, z1 );
path.addPoint( x2, y2, z2 );
mModel.addFixedPath( path );
}
}
// ------------------------------------------------------------------------------------
// FRAME and REFERENCE
private void computeReferenceFrame( boolean set_origin )
{
// get the two stations
// clear Reference Frame
mSketchSurface.clearReferences();
NumStation station1 = mNum.getStation( mInfo.st1 );
NumStation station2 = mNum.getStation( mInfo.st2 );
NumShot shot = mNum.getShot( mInfo.st1, mInfo.st2 );
DistoXDBlock blk = shot.getFirstBlock();
mInfo.setStations( station1, station2, blk, set_origin );
// resetZoom();
List<NumShot> shots = mNum.getShots();
List<NumSplay> splays = mNum.getSplays();
addStationName( station1 );
addStationName( station2 );
// List<NumStation> stations = mNum.getStations();
// for ( NumStation station : stations ) {
// addStationName( station );
// }
for ( NumSplay splay : splays ) {
if ( station1.equals(splay.from) ) {
addFixed( station1.e, station1.s, station1.v, splay.e, splay.s, splay.v, splay.getBlock(), true, false );
} else if ( station2.equals(splay.from) ) {
addFixed( station2.e, station2.s, station2.v, splay.e, splay.s, splay.v, splay.getBlock(), true, false );
}
}
for ( NumShot sh : shots ) {
// addFixed( sh.from.e, sh.from.s, sh.from.v, sh.to.e, sh.to.s, sh.to.v, sh.getFirstBlock(), false, false );
if ( sh.from.equals(station1) ) {
if ( ! sh.to.equals(station2) ) {
addStationName( sh.to );
addFixed( sh.from.e, sh.from.s, sh.from.v, sh.to.e, sh.to.s, sh.to.v, sh.getFirstBlock(), false, false );
} else {
addFixed( sh.from.e, sh.from.s, sh.from.v, sh.to.e, sh.to.s, sh.to.v, sh.getFirstBlock(), false, true );
}
} else if ( sh.from.equals(station2) ) {
if ( ! sh.to.equals(station1) ) {
addStationName( sh.to );
addFixed( sh.from.e, sh.from.s, sh.from.v, sh.to.e, sh.to.s, sh.to.v, sh.getFirstBlock(), false, false );
} else {
addFixed( sh.from.e, sh.from.s, sh.from.v, sh.to.e, sh.to.s, sh.to.v, sh.getFirstBlock(), false, true );
}
} else if ( sh.to.equals(station1) ) {
if ( ! sh.from.equals(station2) ) {
addStationName( sh.from );
addFixed( sh.from.e, sh.from.s, sh.from.v, sh.to.e, sh.to.s, sh.to.v, sh.getFirstBlock(), false, false );
} else {
addFixed( sh.from.e, sh.from.s, sh.from.v, sh.to.e, sh.to.s, sh.to.v, sh.getFirstBlock(), false, true );
}
} else if ( sh.to.equals(station2) ) {
if ( ! sh.from.equals(station1) ) {
addStationName( sh.from );
addFixed( sh.from.e, sh.from.s, sh.from.v, sh.to.e, sh.to.s, sh.to.v, sh.getFirstBlock(), false, false );
} else {
addFixed( sh.from.e, sh.from.s, sh.from.v, sh.to.e, sh.to.s, sh.to.v, sh.getFirstBlock(), false, true );
}
}
}
}
private void prepareReferences( List<DistoXDBlock> list )
{
// mSketchSurface.clearReferences();
mNum = new DistoXNum( list, mInfo.start, null, null, mDecl ); // FIXME null: no barrier no hiding
if ( (! mNum.surveyAttached) && TDSetting.mCheckAttached ) {
Toast.makeText( mActivity, R.string.survey_not_attached, Toast.LENGTH_SHORT ).show();
}
mModel = new SketchModel( mInfo, mNum, mPainter );
mSketchSurface.setModel( mModel );
}
void recreateNum( List<DistoXDBlock> list )
{
mNum = new DistoXNum( list, mInfo.start, null, null, mDecl ); // FIXME null: no barrier no hiding
mModel.setNum( mNum );
}
void updateNum( ArrayList<DistoXDBlock> list )
{
// FIXME mNum.addNewData( list );
computeReferenceFrame( false ); // do not change origin
}
private void setSurfaceTransform( float x_shift, float y_shift )
{
mInfo.shiftOffset3d( x_shift, y_shift );
mModel.setTransform( mInfo.xoffset_3d, mInfo.yoffset_3d, mInfo.zoom_3d );
}
// -------------------------------------------------------------------------
// SELECT methods
// private void doSelectAt( float x_scene, float y_scene )
// {
// // Log.v( "DistoX", "doSelectAt at " + x_scene + " " + y_scene );
// float d0 = TopoDroidApp.mCloseness;
// // SketchPointPath point = mSketchSurface.getPointAt( x_scene, y_scene );
// // if ( point != null ) {
// // // new DrawingPointDialog( mActivity, this, point ).show();
// // return;
// // }
// // SketchLinePath line = mSketchSurface.getLineAt( x_scene, y_scene );
// // if ( line != null ) {
// // // new DrawingLineDialog( mActivity, this, line ).show();
// // return;
// // }
// //
// // SketchAreaPath area = mSketchSurface.getAreaAt( x_scene, y_scene );
// // if ( area != null ) {
// // // new DrawingAreaDialog( mActivity, this, area ).show();
// // return;
// // }
// }
private SketchFixedPath doSelectShotAt( float x_scene, float y_scene )
{
return mModel.selectShotAt( x_scene, y_scene );
}
private SketchStationName doSelectStationAt( float x_scene, float y_scene )
{
return mModel.selectStationAt( x_scene, y_scene );
}
// private boolean doSelectSectionBasePointAt( float x_scene, float y_scene )
// {
// return mModel.selectSectionBasePointAt( x_scene, y_scene );
// }
private SketchTriangle doSelectTriangleAt( float x_scene, float y_scene, SketchTriangle tri )
{
return mModel.selectTriangleAt( x_scene, y_scene, tri );
}
// --------------------------------------------------------------------------
// DELETE
// void deletePoint( DrawingPointPath point )
// {
// mSketchSurface.deletePath( point );
// }
// void deleteLine( DrawingLinePath line )
// {
// mSketchSurface.deletePath( line );
// }
// void deleteArea( DrawingAreaPath area )
// {
// mSketchSurface.deletePath( area );
// }
// void refreshSurface()
// {
// // TDLog.Log( TDLog.LOG_PLOT, "refresh surface");
// mSketchSurface.refresh();
// }
// --------------------------------------------------------------------------
// TOUCH
// private void dumpEvent( MotionEventWrap ev )
// {
// String name[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE", "PTR_DOWN", "PTR_UP", "7?", "8?", "9?" };
// StringBuilder sb = new StringBuilder();
// int action = ev.getAction();
// int actionCode = action & MotionEvent.ACTION_MASK;
// sb.append( "Event action_").append( name[actionCode] );
// if ( actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP ) {
// sb.append( "(pid " ).append( action>>MotionEvent.ACTION_POINTER_ID_SHIFT ).append( ")" );
// }
// sb.append( " [" );
// for (int i=0; i<ev.getPointerCount(); ++i ) {
// sb.append( "#" ).append( i );
// sb.append( "(pid " ).append( ev.getPointerId(i) ).append( ")=" ).append( (int)(ev.getX(i)) ).append( "." ).append( (int)(ev.getY(i)) );
// if ( i+1 < ev.getPointerCount() ) sb.append( ":" );
// }
// sb.append( "]" );
// // Log.v( TopoDroidApp.TAG, sb.toString() );
// }
private float spacing( MotionEventWrap ev )
{
int np = ev.getPointerCount();
if ( np < 2 ) return 0.0f;
float x = ev.getX(1) - ev.getX(0);
float y = ev.getY(1) - ev.getY(0);
return TDMath.sqrt(x*x + y*y);
}
// private float direction( MotionEventWrap ev )
// {
// int np = ev.getPointerCount();
// if ( np < 2 ) return 0.0f;
// float x = ev.getX(1) - ev.getX(0);
// float y = ev.getY(1) - ev.getY(0);
// return TDMath.atan2( y, x );
// }
// private float position( MotionEventWrap ev ) // vertical position
// {
// int np = ev.getPointerCount();
// if ( np == 0 ) return 0.0f;
// if ( np == 1 ) return ev.getY(0);
// return ( ev.getY(1) + ev.getY(0) ) / 2;
// }
// private Vector addPointToEditLine( SketchLinePath line, SketchVertex v1, SketchVertex v2, float t )
// {
// return line.addLinePoint( mInfo.east + v1.x + t * (v2.x-v1.x),
// mInfo.south + v1.y + t * (v2.y-v1.y),
// mInfo.vert + v1.z + t * (v2.z-v1.z) );
// }
// private Vector addPointToEditLine( SketchLinePath line, SketchVertex v1 )
// {
// return line.addLinePoint( mInfo.east + v1.x,
// mInfo.south + v1.y,
// mInfo.vert + v1.z );
// }
private Vector makeEditLinePoint( SketchVertex v1, SketchVertex v2, float t )
{
return new Vector( mInfo.east + v1.x + t * (v2.x-v1.x),
mInfo.south + v1.y + t * (v2.y-v1.y),
mInfo.vert + v1.z + t * (v2.z-v1.z) );
}
private Vector makeEditLinePoint( SketchVertex v1 )
{
return new Vector( mInfo.east + v1.x,
mInfo.south + v1.y,
mInfo.vert + v1.z );
}
public boolean onTouch( View view, MotionEvent rawEvent )
{
if ( onMenu ) {
closeMenu();
return true;
}
dismissPopups();
float d0 = TDSetting.mCloseCutoff + TDSetting.mCloseness / mInfo.zoom_3d;
MotionEventWrap event = MotionEventWrap.wrap(rawEvent);
// TDLog.Log( TDLog.LOG_INPUT, "SketchWindow onTouch() " );
// dumpEvent( event );
float x_canvas = event.getX();
float y_canvas = event.getY();
float x_scene = mInfo.canvasToSceneX( x_canvas );
float y_scene = mInfo.canvasToSceneY( y_canvas );
// Log.v("DistoX", "canvas pt " + x_canvas + " " + y_canvas + " scene " + x_scene + " " + y_scene );
int action = event.getAction() & MotionEvent.ACTION_MASK;
if (action == MotionEvent.ACTION_POINTER_DOWN) {
mTouchMode = SketchDef.TOUCH_ZOOM;
oldDist = spacing( event );
}
else if ( action == MotionEvent.ACTION_POINTER_UP)
{
mTouchMode = SketchDef.TOUCH_MOVE;
/* nothing */
}
// ============================== DOWN ===============================
else if (action == MotionEvent.ACTION_DOWN)
{
if ( mMode == SketchDef.MODE_MOVE /* || mMode == SketchDef.MODE_EDIT */ ) {
// mActivity.setTitle( R.string.title_move );
mSaveX = x_canvas;
mSaveY = y_canvas;
return false;
} else if ( mMode == SketchDef.MODE_DRAW || mMode == SketchDef.MODE_EDIT ) {
mStartX = x_scene;
mStartY = y_scene;
// TDLog.Log( TDLog.LOG_PLOT, "onTouch ACTION_DOWN symbol " + mSymbol );
mPointCnt = 0;
if ( mSymbol == Symbol.LINE || mSymbol == Symbol.AREA ) {
// mSketchSurface.isDrawing = true;
mCurrentLinePath = new DrawingLinePath( mCurrentLine );
mCurrentLinePath.addStartPoint( x_scene, y_scene );
mCurrentBrush.mouseDown( mSketchSurface.previewPath.mPath, x_canvas, y_canvas );
} else { // Symbol.POINT
mSaveX = x_canvas;
mSaveY = y_canvas;
}
} else if ( mMode == SketchDef.MODE_SELECT ) {
mSaveX = x_canvas;
mSaveY = y_canvas;
float xs = mInfo.canvasToSceneX( x_canvas );
float ys = mInfo.canvasToSceneY( y_canvas );
// Log.v("DistoX", "getVertexAt scene " + xs + " " + ys + " d " + d0 );
SketchVertex v = mModel.getVertexAt( xs, ys, d0 );
if ( v != null ) {
SketchVertex v1 = mModel.getSelectedVertex();
if ( v1 == null ) {
mMoveSelected = false;
// Log.v("DistoX", "set selected vertex " + v.index );
mModel.setSelectedVertex( v );
} else if ( v == v1 ) {
mMoveSelected = true;
} else {
mMoveSelected = false;
// Log.v("DistoX", "set selected vertex null ");
mModel.setSelectedVertex( null );
}
}
// SelectionPoint pt = mModel.hotItem();
// if ( pt != null ) {
// mMoveSelected = ( pt.distance( x_scene, y_scene ) < d0 );
// }
// doSelectAt( x_scene, y_scene );
mSaveX = x_canvas;
mSaveY = y_canvas;
} else if ( mMode == SketchDef.MODE_STEP ) {
SketchFixedPath path = doSelectShotAt( x_scene, y_scene );
if ( path == null ) {
Toast.makeText( mActivity, R.string.shot_not_found, Toast.LENGTH_SHORT ).show();
} else {
DistoXDBlock blk = path.mBlock;
if ( blk != null ) {
// float a = mInfo.azimuth;
// float c = mInfo.clino;
// float x = mInfo.xoffset_3d;
// float y = mInfo.yoffset_3d;
// float z = mInfo.zoom_3d;
mInfo.st1 = blk.mFrom;
mInfo.st2 = blk.mTo;
computeReferenceFrame( false );
mMode = SketchDef.MODE_MOVE;
setTheTitle();
// mInfo.resetDirection(); // azi = 0, clino = 0, and compute triad versors
// resetZoom();
// mInfo.shiftOffset3d( x, y );
// mInfo.resetZoom3d( x, y, z );
// mInfo.rotateBy3d( a, c );
}
}
}
}
// ============================== MOVE ===============================
else if (action == MotionEvent.ACTION_MOVE)
{
if ( mTouchMode == SketchDef.TOUCH_MOVE) {
float x_shift = x_canvas - mSaveX; // compute shift
float y_shift = y_canvas - mSaveY;
if ( mMode == SketchDef.MODE_DRAW || mMode == SketchDef.MODE_EDIT ) {
if ( mSymbol == Symbol.LINE || mSymbol == Symbol.AREA ) {
if ( x_shift*x_shift + y_shift*y_shift > TDSetting.mLineSegment2 ) {
++mPointCnt; // add all points
mCurrentLinePath.addPoint( x_scene, y_scene );
mSaveX = x_canvas; // reset start
mSaveY = y_canvas;
mCurrentBrush.mouseMove( mSketchSurface.previewPath.mPath, x_canvas, y_canvas );
}
}
} else if ( mMode == SketchDef.MODE_MOVE
|| ( mMode == SketchDef.MODE_SELECT && ! mMoveSelected ) ) {
if ( Math.abs( x_shift ) < 20 && Math.abs( y_shift ) < 20 ) {
mInfo.rotateBy3d( x_shift/6, -y_shift/6 );
setTheTitle();
mModel.setTransform( mInfo.xoffset_3d, mInfo.yoffset_3d, mInfo.zoom_3d );
mSaveX = x_canvas; // reset start
mSaveY = y_canvas;
}
} else if ( mMode == SketchDef.MODE_SELECT && mMoveSelected ) { // moving the selected vertex
// TODO
} else if ( mMode == SketchDef.MODE_STEP ) {
// nothing
}
} else { // mTouchMode == SketchDef.TOUCH_ZOOM
float newDist = spacing( event );
if ( newDist > 16.0f && oldDist > 16.0f ) {
float factor = newDist/oldDist;
if ( factor > 0.05f && factor < 4.0f ) {
changeZoom( factor );
oldDist = newDist;
}
if ( Math.abs(factor-1.0f) <= 0.05f ) { // move
float x_shift = x_canvas - mSaveX; // compute shift
float y_shift = y_canvas - mSaveY;
if ( (Math.abs(x_shift) + Math.abs(y_shift)) < 200 ) {
setSurfaceTransform( x_shift, y_shift );
mSaveX = x_canvas;
mSaveY = y_canvas;
}
}
}
}
}
// ============================== UP ===============================
else if (action == MotionEvent.ACTION_UP)
{
if ( mTouchMode == SketchDef.TOUCH_ZOOM ) {
mTouchMode = SketchDef.TOUCH_MOVE;
} else {
float x_shift = x_canvas - mSaveX; // compute shift
float y_shift = y_canvas - mSaveY;
if ( mMode == SketchDef.MODE_MOVE )
{
/* nothing */
}
else if ( mMode == SketchDef.MODE_DRAW )
{
// normal draw
if ( mSymbol == Symbol.LINE || mSymbol == Symbol.AREA ) {
mCurrentBrush.mouseUp( mSketchSurface.previewPath.mPath, x_canvas, y_canvas );
mSketchSurface.previewPath.mPath = new Path();
if ( x_shift*x_shift + y_shift*y_shift > TDSetting.mLineSegment2 ) {
mCurrentLinePath.addPoint( x_scene, y_scene );
}
if ( mPointCnt > TDSetting.mLineType ) {
SketchLinePath line = null;
if ( mSymbol == Symbol.LINE ) {
line = new SketchLinePath( DrawingPath.DRAWING_PATH_LINE, mCurrentLine, mInfo.st1, mInfo.st2, mPainter );
} else if ( mSymbol == Symbol.AREA ) {
line = new SketchLinePath( DrawingPath.DRAWING_PATH_AREA, mCurrentArea, mInfo.st1, mInfo.st2, mPainter );
}
ArrayList< LinePoint > pts = new ArrayList< LinePoint >();
for ( LinePoint p = mCurrentLinePath.mFirst; p != null; p = p.mNext ) { pts.add( p ); }
SketchTriangle tri = null;
int np = pts.size();
LinePoint p1 = pts.get(0);
LinePoint p2 = pts.get(np-1);
for (LinePoint p : pts ) {
// find point on the triangulated surface and add it to the line
tri = doSelectTriangleAt( p.mX, p.mY, tri );
if ( tri != null /* && mInfo.isForward( tri ) */ ) {
Vector q1 = tri.get3dPoint( p.mX, p.mY );
line.addLinePoint( mInfo.east + q1.x, mInfo.south + q1.y, mInfo.vert + q1.z );
}
}
if ( mSymbol == Symbol.LINE ) {
p1 = pts.get(0);
p2 = pts.get(pts.size()-1);
float len = TDMath.sqrt( (p2.mX-p1.mX)*(p2.mX-p1.mX) + (p2.mY-p1.mY)*(p2.mY-p1.mY) );
if ( len < SketchDef.CLOSE_GAP ) {
line.close();
}
} else if ( mSymbol == Symbol.AREA ) {
// Log.v("DistoX", "add area type " + mCurrentArea );
line.close();
}
mModel.addSketchPath( line );
}
} else { // Symbol.POINT
if ( Math.abs( x_shift ) < 16 && Math.abs( y_shift ) < 16 ) {
// Log.v("DistoX", "point get triangle at " + x_scene + " " + y_scene );
SketchTriangle tri = doSelectTriangleAt( x_scene, y_scene, null );
if ( tri != null /* && mInfo.isForward( tri ) */ ) {
Vector p = tri.get3dPoint( x_scene, y_scene );
// Log.v("DistoX", "new point " + mCurrentPoint + " at " + p.x + " " + p.y + " " + p.z );
SketchPointPath path = new SketchPointPath( mCurrentPoint, mInfo.st1, mInfo.st2, p.x, p.y, p.z );
SymbolPointLibrary point_lib = BrushManager.mPointLib;
if ( point_lib.isSymbolOrientable( mCurrentPoint ) ) {
float angle = (float)( point_lib.getPointOrientation( mCurrentPoint ) ); // degrees
// Log.v("DistoX", "point " + mCurrentPoint + " angle " + angle );
// angles 0:upward 90;rightward 180:downward 270:leftward
// scene: x is rightward, y downward
// p1 is the 3D point of the orientation (from p to p1)
Vector p1 = tri.get3dPoint( x_scene + 0.1f * TDMath.sind(angle),
y_scene - 0.1f * TDMath.cosd(angle) );
path.setOrientation( p1, mInfo );
}
mModel.addPoint( path );
if ( point_lib.pointHasText( mCurrentPoint ) ) {
// TODO text dialog
new DrawingLabelDialog( mActivity, this, x_scene, y_scene ).show();
}
// } else {
// Log.v("DistoX", "no triangle found");
}
}
}
}
else if ( mMode == SketchDef.MODE_EDIT )
{
if ( mSymbol == Symbol.LINE /* || mSymbol == Symbol.AREA */ ) {
mCurrentBrush.mouseUp( mSketchSurface.previewPath.mPath, x_canvas, y_canvas );
mSketchSurface.previewPath.mPath = new Path();
if ( Math.sqrt( x_shift*x_shift + y_shift*y_shift ) > TDSetting.mLineSegment || (mPointCnt % TDSetting.mLineType) > 0 ) {
mCurrentLinePath.addPoint( x_scene, y_scene );
}
if ( mPointCnt > TDSetting.mLineType ) {
if ( mEdit == SketchDef.EDIT_NONE ) {
// SketchLinePath edit_line =
// new SketchLinePath( DrawingPath.DRAWING_PATH_LINE, mCurrentLine, mInfo.st1, mInfo.st2, mPainter );
// close mCurrentLinePath adding a point equal to the start one (scene coords)
mCurrentLinePath.addPoint( mStartX, mStartY );
boolean skipped_triangle = false;
// mModel.setEditLine( null );
LinePoint p1 = mCurrentLinePath.mFirst;
SketchTriangle tri1 = doSelectTriangleAt( p1.mX, p1.mY, null );
SketchTriangle tri10 = tri1;
Vector w10 = null;
Vector w20 = null;
Vector w120 = null;
if ( tri1 != null /* && mInfo.isForward( tri1 ) */ ) {
ArrayList< SketchRefinement > refines = new ArrayList<SketchRefinement>();
// ArrayList< PointF > border = new ArrayList< PointF >();
SketchTriangle tri2 = tri1;
SketchVertex u1 = null, u2 = null; // previous side of tri2
SketchVertex w1 = null, w2 = null; // current side of tri2
Vector u12 = null;
Vector w12 = null;
PointF border_point = new PointF(0,0);
for ( LinePoint p2 = p1.mNext; p2 != null; p2 = p2.mNext ) {
tri2 = doSelectTriangleAt( p2.mX, p2.mY, tri2 );
if ( tri2 != null && tri2 != tri1 ) {
int i1 = tri1.i;
if ( i1 != tri2.i && i1 != tri2.j && i1 != tri2.k ) i1 = -1;
int j1 = tri1.j;
if ( j1 != tri2.i && j1 != tri2.j && j1 != tri2.k ) j1 = -1;
int k1 = tri1.k;
if ( k1 != tri2.i && k1 != tri2.j && k1 != tri2.k ) k1 = -1;
if ( i1 >= 0 ) {
if ( j1 >= 0 ) { // side v1--v2 of tri1
w1 = tri1.v1;
w2 = tri1.v2;
// intersect p1--p2 with tri2.p1--tri2.p2
float t = Geometry2D.intersect( p1, p2, tri1.p1, tri1.p2, border_point );
// w12 = addPointToEditLine( edit_line, w1, w2, t );
w12 = makeEditLinePoint( w1, w2, t );
} else if ( k1 >= 0 ) { // side v3--v1
w1 = tri1.v3;
w2 = tri1.v1;
float t = Geometry2D.intersect( p1, p2, tri1.p3, tri1.p1, border_point );
// w12 = addPointToEditLine( edit_line, w1, w2, t );
w12 = makeEditLinePoint( w1, w2, t );
} else { // vertex v1
w1 = tri1.v1;
w2 = tri1.v1;
// w12 = addPointToEditLine( edit_line, w1 );
w12 = makeEditLinePoint( w1 );
// border_point.x = tri1.p1.x;
// border_point.y = tri1.p1.y;
}
} else if ( j1 >= 0 ) {
if ( k1 >= 0 ) { // side v2--v3
w1 = tri1.v2;
w2 = tri1.v3;
float t = Geometry2D.intersect( p1, p2, tri1.p2, tri1.p3, border_point );
// w12 = addPointToEditLine( edit_line, w1, w2, t );
w12 = makeEditLinePoint( w1, w2, t );
} else { // vertex v2
w1 = tri1.v2;
w2 = tri1.v2;
// w12 = addPointToEditLine( edit_line, w1 );
w12 = makeEditLinePoint( w1 );
// border_point.x = tri1.p2.x;
// border_point.y = tri1.p2.y;
}
} else if ( k1 >= 0 ) { // vertex v3
w1 = tri1.v3;
w2 = tri1.v3;
// w12 = addPointToEditLine( edit_line, w1 );
w12 = makeEditLinePoint( w1 );
// border_point.x = tri1.p3.x;
// border_point.y = tri1.p3.y;
} else {
Log.v("DistoX", "WARNING edit_line jumps over a triangle");
skipped_triangle = true;
}
// border.add( new PointF( border_point.x, border_point.y ) );
if ( u1 != null ) {
if ( u2 == w1 ) { // u1 --(u12)--> u2=w1 --(w12)--> w2
refines.add( new SketchRefinement( tri1, u2, w12, u12 ) );
} else if ( u1 == w2 ) { // w1 --(w12)--> w2=u1 --(u12)--> u2
refines.add( new SketchRefinement( tri1, u1, u12, w12 ) );
}
} else {
w10 = w1;
w20 = w2;
w120 = w12;
}
tri1 = tri2;
u1 = w2;
u2 = w1;
u12 = w12;
}
p1 = p2;
}
if ( u2 == w10 ) { // u1 --> u2=w1 --> w2
refines.add( new SketchRefinement( tri10, u2, w120, u12 ) );
} else if ( u1 == w20 ) { // w1 --> w2=u1 --> u2
refines.add( new SketchRefinement( tri10, u1, u12, w120 ) );
}
if ( skipped_triangle ) {
Toast.makeText( mActivity, R.string.few_line_points, Toast.LENGTH_SHORT ).show();
} else {
// Log.v("DistoX", "refinements " + refines.size() );
// NOW GET the inside triangles. extend border a little
// float x = 0;
// float y = 0;
// for ( PointF p : border ) { x += p.x; y += p.y; }
// x /= border.size();
// y /= border.size();
// // StringWriter sw = new StringWriter();
// // PrintWriter pw = new PrintWriter( sw );
// for ( PointF p : border ) {
// p.x += 0.1f * (p.x - x );
// p.y += 0.1f * (p.y - y );
// // pw.format(Locale.US, "%.2f %.2f ", p.x, p.y );
// }
// Log.v( "DistoX", " border " + sw.getBuffer().toString() );
mModel.setRefinement( refines );
// mModel.setEditLine( edit_line );
// mModel.setBorder( border );
// mModel.doRefinement( );
// Log.v( "DistoX", "border " + border.size() + " inside triangles " + ntin );
}
}
} else if ( mEdit == SketchDef.EDIT_STRETCH /* || mEdit == SketchDef.EDIT_EXTRUDE */ ) {
// TODO convert mCurrentLinePath (DrawingLinePath) to 3D line
ArrayList<Vector> pts = new ArrayList<Vector>();
LinePoint p1 = mCurrentLinePath.mFirst;
float x = mInfo.canvasToSceneX( p1.mX );
float y = mInfo.canvasToSceneY( p1.mY );
pts.add( mInfo.sceneToWorld( x, y ) );
for ( LinePoint p2 = p1.mNext; p2 != null; p2 = p2.mNext ) {
x = mInfo.canvasToSceneX( p2.mX );
y = mInfo.canvasToSceneY( p2.mY );
pts.add( mInfo.sceneToWorld( x, y ) );
}
// if ( mEdit == SketchDef.EDIT_EXTRUDE ) { // line is the path along which to extrude the new surface
// mModel.makeExtrude( pts );
// } else if ( mEdit == SketchDef.EDIT_STRETCH ) {
mModel.makeStretch( pts );
// }
mEdit = SketchDef.EDIT_NONE;
}
// NOTE EDIT_CUT is done immediately on the surface insideTriangles
}
}
} else if ( mMode == SketchDef.MODE_SELECT ) {
if ( mMoveSelected ) {
// TODO ???
}
}
}
}
return true;
}
private void askDeleteLine( final SketchLinePath line )
{
TopoDroidAlertDialog.makeAlert( mActivity, getResources(),
getResources().getString( R.string.line_delete ) + " ?",
new DialogInterface.OnClickListener() {
@Override
public void onClick( DialogInterface dialog, int btn ) {
doDeleteLine( line );
}
} );
}
void doDeleteLine( SketchLinePath line )
{
mModel.deleteLine( line );
}
// ----------------------------------------------------------------------
// CLICK
public void onClick(View view)
{
if ( onMenu ) {
closeMenu();
return;
}
dismissPopups();
if ( mTimer != null ) mTimer.mRun = false;
Button b = (Button)view;
if ( b == mImage ) {
if ( mMenu.getVisibility() == View.VISIBLE ) {
mMenu.setVisibility( View.GONE );
onMenu = false;
} else {
mMenu.setVisibility( View.VISIBLE );
onMenu = true;
}
return;
}
// if ( b == selectBtn ) {
// if ( mSelect == SketchDef.SELECT_SECTION ) {
// setSelect( SketchDef.SELECT_STEP );
// } else if ( mSelect == SketchDef.SELECT_STEP ) {
// setSelect( SketchDef.SELECT_SHOT );
// } else if ( mSelect == SketchDef.SELECT_SHOT ) {
// setSelect( SketchDef.SELECT_JOIN );
// } else if ( mSelect == SketchDef.SELECT_JOIN ) {
// setSelect( SketchDef.SELECT_SECTION );
// }
// // FIXME (new SketchSelectDialog(mActivity, this)).show();
// } else
if ( b == mButton1[0] || b == mButton2[0] || b == mButton3[0] || b == mButton4[0] ) {
makePopupMode( b );
} else if ( b == mButton1[1] ) { // one
mInfo.resetDirection(); // azi = 0, clino = 0, and compute triad versors
resetZoom();
// doSaveTh3AndReload( ); // save to th3
// mSketchSurface.isDrawing = true;
} else if ( b == mButton1[2] ) { // display mode. cycle (NGBH, SINGLE, ALL)
(new SketchModeDialog( mActivity, mModel )).show();
} else if ( b == mButton1[3] ) { // surface
if ( mModel.mCurrentSurface != null ) {
alertMakeSurface( );
} else {
doMakeSurface( );
}
} else if ( b == mButton1[4] ) { // download
if ( mApp.mDevice != null ) {
// TODO if there is an empty shot use it, else try to download the data
// with the Asynch task that download the data.
// if there is an empty shot assign it
mActivity.setTitleColor( TDConst.COLOR_CONNECTED );
ListerHandler handler = new ListerHandler( this ); // FIXME LISTER
new DataDownloadTask( mApp, handler ).execute();
// new DataDownloadTask( mApp, this ).execute();
} else {
Toast.makeText( mActivity, R.string.device_none, Toast.LENGTH_SHORT ).show();
}
} else if ( b == mButton1[5] ) { // notes
(new DistoXAnnotations( mActivity, mData.getSurveyFromId(mSid) )).show();
} else if ( b == mButton1[6] ) { // info
// float azimuth = -1;
new DistoXStatDialog( mActivity, mNum, mInfo.start, -1, mData.getSurveyStat( mApp.mSID ) ).show();
} else if ( b == mButton2[1] ) { // undo
mModel.undo();
} else if ( b == mButton2[2] ) { // redo
mModel.redo();
} else if ( b == mButton2[3] ) { // symbols
if ( TDSetting.mPickerType == TDSetting.PICKER_RECENT ) {
new ItemRecentDialog(mActivity, this, mType ).show();
} else {
new ItemPickerDialog(mActivity, this, mType, mSymbol ).show();
}
} else if ( b == mButton3[1] ) { // refine triangles
// extrudeRegion();
// Log.v("DistoX", "refine to max side ");
int split = mModel.refineToMaxSide( TDSetting.mSketchSideSize );
if ( split == 0 ) {
Toast.makeText( mActivity, getString(R.string.sketch_no_split), Toast.LENGTH_SHORT ).show();
}
} else if ( b == mButton3[2] ) { // refine_center
mModel.refineSurfaceAtCenters();
} else if ( b == mButton3[3] ) { // refine_sides
mModel.refineSurfaceAtSides();
} else if ( b == mButton3[4] && mCurrentLinePath != null ) { // cut
cutRegion();
} else if ( b == mButton3[5] && mCurrentLinePath != null ) { // stretch
stretchRegion();
} else if ( b == mButton4[1] ) {
// TODO previous
} else if ( b == mButton4[2] ) {
// TODO next
} else if ( b == mButton4[3] ) {
mModel.refineSurfaceAtSelectedVertex();
} else if ( b == mButton4[4] ) {
// TODO edit item
}
}
// void setSelect( int select )
// {
// mSelect = select;
// setMode( ( select != SketchDef.SELECT_NONE )? SketchDef.MODE_EDIT : SketchDef.MODE_MOVE );
// }
// ----------------------------------------------------------------
// SECTION
// void setSectionType( int type )
// {
// mModel.setSectionType( type );
// mSectionType = type;
// }
void startSectionDialog()
{
}
void addSection()
{
}
// ----------------------------------------------------------------
// void setHeading( float heading )
public void setBearingAndClino( float heading, float clino )
{
mInfo.resetDirection( heading, 0.0f ); // from the side
// mCompass = null;
setMode( SketchDef.MODE_MOVE );
}
// ----------------------------------------------
// MENU
private void setMenuAdapter( Resources res )
{
// HOVER
// mMenuAdapter = new MyMenuAdapter( mActivity, this, mMenu, R.layout.menu, new ArrayList< MyMenuItem >() );
mMenuAdapter = new ArrayAdapter<String>(mActivity, R.layout.menu );
mMenuAdapter.add( res.getString( menus[0] ) );
mMenuAdapter.add( res.getString( menus[1] ) );
mMenuAdapter.add( res.getString( menus[2] ) );
mMenuAdapter.add( res.getString( menus[3] ) );
mMenuAdapter.add( res.getString( menus[4] ) );
mMenuAdapter.add( res.getString( menus[5] ) );
mMenu.setAdapter( mMenuAdapter );
mMenu.invalidate();
}
private void closeMenu()
{
mMenu.setVisibility( View.GONE );
// HOVER
// mMenuAdapter.resetBgColor();
onMenu = false;
}
private void handleMenu( int pos )
{
closeMenu();
int p = 0;
if ( p++ == pos ) { // EXPORT
// new SketchSaveDialog( mActivity, this ).show();
new ExportDialog( mActivity, this, TDConst.mSketchExportTypes, R.string.title_plot_save ).show();
} else if ( p++ == pos ) { // PALETTE
BrushManager.makePaths( getResources() );
(new SymbolEnableDialog( mActivity, mApp )).show();
} else if ( p++ == pos ) { // DELETE
askDelete();
} else if ( p++ == pos ) { // SETTINGS
Intent optionsIntent = new Intent( mActivity, TopoDroidPreferences.class );
optionsIntent.putExtra( TopoDroidPreferences.PREF_CATEGORY, TopoDroidPreferences.PREF_CATEGORY_SKETCH );
mActivity.startActivity( optionsIntent );
} else if ( p++ == pos ) { // HEADING
setMode( SketchDef.MODE_MOVE );
// SensorManager sm = (SensorManager)getSystemService( Context.SENSOR_SERVICE );
// mCompass = new SketchCompassSensor( mActivity, sm, TDSetting.mCompassReadings );
mTimer = new TimerTask( mActivity, this );
mTimer.execute();
} else if ( p++ == pos ) { // HELP
int nn = mNrButton1 + mNrButton2 - 3 + mNrButton3 - 3 + mNrButton4 - 3;
(new HelpDialog(mActivity, izons, menus, help_icons, help_menus, nn, menus.length ) ).show();
}
}
void doDelete()
{
mData.deleteSketch( mPid, mSid );
finish();
}
private void askDelete()
{
TopoDroidAlertDialog.makeAlert( mActivity, getResources(), R.string.sketch_delete,
new DialogInterface.OnClickListener() {
@Override
public void onClick( DialogInterface dialog, int btn ) {
doDelete();
}
} );
}
public void doExport( String type )
{
int index = TDConst.sketchExportIndex( type );
switch ( index ) {
case TDConst.DISTOX_EXPORT_TH3: doSaveTh3( false ); break;
case TDConst.DISTOX_EXPORT_DXF: doSaveDxf(); break;
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id)
{
if ( mMenu == (ListView)parent ) {
handleMenu( pos );
}
}
// ------------------------------------------------------------------------
// HIGHLIGHT - EXTRUSION
// void highlightRegion() { mModel.highlightLineRegion( ); }
private void cutRegion()
{
mModel.doRefinement();
mModel.makeCut( );
}
// private void extrudeRegion() { prepareEditRegion( SketchDef.EDIT_EXTRUDE ); }
private void stretchRegion() { prepareEditRegion( SketchDef.EDIT_STRETCH ); }
private void prepareEditRegion( int edit )
{
mModel.doRefinement();
mEdit = edit;
mSymbol = Symbol.LINE;
mCurrentLine = 0;
mTouchMode = SketchDef.TOUCH_MOVE;
setMode( SketchDef.MODE_EDIT );
// computeReferenceFrame( false );
// setSurfaceTransform( 0, 0 );
}
// ------------------------------------------------------------------------------
// MAKE SURFACE
/** (x,y) quadrant ( 0:TL 1:BL 2:BR 3:TR )
* 0 | 3
* ----+----
* 1 | 2
*/
// int getQuad( float x, float y )
// {
// if ( x < 0 ) {
// return ( y < 0 )? 0 : 1;
// }
// return ( y > 0 )? 2 : 3;
// }
/** quadrants start point
* @param q quadrant
* @param xc center X coord
* @param yc center Y coord
* @param r radius
*/
// PointF getQuadStart( int q, float xc, float yc, float r )
// {
// switch ( q ) {
// case 0: return new PointF( xc, yc-r ); // Top Left
// case 1: return new PointF( xc-r, yc ); // Bottom Left
// case 2: return new PointF( xc, yc+r ); // Bottom Right
// case 3: return new PointF( xc+r, yc ); // Top Right
// }
// return null;
// }
public void doMakeSurface( )
{
// FIXME CONVEX HULL SURFACE
// mModel.makeSurface();
mModel.makeConvexSurface();
}
public void removeSurface( boolean with_sections )
{
mModel.removeSurface( with_sections );
}
// private void doMakeSurfaceDialog( )
// {
// // new SketchSurfaceDialog( mSketchSurface.getContext(), this ).show();
// mModel.computeShapeSize();
// new SketchShape( mSketchSurface.getContext(), mModel.mShapeSize, this ).show();
// }
@Override
public boolean onSearchRequested()
{
// TDLog.Error( "search requested" );
Intent intent = new Intent( mActivity, TopoDroidPreferences.class );
intent.putExtra( TopoDroidPreferences.PREF_CATEGORY, TopoDroidPreferences.PREF_CATEGORY_SKETCH );
mActivity.startActivity( intent );
return true;
}
@Override
public boolean onKeyDown( int code, KeyEvent event )
{
if ( dismissPopups() ) return true;
switch ( code ) {
case KeyEvent.KEYCODE_BACK: // HARDWARE BACK (4)
super.onBackPressed();
return true;
case KeyEvent.KEYCODE_SEARCH:
return onSearchRequested();
case KeyEvent.KEYCODE_MENU: // HARDWRAE MENU (82)
String help_page = getResources().getString( R.string.SketchWindow );
if ( help_page != null ) UserManualActivity.showHelpPage( mActivity, help_page );
return true;
// case KeyEvent.KEYCODE_VOLUME_UP: // (24)
// case KeyEvent.KEYCODE_VOLUME_DOWN: // (25)
default:
// TDLog.Error( "key down: code " + code );
}
return false;
}
// ----------------- ILister interface --------------------------------------------
@Override
public void setRefAzimuth( float azimuth, long fixed_extend ) { }
// forward to the ShotWindow
@Override
public void updateBlockList( DistoXDBlock blk )
{
mApp.mShotWindow.updateBlockList( blk );
// FIXME FIXME updateDisplay( true, true );
}
@Override
public void updateBlockList( long blk_id )
{
mApp.mShotWindow.updateBlockList( blk_id );
// FIXME FIXME updateDisplay( true, true );
}
@Override
public void refreshDisplay( int nr, boolean toast )
{
mActivity.setTitleColor( TDConst.COLOR_NORMAL );
if ( nr >= 0 ) {
if ( nr > 0 ) {
List<DistoXDBlock> list = mData.selectAllShots( mSid, TopoDroidApp.STATUS_NORMAL );
recreateNum( list );
}
Toast.makeText( mActivity, getResources().getQuantityString(R.plurals.read_data, nr, nr ), Toast.LENGTH_SHORT ).show();
} else if ( nr < 0 ) {
Toast.makeText( mActivity, mApp.DistoXConnectionError[ -nr ], Toast.LENGTH_SHORT ).show();
}
}
@Override
public void setConnectionStatus( int status )
{
/* TODO */
}
// --------------------------------------------------
// MODE
private PopupWindow mPopupMode = null;
/** mode popup
* @param b button
*/
private void makePopupMode( View b )
{
if ( mPopupMode != null ) return;
final Context context = this;
LinearLayout popup_layout = new LinearLayout(this);
popup_layout.setOrientation(LinearLayout.VERTICAL);
int lHeight = LinearLayout.LayoutParams.WRAP_CONTENT;
int lWidth = LinearLayout.LayoutParams.WRAP_CONTENT;
String text = getString(R.string.title_move);
int len = text.length();
Button myTextView0 = CutNPaste.makePopupButton( this, text, popup_layout, lWidth, lHeight,
new View.OnClickListener( ) {
public void onClick(View v) {
dismissPopupMode();
setMode( SketchDef.MODE_MOVE );
}
} );
text = getString(R.string.title_draw);
if ( len < text.length() ) len = text.length();
Button myTextView1 = CutNPaste.makePopupButton( this, text, popup_layout, lWidth, lHeight,
new View.OnClickListener( ) {
public void onClick(View v) {
dismissPopupMode();
setMode( SketchDef.MODE_DRAW );
}
} );
text = getString(R.string.title_contour);
if ( len < text.length() ) len = text.length();
Button myTextView2 = CutNPaste.makePopupButton( this, text, popup_layout, lWidth, lHeight,
new View.OnClickListener( ) {
public void onClick(View v) {
dismissPopupMode();
setMode( SketchDef.MODE_EDIT );
}
} );
text = getString(R.string.title_select);
if ( len > text.length() ) len = text.length();
Button myTextView3 = CutNPaste.makePopupButton( this, text, popup_layout, lWidth, lHeight,
new View.OnClickListener( ) {
public void onClick(View v) {
dismissPopupMode();
setMode( SketchDef.MODE_SELECT );
}
} );
text = getString(R.string.title_step);
if ( len > text.length() ) len = text.length();
Button myTextView4 = CutNPaste.makePopupButton( this, text, popup_layout, lWidth, lHeight,
new View.OnClickListener( ) {
public void onClick(View v) {
dismissPopupMode();
setMode( SketchDef.MODE_STEP );
}
} );
FontMetrics fm = myTextView0.getPaint().getFontMetrics();
// Log.v("DistoX", "font metrics TOP " + fm.top + " ASC. " + fm.ascent + " BOT " + fm.bottom + " LEAD " + fm.leading );
int w = (int)( Math.abs( ( len + 1 ) * fm.ascent ) * 0.7);
int h = (int)( (Math.abs(fm.top) + Math.abs(fm.bottom) + Math.abs(fm.leading) ) * 7 * 1.70);
// int h1 = (int)( myTextView0.getHeight() * 7 * 1.1 ); this is 0
myTextView0.setWidth( w );
myTextView1.setWidth( w );
myTextView2.setWidth( w );
myTextView3.setWidth( w );
myTextView4.setWidth( w );
// Log.v( TopoDroidApp.TAG, "popup width " + w );
mPopupMode = new PopupWindow( popup_layout, w, h );
// mPopupMode = new PopupWindow( popup_layout, popup_layout.getHeight(), popup_layout.getWidth() );
mPopupMode.showAsDropDown(b);
}
private boolean dismissPopupMode()
{
if ( mPopupMode != null ) {
mPopupMode.dismiss();
mPopupMode = null;
return true;
}
return false;
}
private boolean dismissPopups()
{
return dismissPopupMode();
}
}