/
nea
/
androidGroupBuilder
Обзор
Документация
Войти
/
nea
/
androidGroupBuilder
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
app/src/main/java/com/ea/groupbuilder/NormalSubgrActivity.java
869 строк
38 KB
ea
Группа Автоморфизмов отлажено 23_04_2026
23 апр 2026, 17:08
23 апр 2026, 17:08
4513276
Код
Авторство
О чём код?
package com.ea.groupbuilder; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.app.AlertDialog; import android.content.Intent; import android.content.pm.ActivityInfo; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import android.view.ViewConfiguration; import android.widget.PopupMenu; import android.widget.TextView; import com.google.android.material.floatingactionbutton.FloatingActionButton; public class NormalSubgrActivity extends AppCompatActivity implements SurfaceHolder.Callback { // Построение Схемы нормальных подгрупп, строит только для текущей подгруппы, Sn не участыует private final static String TAG = "GRUGRA_NORML"; final static private boolean DISPLAYLOG = false; public Canvas canvas = null; public boolean IsCreateNorm = false; // не созданы private PaintAllNorm paintKal = null; final static private Paint paintTxt = new Paint(Paint.ANTI_ALIAS_FLAG), // текст и тонкие paintSubs = new Paint(Paint.ANTI_ALIAS_FLAG), // заголовок и толстые линии paintCount = new Paint(Paint.ANTI_ALIAS_FLAG), paintLine = new Paint(Paint.ANTI_ALIAS_FLAG), paintCirc = new Paint(Paint.ANTI_ALIAS_FLAG); // круг private DbHelper dbH; private mAplication mApp; public substitutionS classSubs; private static SQLiteDatabase db = null; private SurfaceView view; public FloatingActionButton fab; private TextView txtSoor; final static int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout(); private long mOldClicktime = 0L; private float xTopOld = 0f, yTopOld = 0f; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); setContentView(R.layout.activity_norm_sub); view = findViewById(R.id.norm_view); // requestWindowFeature(Window.FEATURE_NO_TITLE); txtSoor = findViewById(R.id.grzak_norm); view.getHolder().addCallback(this); mApp = (mAplication) getApplication(); mApp.activityNormal = this; dbH = mApp.dbH; db = dbH.getReadableDatabase(); classSubs = mApp.classSubs; setTitle("Вложенность нормальных подгрупп"); DbHelper.err = ""; dbH.f_getParm(0, 7, 0); paintSubs.setStyle(Paint.Style.FILL); paintSubs.setStrokeWidth(1.2f); paintSubs.setTextSize(22); paintSubs.setARGB(255, 0, 0, 0); paintCirc.setStyle(Paint.Style.STROKE); paintCirc.setStrokeWidth(3); paintCirc.setARGB(255, 0, 181, 0); paintTxt.setStyle(Paint.Style.STROKE); paintTxt.setStrokeWidth(0.8f); paintTxt.setTextSize(18); paintTxt.setARGB(255, 0, 0, 0); paintCount.setStyle(Paint.Style.STROKE); paintCount.setStrokeWidth(0.8f); paintCount.setTextSize(15); paintCount.setARGB(255, 255, 0, 0); paintLine.setStyle(Paint.Style.STROKE); paintLine.setStrokeWidth(0.8f); paintLine.setTextSize(15); paintLine.setARGB(255, 0, 255, 0); faktData.clear(); maxCounDeg = dbH.f_getCount("select max(deg) as ccc from soc_list" + mApp.tableNameEnd + " \n" + "where dubl_flag = 0;"); countLevel = dbH.f_getCount("select max(nrow) as ccc from soc_list" + mApp.tableNameEnd + " where dubl_flag = 0;"); // уровней maxItematRow = dbH.f_getCount("select max(cc) as ccc from (\n" + // max на 1 уровне + 2 "select count(nrow) as cc, nrow \n" + "from soc_list" + mApp.tableNameEnd + " where dubl_flag = 0\n" + "group by nrow\n" + "order by nrow asc\n" + ");") + 2; view.setOnTouchListener ( (v, event) -> { final ViewConfiguration conf = ViewConfiguration.get(getApplicationContext()); // системные параметры для DblCklick int action = event.getAction(); int actionCode = action & MotionEvent.ACTION_MASK; // код действия: нажатие, отпускание,... int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; float xt = event.getX(pointerIndex), yt = event.getY(pointerIndex); float deltaX = xTopOld - xt, deltaY = yTopOld - yt; float delta2 = deltaX * deltaX + deltaY * deltaY; float velocity = 0f; long time_now = event.getEventTime(); long deltaTime = time_now - mOldClicktime; if (deltaTime > 0) velocity = (float) (500f * Math.sqrt(delta2) / deltaTime); switch (actionCode) { case MotionEvent.ACTION_DOWN: // 0 case MotionEvent.ACTION_POINTER_DOWN: // 5 for (int j = 0; j < faktData.size(); j++) { dataItem dItem = faktData.get(j); if (dItem.f_test(xt, yt)) dItem.clickFlag = !dItem.clickFlag; } xTopOld = xt; yTopOld = yt; mOldClicktime = time_now; txtSoor.setText(""); break; case MotionEvent.ACTION_MOVE: // 2 if (deltaTime < DOUBLE_TAP_TIMEOUT) { if (velocity >= conf.getScaledMinimumFlingVelocity()) f_popClear(); } break; case MotionEvent.ACTION_POINTER_UP: // 6 case MotionEvent.ACTION_CANCEL: // 3 default: break; } v.performClick(); return true; } ); fab = findViewById(R.id.fab); fab.setOnClickListener(view -> { kolvoItemClick = 0; // считаю количество выбранных подгрупп for (int j = 0; j < faktData.size(); j++) { if (faktData.get(j).clickFlag) kolvoItemClick++; } txtSoor.setText(""); if (DISPLAYLOG) Log.e(TAG, "fab kolvoItemClick=" + kolvoItemClick ); if (kolvoItemClick == 1) { PopupMenu popupMenu = new PopupMenu(getApplicationContext(), fab); popupMenu.inflate(R.menu.manu_norm_popup); popupMenu.show(); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.action_norm_klass: f_popList(1); return true; case R.id.action_norm_prop: f_popProp(); return true; case R.id.action_norm_list: f_popList(0); // Элементы подгруппы return true; case R.id.action_norm_clear: // Отменить все выделения f_popClear(); return true; default: return false; } } }); } else if (kolvoItemClick > 1) { PopupMenu popupMenu = new PopupMenu(getApplicationContext(), fab); popupMenu.inflate(R.menu.menu_norm_pop_many); popupMenu.show(); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.action_norm_many_klass: f_popListMamy(2); // 2 - Общие классы подгрупп return true; case R.id.action_norm_many_list: f_popListMamy(3); // 3 - Общие элементы подгрупп return true; case R.id.action_norm_many_clear: // Отменить все выделения f_popClear(); return true; default: return false; } } }); } else { // 0 выбрано PopupMenu popupMenu = new PopupMenu(getApplicationContext(), fab); popupMenu.inflate(R.menu.menu_norm_popup_select); popupMenu.show(); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.action_norm_0: f_popSelect(0); // return true; case R.id.action_norm_1: f_popSelect(1); // return true; case R.id.action_norm_2: f_popSelect(2); // return true; case R.id.action_norm_3: f_popSelect(3); // return true; case R.id.action_norm_4: f_popSelect(4); // return true; case R.id.action_norm_5: f_popSelect(5); // return true; case R.id.action_norm_6: f_popSelect(6); // return true; case R.id.action_norm_7: f_popSelect(7); // return true; case R.id.action_norm_8: f_popSelect(8); // return true; default: return false; } } }); } }); } static final String txtCoob[] ={"цоколевые подгруппы", "силовские подгруппы", "коммутанты", "цоколь", "центр группы", "подгруппа четных подстановок", "подгруппы содержащая класс ", "ядра действия на силовских подгруппах", "подгруппы прямых произведений" }; private void f_popSelect(int kod) { // выбрать подгруппы с заданным свойством // 0 numSoc номер цоколевой подгр // 1 sylow_num // 2 comm_level // 3 soc_level // 4 centr_flag // 5 even_flag // 6 count_klass // 7 epi_pe // 8 summa_num txtSoor.setText("Выделено: " + txtCoob[kod]); if (kod == 6) { AdapterShowList adapterList = new AdapterShowList(this); adapterList.f_selectCodForNorm(this, dbH); adapterList.f_showList(); return; } for (int j = 0; j < faktData.size(); j++) if (faktData.get(j).prop[kod] > 0) faktData.get(j).clickFlag = true; } public void f_go(int choslo) { // сюда adapterList передает введенное число if (DISPLAYLOG) Log.e(TAG, "f_go choslo=" + choslo ); int i = dbH.f_getMas("select distinct num_maim || '' as stext from sub_structure" + mApp.tableNameEnd + " where num_subs = "+ choslo + " order by stext;"); int k, j, m, kk = faktData.size(); txtSoor.setText("Выделены " + txtCoob[6] + choslo); for (k = 0; k<i; k++) { m = Integer.parseInt(DbHelper.selectedMas[k].trim()); for (j = 0; j < kk; j++) if (faktData.get(j).numKlass == m) faktData.get(j).clickFlag = true; } } private void f_popClear() { // Отменить все выделения for (int j = 0; j < faktData.size(); j++) faktData.get(j).clickFlag = false; } private void f_popListMamy(int cod) { if (DISPLAYLOG) Log.e(TAG, "f_popListMamy = " + cod ); AdapterShowList adapterList = new AdapterShowList(this); adapterList.f_setNormal(this, dbH, faktData, cod); adapterList.f_showList(); } private void f_popList(int cod) { if (DISPLAYLOG) Log.e(TAG, "f_popList = " ); AdapterShowList adapterList = new AdapterShowList(this); adapterList.f_setNormal(this, dbH, faktData, cod); adapterList.f_showList(); } private void f_popProp() { String str; if (kolvoItemClick > 1) str = "Должна быть выбрана 1 подгруппа"; else { dataItem datIt = faktData.get(0); for (int j = 0; j < faktData.size(); j++) { if (faktData.get(j).clickFlag) { datIt = faktData.get(j); break; } } str = "Подгруппа № " + datIt.numKlass + " уровень "+ datIt.level + "\n"+ " Порядок " + datIt.count + ", состоит из " + datIt.prop[6] + " классов\n"; if (datIt.xarac ) str += "Характеристическая\n"; if (datIt.prop[4] > 0) str += "Содержится в центре\n"; if (datIt.prop[5] > 0) str += "Содержит четные подстановки\n"; if (datIt.prop[2] > 0) str += "Содержится в коммутанте\n"; if (datIt.prop[1] > 0) str += "Подгруппа силова № " + datIt.prop[1] + "\n"; if (datIt.prop[0] > 0) str += "Подгруппа цоколя № " + datIt.prop[0] + "\n"; else { if (datIt.prop[3] > 0) str += "Содержится в цоколе " + datIt.prop[3] + "\n"; } /* private int numKlass, numSoc, count, // номер подгр, цоколя, уровня, число элементов npp, cItem, level, sylow_num. comm_level, soc_level, centr_flag, even_flag, count_klass; // свойства подгруппы из soc_list */ } AlertDialog.Builder builderNorm; builderNorm = new AlertDialog.Builder(this); builderNorm.setMessage(str) .setNegativeButton("Выход", null) .setIcon(R.drawable.textview_border) .show(); if (DISPLAYLOG) Log.e(TAG, "f_popProp kolvoItemClick=" + kolvoItemClick + " " + str ); } public void repaint() { if (IsCreateNorm) { if (DISPLAYLOG) Log.e(TAG, "repaint sh2= " + sh2); if (paintKal == null) startPotok(); } } @Override protected void onStop( ) { super.onStop() ; if (DISPLAYLOG) Log.e(TAG, "=== onStop" ); stopPotok(); mApp.activityNormal = null; } @Override protected void onDestroy( ) { super.onDestroy() ; if (DISPLAYLOG) Log.e(TAG, "=== onDestroy" ); stopPotok(); } @Override protected void onRestart( ) { super.onRestart() ; if (DISPLAYLOG) Log.e(TAG, "=== onRestart" ); } @Override protected void onPause() { super.onPause(); //Log.e("SQL", "=== onPause txtKak="+txtKak ); stopPotok(); } public void startPotok() {// запустить поток для рисования for (int j = 0; j <= countLevel; j++) // countLevel + 1 f_createLevel(j); // рисование уровня j f_buildDop(); // построение доп связей if (maxCounDeg < DbHelper.countElements) { // нет всей группы в soc_list - добавить всю группу на уровень 0 plusLevl = 1; // подгруппа 0 = вся группа // faktData.add(new dataItem(0, 0, DbHelper.countElements, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0)); } paintKal = new PaintAllNorm(this, view); paintKal.setRunning(true); paintKal.setName("paintNornal"); paintKal.setPriority(1); paintKal.start(); // запустить поток if (DISPLAYLOG) Log.e(TAG, "startPotok " ); } public void stopPotok() {// остановить поток рисования if (paintKal != null) { if (paintKal.running.get()) { paintKal.stopPotok(); boolean retry = true; while (retry) { try {// ожидание завершение потока paintKal.join(); retry = false; } catch (InterruptedException e) { Log.e(TAG, "Error stopPotok " + e.toString()); // Toast.makeText(getApplicationContext(), "Error stopPotok " + e.toString(), //??? Toast.LENGTH_LONG).show(); } } } paintKal = null; } } public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_normal, menu); return super.onCreateOptionsMenu(menu); } private boolean whoWrite = true; // писать порядки подгрупп, иначе - число классов public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_exit_normal: finish(); break; case R.id.action_help_normal: Intent intent = new Intent(NormalSubgrActivity.this, helpActivity.class); startActivity(intent); break; case R.id.action_normal_txt: item.setChecked(! item.isChecked()); whoWrite = item.isChecked(); if (whoWrite) item.setTitle("Отобразить число классов"); else item.setTitle("Отобразить порядки подгрупп"); // Log.e(TAG, "menus whoWrite = " + whoWrite); break; } return super.onOptionsItemSelected(item); } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { if (DISPLAYLOG) Log.e(TAG, "surfaceChanged width=" + width +" height="+ height ); IsCreateNorm = true; repaint(); } @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { IsCreateNorm = true; repaint(); } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { IsCreateNorm = false; } static private int kolvoItemClick = 0; // количество выбранных подгрупп static private int sh2 = 0; // высота элемента + отступ static private int hSpace = 0; // h отступа static private int radius = 0; private static int maxCounDeg = 0, // мах порядок подгруппы в soc_list plusLevl = 0, // прибавлять или нет (=1) общую группу на уровень 0 и остальные сдвинуть +1 countLevel = 0, // уровней maxItematRow; // max на 1 уровне + 2 // CREATE TABLE normal_subgroup (_id INTEGER primary key autoincrement, num_maim INTEGER NOT NULL, order_main INTEGER, num_sub INTEGER NOT NULL, order_sub INTEGER) public static List<dataItem> faktData = new ArrayList<>(); // хранилище подгрупп для рисования private void f_paint() { // рисование if (IsCreateNorm) { canvas.drawColor(Color.WHITE); canvas.save(); int sh = canvas.getHeight(); // размеры экрана, размер int sw = canvas.getWidth(); paintSubs.setARGB(255, 0, 0, 0); canvas.drawText( (mApp.tableNameEnd.equals("_a") ? "Автоморфизмы " : "") + mApp.groupName, 17f, sh / 20f, paintSubs); paintSubs.setARGB(255, 218, 165, 32); int xHole, iL1 = (int) sh / 15; sh -= iL1; // поднять все sh - высота экрана if (maxCounDeg < DbHelper.countElements) { // нет всей группы в soc_list - добавить всю группу на уровень 0 sh2 = (int) ((sh - iL1) / (countLevel + 3)); // высота элемента + отступ } else sh2 = (int) ((sh - iL1) / (countLevel + 2)); // высота элемента + отступ // высота элемента int hElement = (int) (0.35 * sh2); // высота элемента // высота элемента int wElement = (int) (0.7 * sw / maxItematRow); // на 1 итем по ширине radius = Math.min(wElement, hElement) / 2; hSpace = sh2 - 2 * radius; // Log.e(TAG, "f_paint sh=" + sh + " countLevel= "+ countLevel +" iL1="+ iL1+ " sh2 = " + sh2 + " hElement=" + hElement+ " radius=" + radius); // Log.e(TAG, "f_paint sw=" + sw +" maxItematRow="+ maxItematRow+ " wElement=" + wElement+ " radius=" + radius); for (int k = 0; k < faktData.size(); k++) { dataItem dItem = faktData.get(k); xHole = (sw - (2 * dItem.cItem * radius)) / (dItem.cItem + 1); // длина дырки // Log.e(TAG, "f_paint k=" + k +" xHole="+ xHole+ " dItem.cItem=" + dItem.cItem+ " numKlass=" + dItem.numKlass + " npp="+ dItem.npp + " level=" + dItem.level); dItem.f_draw(xHole); } canvas.restore(); } } private void f_createLevel(int level) { // на уровня level дополняет список faktData if (DISPLAYLOG) Log.e(TAG, "f_createLevel level=" + level); final int cItem = dbH.f_getCount("select count(nrow) as ccc \n" + // число групп на уровне "from soc_list" + mApp.tableNameEnd + " where dubl_flag = 0 and nrow = " + level + ";"); int npp = 0, j, kl, nSoc, deg, num_maim, comm_level, soc_level, centr_flag, even_flag, count_klass, sylow_num, summa_num, epi_pe; // создание кружков String sSQL = "select num_klass, num, 0 as num_maim, deg, comm_level, sylow_num, \n" + // только сами группы без главной " soc_level, centr_flag, even_flag, count_klass, ncol, summa_num + 1 as summ, epi_pe\n " + " from soc_list" + mApp.tableNameEnd + " where dubl_flag = 0 and nrow = " + level + " order by ncol asc;"; Cursor cur1Crete = db.rawQuery(sSQL, null); cur1Crete.moveToFirst(); if (cur1Crete.getCount() > 0) { int indKl = cur1Crete.getColumnIndex("num_klass"), indSumma_num = cur1Crete.getColumnIndex("summ"), indEpi = cur1Crete.getColumnIndex("epi_pe"), indSoc = cur1Crete.getColumnIndex("num"), indsylow_num = cur1Crete.getColumnIndex("sylow_num"), indComm_level = cur1Crete.getColumnIndex("comm_level"), indSoc_level = cur1Crete.getColumnIndex("soc_level"), indCentr_flag = cur1Crete.getColumnIndex("centr_flag"), indEven_flag = cur1Crete.getColumnIndex("even_flag"), indCount_klass = cur1Crete.getColumnIndex("count_klass"), indDeg = cur1Crete.getColumnIndex("deg") ; do { kl = cur1Crete.getInt(indKl); epi_pe = cur1Crete.getInt(indEpi); summa_num = cur1Crete.getInt(indSumma_num); nSoc = cur1Crete.getInt(indSoc); deg = cur1Crete.getInt(indDeg); sylow_num = cur1Crete.getInt(indsylow_num); // num_maim = cur1Crete.getInt(indNum_maim); comm_level = cur1Crete.getInt(indComm_level); soc_level = cur1Crete.getInt(indSoc_level); centr_flag = cur1Crete.getInt(indCentr_flag); even_flag = cur1Crete.getInt(indEven_flag); count_klass = cur1Crete.getInt(indCount_klass); faktData.add( new dataItem(kl, nSoc, deg, level, npp, cItem, 0, comm_level, soc_level, centr_flag, even_flag, count_klass, sylow_num, epi_pe, summa_num)); if (mApp.tableNameEnd.length() == 0) faktData.get(faktData.size() - 1).xarac = (dbH.f_getCountRow("select porjadok from charac_group where num_subs = " + kl + ";") > 0); if (DISPLAYLOG) Log.e(TAG, "f_createLevel level=" + level + " kl=" + kl + " cItem=" + cItem + " npp=" + npp); npp++; } while (cur1Crete.moveToNext()); } cur1Crete.close(); // связи по normal_subgroup if (level > 0) { // вытаскиваю и куда она входит целиком = главная связь sSQL = "select L.num_klass as num_klass, N.num_maim as num_maim \n" + " from soc_list" + mApp.tableNameEnd + " L, normal_subgroup" + mApp.tableNameEnd + " N\n" + " where L.num_klass = N.num_sub and\n" + " L.dubl_flag = 0 and L.nrow = " + level + "\n" + " order by L.ncol asc;"; cur1Crete = db.rawQuery(sSQL, null); cur1Crete.moveToFirst(); if (cur1Crete.getCount() > 0) { int indKl = cur1Crete.getColumnIndex("num_klass"), indNum_maim = cur1Crete.getColumnIndex("num_maim"); do { kl = cur1Crete.getInt(indKl); num_maim = cur1Crete.getInt(indNum_maim); for(j=0; j<faktData.size(); j++) { if (faktData.get(j).numKlass == kl) { faktData.get(j).upperNum = num_maim; if (DISPLAYLOG) Log.e(TAG, "f_createLevel " + level + " kl=" + +kl + " --->" + num_maim); } } } while (cur1Crete.moveToNext()); } cur1Crete.close(); } } private void f_buildDop() { // построение доп связей final String sSQL = "select X.num1 as num1, X.num2 as num2, X.num_common as comm\n" + " from normal_connect X, soc_list" + mApp.tableNameEnd + " L1, soc_list" + mApp.tableNameEnd + " L2\n" + " where X.num1 = L1.num_klass and X.num2 = L2.num_klass and\n" + " (L1.nrow = (L2.nrow + 1) or (L1.nrow + 1) = L2.nrow)\n" + " order by X.num1 asc, X.num2 asc;"; if (DISPLAYLOG) Log.e(TAG, "f_buildDop f_buildDop " ); Cursor cur2Line = db.rawQuery(sSQL, null); cur2Line.moveToFirst(); if (cur2Line.getCount() > 0) { int n1, n2, n0, j, ind1 = cur2Line.getColumnIndex("num1"), ind2 = cur2Line.getColumnIndex("num2"), indComm = cur2Line.getColumnIndex("comm"); do { n1 = cur2Line.getInt(ind1); n2 = cur2Line.getInt(ind2); n0 = cur2Line.getInt(indComm); for (j = 0; j< faktData.size(); j++) if (faktData.get(j).numKlass == n1) { faktData.get(j).dopNum.add(n2); faktData.get(j).dopCount.add(n0); if (DISPLAYLOG) Log.e(TAG, "f_createLevel f_buildDop numKlass n1=" + n1 + " n2=" + n2 + " n0=" + n0 ); } } while (cur2Line.moveToNext()); } cur2Line.close(); } public class dataItem { public boolean clickFlag = false; // выбрана подгруппа public int numKlass; // номер подгр, public boolean xarac = false; // характеристическая public int [] prop ={ // свойства подгруппы из soc_list 0, // 0 numSoc номер цоколевой подгр 0, // 1 sylow_num 0, // 2 comm_level 0, // 3 soc_level 0, // 4 centr_flag 0, // 5 even_flag 0, // 6 count_klass 0, // 7 epi_pe, 0 // 8 summa_num) }; final private int count, // число элементов npp, // № п/п cItem, // число групп на уровне level; // уровень private float xn, yn; // координаты центра private int upperNum = 0; // номер подгруппы к какой надо прицепить public List<Integer> dopNum = new ArrayList<>(), // номера куда протянуть линию dopCount = new ArrayList<>(); // номер общей подгруппы для этой связи dataItem(int numKlass, int numSoc, int count, int level, int npp, int cItem, int num_maim, int comm_level, int soc_level, int centr_flag, int even_flag, int count_klass, int sylow_num, int epi_pe, int summa_num) { this.numKlass = numKlass; prop[1] = sylow_num; prop[0] = numSoc; this.count = count; this.npp = npp; this.level = level; this.cItem = cItem; upperNum = num_maim; prop[2] = comm_level; prop[3] = soc_level; prop[4] = centr_flag; prop[5] = even_flag; prop[6] = count_klass; prop[7] = epi_pe; prop[8] = summa_num; } private boolean f_test(float xT, float yT) { if(Math.sqrt((xT - xn)*(xT - xn) + (yT - yn)*(yT - yn)) < radius) return true; else return false; } private void f_draw(int lHole) { // рисовать setStrokeWidth(10); /* ---------------------> x | v y upperNum (xn.yn, radius) level = 0 numKlass (xn.yn, radius) level = 1 */ int j, k; float r2 = 2f * radius, x1, y1, x2, y2, dXar = xarac ? 10f : 0f; // характер подгруппы выделяю эллипсом if (numKlass > 0) { // 0-вая подгруппа = вся группа, когда ее нет в soc_list yn = (plusLevl + level) * (hSpace + r2) + 2f * hSpace; } else { yn = 2f * hSpace; } xn = lHole + (lHole + r2) * npp; RectF rectSyl = new RectF((float) (xn - radius), (float) (yn - radius), (float) (xn + radius), (float) (yn + radius)); paintCirc.setStyle(Paint.Style.STROKE); if (xarac) paintCirc.setARGB(255, 0, 1, 184); else paintCirc.setARGB(255, 0, 181, 0); canvas.drawCircle(xn, yn, (float) radius, paintCirc); if (clickFlag) { paintCirc.setARGB(255, 210, 105, 30); // выделенная подгруппа canvas.drawCircle(xn, yn, (float) radius + 4f, paintCirc); } paintCirc.setStyle(Paint.Style.FILL); // заливаем canvas. drawArc(rectSyl, 0f, 360f * count / DbHelper.countElements , true, paintCirc); canvas.drawText("" + numKlass, xn - 1.3f * r2, yn - 0.17f * radius, paintTxt); if (whoWrite) canvas.drawText("" + count, (xn + 1.2f * radius), (yn + radius), paintCount); else canvas.drawText("" + prop[6], (xn + 1.2f * radius), (yn + radius), paintCount); // Log.e(TAG, "f_draw level= " + level + " numKlass="+numKlass + " upperNum="+ upperNum + " npp= " + npp + " xn =" + xn + " yn=" + yn + " radius=" + radius+ // " hSpace=" +hSpace + " lHole=" + lHole + " DbHelper.countElements="+ DbHelper.countElements+ " count=" + count); // рисовать линию if (upperNum > 0 | (plusLevl == 1 && level == 0) ) { for (j=0; j<faktData.size(); j++ ) if (faktData.get(j).numKlass == upperNum) { dataItem mItem = faktData.get(j); canvas.drawLine(xn, yn - radius, mItem.xn, mItem.yn + radius, paintLine); } } // доп линии for (k=0; k<dopNum.size(); k++) { for (j=0; j<faktData.size(); j++ ) if (faktData.get(j).numKlass == dopNum.get(k)) { dataItem mItem = faktData.get(j); if (mItem.level < level) { x1 = mItem.xn; x2 = xn; y1 = mItem.yn + radius; y2 = yn - radius; } else { x1 = xn; x2 = mItem.xn; y1 = yn + radius; y2 = mItem.yn - radius; } if (dopCount.get(k) == mItem.numKlass || dopCount.get(k) == numKlass) canvas.drawLine(x1, y1, x2, y2, paintLine); // зеленая линия = содержится полностью, желтая - частично else canvas.drawLine(x1, y1, x2, y2, paintSubs); // желтая } } } } private class PaintAllNorm extends Thread { private final NormalSubgrActivity activity; private final SurfaceView view; volatile AtomicBoolean running; public PaintAllNorm(NormalSubgrActivity cActivity, SurfaceView view) { activity = cActivity; this.view = view; running = new AtomicBoolean(); running.set(false); } /** состояния потока*/ public void setRunning(boolean run) { running.set(run); } /** в потоке */ public void run() { if (DISPLAYLOG) Log.e(TAG, "***run() " ); while (running.get()) { if (isInterrupted()) return; canvas = null; // своя ссылка на канву try { // подготовка Canvas-а canvas = view.getHolder().lockCanvas(); synchronized (view.getHolder()) { activity.f_paint(); // собственно рисование // if (DISPLAYLOG) // Log.e(TAG, "***running "); } } catch (Exception e) { StackTraceElement ste[] = e.getStackTrace(); Log.e(TAG, "***Error " + e.toString() + " running=" + running.get()); for (int i = 0; i < ste.length; i++) Log.e(TAG, "***Error " + i + " " + ste[i].getMethodName() + " line " + ste[i].getLineNumber()); // Toast.makeText(activity, "Error" + e.toString() +" "+activity.buildStep+ " "+ activity.IsKaleydoskop.get()+" running="+running.get() + " "+e.getStackTrace(), Toast.LENGTH_SHORT).show(); } finally { // try закончился if (canvas != null) { view.getHolder().unlockCanvasAndPost(canvas); } } } } public void stopPotok() { //прервать рисование running.set(false); // текущая итерация - последняя this.interrupt(); // и заканчивается она прямо сейчас } } @Override protected void onStart(){ super.onStart(); mApp.activityNormal = this; } }