/
nea
/
androidGroupBuilder
Обзор
Документация
Войти
/
nea
/
androidGroupBuilder
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
app/src/main/java/com/ea/groupbuilder/GrupActivity.java
1 233 строки
61 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.annotation.SuppressLint; import android.content.DialogInterface; 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.drawable.Drawable; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.SurfaceView; import android.view.ViewConfiguration; import android.graphics.Paint; import android.util.Log; import android.view.SurfaceHolder; import android.view.View; import android.widget.ArrayAdapter; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; import android.widget.Toast; import com.google.android.material.floatingactionbutton.FloatingActionButton; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import android.widget.PopupMenu; public class GrupActivity extends AppCompatActivity implements InputIntInterface, SurfaceHolder.Callback { // отображает основные подгруппы в виде графиков, меню Основные подгруппы private final static String TAG = "GRUGRA_GRAF"; final static private boolean DISPLAYLOG = false; final static int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout(); private DbHelper dbH; private static mAplication mApp; public substitutionS classSubs; private SurfaceView view; private PaintGrup paintGrup = null; final private colorSelector colorSlt = new colorSelector(); static private int countSylowGrup = 0; // число выдаваемых подгрупп, > 0 - число установлено и второй раз не спрашиваю volatile boolean flagSn = false; // true - отображать как подгруппу Sn public Canvas canvas = null; public boolean IsCreat = false; // не созданы public FloatingActionButton fab; static public Paint paintGraf = new Paint(Paint.ANTI_ALIAS_FLAG), paintTxt = new Paint(Paint.ANTI_ALIAS_FLAG), paintLine = new Paint(Paint.ANTI_ALIAS_FLAG); private static SQLiteDatabase db = null; private ListView tableListView; 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_grup); view = findViewById(R.id.sview); tableListView = findViewById(R.id.adb_listview); countSylowGrup = 0; f_goOtchet(); } private void f_goOtchet() { // собственно заполнение окна mApp = (mAplication) getApplication(); dbH = mApp.dbH; db = DbHelper.db; fab = findViewById(R.id.fabgrupp); stopPotok(); IsCreat = false; mApp.activityGrp = null; if (DISPLAYLOG) Log.e(TAG, "f_goOtchet() 2 colCount=" + colCount + " IsCreat=" + IsCreat); ujeYes = ujeCoob = indClick = whatToOutput = rowCount = 0; yClick = 0f; dbH.f_getParm(0, 4, flagSn ? 1 : 0); // считать число эл-тов группы,... // выбираю max число силовских подгрупп int mx = dbH.f_getCount("select max(nnn) as ccc from (\n" + "select count( distinct num) as nnn, pe from sylov_table" + mApp.tableNameEnd + "\n" + "\tgroup by pe\n" + ");"), mxFg = dbH.f_getCount("select max(nnn) as ccc from (\n" + "select count( distinct num) as nnn, pe from sylov_table_n\n" + "\tgroup by pe\n" + ");"); IsCreat = false; // не созданы if (DISPLAYLOG) Log.e(TAG, "f_goOtchet count=" + DbHelper.countElements); fab.show(); fab.setOnClickListener(view -> { int kolvoItemClick = 0; // считаю количество выбранных подгрупп for (int j = 0; j < colCount; j++) // j = столбец (# столбца) if (clickCol[j]) kolvoItemClick++; if (DISPLAYLOG) Log.e(TAG, "fab kolvoItemClick=" + kolvoItemClick); if (kolvoItemClick == 1) { PopupMenu popupMenu = new PopupMenu(getApplicationContext(), fab); popupMenu.inflate(R.menu.menu_popup_grup_one); popupMenu.show(); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.action_grup_list: // Элементы подгруппы f_clickFinger(0); return true; case R.id.action_grup_class: // Классы подгруппы f_showClass(0); return true; case R.id.action_grup_id_show_one: f_showClass(10); // Указать элемент группы return true; default: return false; } } }); } else if (kolvoItemClick > 1) { PopupMenu popupMenu = new PopupMenu(getApplicationContext(), fab); popupMenu.inflate(R.menu.menu_popup_grup_many); popupMenu.show(); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.action_grup_many_list: f_clickFinger(1); return true; case R.id.action_grup_many_class: f_showClass(1); // Общие классы подгрупп return true; case R.id.action_grup_many_clear: f_grpClaer(); // очистить все выделения return true; case R.id.action_grup_id_show_many: f_showClass(10); // Указать элемент группы return true; default: return false; } } }); } else { // ничего не выбрано PopupMenu popupMenu = new PopupMenu(getApplicationContext(), fab); popupMenu.inflate(R.menu.menu_popup_grup_common); popupMenu.show(); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.action_grup_1_class: f_showClass(2); // Отобразить один класс return true; case R.id.action_grup_n_class: f_showClass(3); // Отобразить все классы return true; case R.id.action_grup_s_class: f_showClass(4); // Отобразить все классы силовских подгрупп return true; case R.id.action_grup_c_class: f_showClass(5); // Отобразить классы цоколя return true; case R.id.action_grup_m_class: f_showClass(6); // Отобразить классы коммутанта return true; case R.id.action_grup_h_class: f_showClass(7); // Отобразить классы чентых подстановок return true; case R.id.action_grup_j_class: f_showClass(8); // Отобразить классы ядра return true; case R.id.action_grup_z_class: f_showClass(9); // Отобразить классы центра return true; case R.id.action_grup_id_show: f_showClass(10); // Указать элемент группы return true; default: return false; } } }); } }); f_grpClaer(); if (mxFg > 3 && countSylowGrup == 0) { // запрос числа силовских подгрупп для отображения inputInt iI = inputInt.newInstance(); iI.f_init(this, "Задайте число выводимых однотипных групп, их может быть "+mx + ", " + mxFg + " - для Sn.\n" + "Для большого числа трбуется много памяти!", 3); iI.show(getSupportFragmentManager(), "inputInt"); // продолжение f_go() } else { if ( countSylowGrup == 0 ) countSylowGrup = 3; f_go(countSylowGrup); } } private void f_showClass(int chego) { /* 0 - список Классов подгруппы 1 Общие классы подгрупп 2 - Отобразить один класс 3 - Отобразить все классы 4 - Отобразить все классы силовских подгрупп 5 - Отобразить классы цоколя 6 - Отобразить классы коммутанта 7 - Отобразить классы чентых подстановок 8 - Отобразить классы ядра 9 - центра 10 - указать жлемент группы */ String sqt = ""; int nn = 0; switch (chego) { case 0: case 1: new adapterShowGrupp(this, dbH, 2 + chego); break; case 2: case 4: case 8: case 10: AdapterShowList adapSel = new AdapterShowList(this); adapSel.f_selectCodForGrup(this, dbH, chego, flagSn); // установка whatToOutput в f_goClass() break; case 3: whatToOutput = 0; break; case 5: // 5 - Отобразить классы цоколя if (flagSn) sqt = "select distinct P.class_area || '' as stext from pairing_area_n P, elements_n E" + " where not E.nomer_soc isnull and E.id_true = P.id_subs order by 1 asc;"; else sqt = "select distinct P.class_area || '' as stext from pairing_area" + mApp.tableNameEnd + " P, elements" + mApp.tableNameEnd + " E" + " where not E.nomer_soc isnull and E._id = P.id_subs order by 1 asc;"; f_setListToOutput(sqt); txtShow = "Показаны классы цоколя"; break; case 6: // 6 - Отобразить классы коммутанта if (flagSn) sqt = "select distinct P.class_area || '' as stext from pairing_area_n P, elements_n E" + " where E.switchboard_num > 0 and E.id_true = P.id_subs order by 1 asc;"; else sqt = "select distinct P.class_area || '' as stext from pairing_area" + mApp.tableNameEnd + " P, elements" + mApp.tableNameEnd + " E" + " where E.switchboard_num > 0 and E._id = P.id_subs order by 1 asc;"; f_setListToOutput(sqt); txtShow = "Показаны классы коммутанта"; break; case 7: // 7 - Отобразить классы чентых подстановок if (flagSn) sqt = "select distinct P.class_area || '' as stext from pairing_area_n P, elements_n E" + " where E.parity = 0 and E.id_true = P.id_subs order by 1 asc;"; else sqt = "select distinct P.class_area || '' as stext from pairing_area" + mApp.tableNameEnd + " P, elements" + mApp.tableNameEnd + " E" + " where E.parity = 0 and E._id = P.id_subs order by 1 asc;"; f_setListToOutput(sqt); txtShow = "Показаны классы чентых подстановок"; break; case 9: // 9 - Отобразить классы центра if (flagSn) { sqt = "select distinct P.class_area || '' as stext from pairing_area_n P, elements_n E" + " where E.center_num = " + DbHelper.countElements_n + " and E.id_true = P.id_subs order by 1 asc;"; } else sqt = "select distinct P.class_area || '' as stext from pairing_area" + mApp.tableNameEnd + " P, elements" + mApp.tableNameEnd + " E" + " where E.center_num = "+ DbHelper.countElements + " and E._id = P.id_subs order by 1 asc;"; f_setListToOutput(sqt); txtShow = "Показаны классы центра"; break; } } public void f_goClass(int clac, int what) { // выбран класс (элемент) для отображения, clac = _id при String sql = ""; int k; switch (what) { case 2: // Отобразить один класс clac whatToOutput = clac; if (DISPLAYLOG) Log.e(TAG, "f_goClass 2 clac="+ clac + " what=" +what + " sql = " + sql); return; case 4: // 4 - Отобразить все классы силовских подгрупп, what = pe // CREATE TABLE sylov_table (_id INTEGER primary key autoincrement, pe INTEGER,num INTEGER, id_main INTEGER NOT NULL, id_s INTEGER NOT NULL, effort INTEGER, parity INTEGER) // CREATE TABLE pairing_area (_id INTEGER primary key autoincrement, class_area INTEGER, num INTEGER, id_subs INTEGER NOT NULL, cykl_len TEXT) if (flagSn) sql = "select distinct P.class_area || '' as stext from pairing_area_n P, sylov_table_n S " + " where P.id_subs = S.id_s and S.pe = " + clac + " order by 1 asc;"; else sql = "select distinct P.class_area || '' as stext from pairing_area" + mApp.tableNameEnd + " P, sylov_table" + mApp.tableNameEnd + " S " + " where P.id_subs = S.id_s and S.pe = " + clac + " order by 1 asc;"; txtShow = "Показаны классы всех силовских подгрупп для P = " + clac; break; case 8: // 8 - Отобразить классы ядра, what = pe if (flagSn) sql = "select distinct P.class_area || '' as stext \n" + "from epimorphism" + mApp.tableNameEnd + "_n F, pairing_area_n P \n" + "where F.id_element = P.id_subs and " + "F.pe = " + clac+ " and F.deg = 0 " + " order by 1 asc;"; else sql = "select distinct P.class_area || '' as stext \n" + "from epimorphism" + mApp.tableNameEnd + " F, pairing_area" + mApp.tableNameEnd + " P \n" + "where F.id_element = P.id_subs and " + "F.pe = " + clac+ " and F.deg = 0 " + " order by 1 asc;"; txtShow = "Показаны классы ядра при действии на силовских подгруппах для P = " + clac; break; case 10: // 10 - выбор элемента: clac = _id // if (! flagSn) for (k=0; k<dataGraph.length; k++) if (dataGraph[k].id == clac) { yClick = dataGraph[k].yPoint + (0.5f * sh / rowCount); if (DISPLAYLOG) Log.e(TAG, "f_goClass clac="+ clac + " what=" +what + " yClick = " + yClick + " rowCount = "+ rowCount + " dataGraph[k].yPoint + " + dataGraph[k].yPoint + " k= "+ k); return; } break; default: } if (DISPLAYLOG) Log.e(TAG, "f_goClass clac="+ clac + " what=" +what + " sql = " + sql); f_setListToOutput(sql); } private void f_setListToOutput(String sql) { // заполнение listToOutput по sql int i, j; whatToOutput = -1; listToOutput.clear(); i = dbH.f_getMas(sql); // DbHelper.selectedMas - заполнен классами for (j = 0; j<i; j++) { listToOutput.add(Integer.parseInt(DbHelper.selectedMas[j].trim())); // Log.e(TAG, "f_setListToOutput clac="+ i + " j=" + j + " DbHelper.selectedMas=" +DbHelper.selectedMas.length + " selectedMas="+ Integer.parseInt(DbHelper.selectedMas[j].trim()) + " sql = " + sql + " selectGrupGrid = " + DbHelper.selectGrupGrid); } } private void f_grpClaer() { // очистить все выделения в заголовках Drawable backgroundDrawable = getResources().getDrawable(R.drawable.textview_border); for (int j = 0; j < colCount; j++) { // j = столбец (# столбца) clickCol[j] = false; TextView v = findViewById(classIds.idbZ[j]); v.setBackground(backgroundDrawable); } } private void f_next() { // продолжение onCreate после f_go() view.getHolder().addCallback(this); ujeYes = 0; DbHelper.err = ""; paintGraf.setStyle(Paint.Style.STROKE); paintGraf.setStrokeWidth(3); paintLine.setStyle(Paint.Style.STROKE); paintLine.setStrokeWidth(0.4f); paintLine.setARGB(155, 0, 0, 0); final ViewConfiguration confToch = ViewConfiguration.get(getApplicationContext()); // системные параметры для DblCklick final int doubleTapSlop = confToch.getScaledDoubleTapSlop(); if (flagSn) setTitle("Основные подгруппы в Sn для n = " + dbH.f_getCount("select ind as ccc from params where parm = 'saveSnLen';")); else setTitle("Основные подгруппы " + (mApp.tableNameEnd.equals("_a") ? "автоморфизмов " : "") + mApp.groupName); view.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // onTouch на canvas // определяет yClick = y линии, и ujeCoob больше ничего final ViewConfiguration conf = ViewConfiguration.get(getApplicationContext()); // системные параметры для DblCklick int pc = event.getPointerCount(); // число пальцев на экране 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); long time_now = event.getEventTime(); long deltaTime = time_now - mOldClicktime; if (pc > 1) return true; /* for (int j = 0; j < colCount; j++) { if (startCol[j] <= xt && xt <= (startCol[j] + dl)) { if (DISPLAYLOG) Log.d(TAG, "onTouchEvent j=" + j + " colCount=" + colCount + " startCol[j] " + startCol[j] + " xt = " + xt + " startCol[j] + dl = " + (startCol[j] + dl)); break; } } */ float deltaX = xTopOld - xt, deltaY = yTopOld - yt; float delta2 = deltaX * deltaX + deltaY * deltaY; float velocity = 0f; if (deltaTime > 0) velocity = (float) (500f * Math.sqrt(delta2) / deltaTime); /* ACTION_DOWN – срабатывает при касании первого пальца ACTION_POINTER_DOWN – срабатывает при касании каждого последующего пальца ACTION_MOVE - срабатывает при любом движении ACTION_ POINTER_UP – срабатывает при отпускании каждого пальца кроме последнего ACTION_ UP – срабатывает при отпускании последнего пальца */ switch (actionCode) { case MotionEvent.ACTION_DOWN: // 0 case MotionEvent.ACTION_POINTER_DOWN: // 5 // был клик if (deltaTime < DOUBLE_TAP_TIMEOUT && (delta2 < doubleTapSlop * doubleTapSlop)) { // сделан двойной клик yClick = yt; if (DISPLAYLOG) Log.e(TAG, "onTouchEvent yClick=" + yClick + " colCount=" + colCount + " flagSn= " + flagSn + " xt = " + xt + " dl = " + dl); ujeCoob = 0; } xTopOld = xt; yTopOld = yt; mOldClicktime = time_now; break; case MotionEvent.ACTION_MOVE: // 2 if (deltaTime < DOUBLE_TAP_TIMEOUT) { if (velocity >= conf.getScaledMinimumFlingVelocity()) yClick = -1f; // y линии } /* Log.d(TAG, "onTouchEvent ACTION_MOVE actionCode=" + actionCode + " xt=" + xt + " yt=" + yt + " xTopOld="+ xTopOld + " yTopOld="+ yTopOld + " action=" + action + " deltaTime = " + deltaTime + " DOUBLE_TAP_TIMEOUT=" + DOUBLE_TAP_TIMEOUT); Log.d(TAG, "onTouchEvent velocity="+velocity + " "+ conf.getScaledMinimumFlingVelocity() + " deltaTime="+deltaTime+" distanceX="+deltaX+" distanceY="+deltaY); */ break; case MotionEvent.ACTION_UP: // последнего пальца /* if (deltaTime > DOUBLE_TAP_TIMEOUT) { // не было длинное нажатие f_clickFinger(); } */ break; case MotionEvent.ACTION_POINTER_UP: // 6 case MotionEvent.ACTION_CANCEL: // 3 default: break; } v.performClick(); return true; } }); paintTxt.setStyle(Paint.Style.STROKE); paintTxt.setStrokeWidth(0.7f); paintTxt.setTextSize(15); paintTxt.setARGB(255, 0, 0, 0); } volatile static private int colCount = 0; // кол=во действующих колонок на canvas private static int tekClickIndex = 0; // текущий кликнутый индекс колонки заголовка final static private float startCol[] = new float[classIds.MAX_COL_NUM + 1]; // x для колонки, ширина колонки = dl final static private boolean clickCol[] = new boolean[classIds.MAX_COL_NUM + 1]; // true - выбрана колонка final static private TextView textView[] = new TextView[classIds.MAX_COL_NUM + 1]; // тексты заголовков private void f_clickFinger(int skoko) { // skoko = 0 - вывести содержимое подгруппы // = 1 - кликнутых подгрупп if (DISPLAYLOG) { Log.e(TAG, "f_clickFinger "); for (int i = 0; i < colCount; i++) if (clickCol[i]) Log.e(TAG, "f_clickFinger i= " + i + " " + DbHelper.grupZag.get(i)); } new adapterShowGrupp(this, dbH, skoko); } volatile private String txtShow = ""; // текст для отображения внизу view static private int sh, sw; // размер SurfaceView volatile private float yClick = -1f; // y горизонтальной линии элемента группы volatile static private int rowCount = 0, // число всех строк ujeYes = 0, // 1 - dataGraph заполнено ujeCoob = 0, // сообщение о строке выдано indClick = 0, // i кликнутого dataGraph[i] whatToOutput = 0; // 0- выводить все классы, > 0 - только этот класс final private List<Integer> listToOutput = new ArrayList<>(); // список классов для отображения при whatToOutput = -1 static private float dl = 0f; // шаг рисования элемента private void f_paint() { // рисование на canvas в потоке // Log.e(TAG, "рисование colCount=" + colCount + " IsCreat=" + IsCreat); if (IsCreat) { int i, j; canvas.drawColor(Color.WHITE); canvas.save(); if (ujeYes == 0) { f_readData(); ujeYes = 1; } sh = canvas.getHeight() - 27; sw = canvas.getWidth(); float dh, dk = sh / (float)(1.1 * (flagSn ? DbHelper.countElements_n : DbHelper.countElements)); // интервал рисования элемента по высоте if (DISPLAYLOG) Log.d(TAG, "f_paint sh= "+sh + " dk= "+ dk + " sw="+sw + " DbHelper.countElements="+ DbHelper.countElements); paintGraf.setStyle(Paint.Style.STROKE); if (whatToOutput == 0) canvas.drawText( "Показаны все классы группы",58f, (float) sh + 20f , paintTxt); else if (whatToOutput > 0) canvas.drawText( "Показан класс " + whatToOutput,58f, (float) sh + 20f , paintTxt); else { canvas.drawText( txtShow,58f, (float) sh + 20f , paintTxt); } paintGraf.setStrokeWidth(12); for (j = 0; j < colCount; j++) { // j = столбец (# столбца) for (i = 0; i < rowCount; i++) { // i = строка dh = sh * (i - 0.f) / rowCount; dataGraph[i].yPoint = dh; colorSelector.indColor = dataGraph[i].col; // рисование основной группы colorSlt.f_setColor(); if (flagSn) paintGraf.setARGB(45, colorSelector.rCol, colorSelector.gCol, colorSelector.bCol); else paintGraf.setARGB(255, colorSelector.rCol, colorSelector.gCol, colorSelector.bCol); if (dataGraph[i].strData[j] > 0) { if (whatToOutput == 0 || (whatToOutput == dataGraph[i].col && whatToOutput > 0) || (listToOutput.contains(dataGraph[i].col) && whatToOutput < 0)) { canvas.drawLine((j + 1) * dl - 17f, dh, (j + 1) * dl - 17f, dh + dk, paintGraf); if (dataGraph[i].classSubGr >= 0 && flagSn) { // рисование подгруппы colorSelector.indColor = dataGraph[i].classSubGr; // цвет = классу сопр эл-тов colorSlt.f_setColor(); paintGraf.setARGB(255, colorSelector.rCol, colorSelector.gCol, colorSelector.bCol); if (j == 0) // рисование колонки 1 canvas.drawLine(dl - 2f, dh, dl - 2f, dh + dk, paintGraf); else // рисование других колонок canvas.drawLine((j + 1) * dl - 17f, dh, (j + 1) * dl - 17f, dh + dk, paintGraf); } } } } } for (i=0; i<dataGraph.length; i++) if (yClick >= dataGraph[i].yPoint && yClick <= dataGraph[i].yPoint + dk) { indClick = i; break; } if (DISPLAYLOG) if (yClick > 0 && ujeCoob == 0) Log.e(TAG, "f_paint yClick= " + yClick + " indClick=" + indClick + " id = "+ dataGraph[indClick].id ); // вывод горизонтальной линии if (yClick > 0) { canvas.drawLine(0f, yClick, (1f + colCount) * dl, yClick, paintLine); if (ujeCoob == 0) { paintGrup.activity.runOnUiThread(new Runnable() { public void run() { String ss = "select 'id гр-пы = '||E._id||' '|| E.substitution || ' ' || E.ciklos || ' Класс гр-пы = ' || P.class_area as stext " + "from elements" + mApp.tableNameEnd + " E, pairing_area" + mApp.tableNameEnd + " P where E._id = P.id_subs and E._id = " + dataGraph[indClick].id + ";"; if (flagSn) ss = "select 'id Sn= '||E.id_true||' id подгр-пы = '||E.link_to_elements||' '|| E.substitution || ' ' || E.ciklos || ' Класс Sn = ' || P.class_area || ' Класс гр-пы = ' || PP.class_area as stext " + "from elements_n E, pairing_area_n P , pairing_area" + mApp.tableNameEnd + " PP" + " where E.link_to_elements = PP.id_subs and E.id_true = P.id_subs and E.id_true = " + dataGraph[indClick].id + ";"; if (DISPLAYLOG) Log.e(TAG, "f_paint yClick= " + yClick + " indClick=" + indClick + " id = " + dataGraph[indClick].id + " \nстрока= " + ss); int i = dbH.f_getMas(ss); // DbHelper.selectedMas - заполнен // выдать сообщение if (i > 0) { Toast.makeText(getApplicationContext(), DbHelper.selectedMas[0], Toast.LENGTH_LONG).show(); if (DISPLAYLOG) Log.d(TAG, "f_paint a yClick= " + yClick + " indClick=" + indClick + " id = " + dataGraph[indClick].id + " \nстрока= " + ss+ "\n"+ DbHelper.selectedMas[0]); } else { if (flagSn) ss = "select 'id Sn= '||E.id_true||' '||E.substitution || ' ' || E.ciklos || ' Класс Sn= ' || P.class_area as stext " + "from elements_n E, pairing_area_n P where E.id_true = P.id_subs and E.id_true = " + dataGraph[indClick].id + ";"; else ss = "select 'id '||E._id||' '|| E.substitution || ' ' || E.ciklos || ' Класс = ' || P.class_area as stext " + "from elements" + mApp.tableNameEnd + " E, pairing_area" + mApp.tableNameEnd + " P where E._id = P.id_subs and E._id = " + dataGraph[indClick].id + ";"; i = dbH.f_getMas(ss); if (DISPLAYLOG) Log.e(TAG, "f_paint b i= " + i + " indClick=" + indClick + " id = " + dataGraph[indClick].id + " \nстрока= " + ss); if (i > 0) { Toast.makeText(getApplicationContext(), DbHelper.selectedMas[0], Toast.LENGTH_LONG).show(); if (DISPLAYLOG) Log.d(TAG, "f_paint c yClick= " + yClick + " indClick=" + indClick + " id = " + dataGraph[indClick].id + " \nстрока= " + ss); } } } }); ujeCoob = 1; } } canvas.restore(); } } private PaintData dataGraph[]; // - хранилище всех данных для рисования на canvas: 1 элемент хранит данные 1 строки private void f_readData() { // собственно чтение данных - рисование в потоке вызывается из f_paint() // flagSn = true - для Sn и строит данные для подгруппы, иначе только для подгруппы int nRow = 0, i, id, cls, idArea, class_area; dbH.f_buildSelectSubgrups(countSylowGrup, true, false, flagSn); // строит selectGrupGrid, selectGrupSum, grupZag, grupRow colCount = DbHelper.grupZag.size(); if (colCount > classIds.MAX_COL_NUM) colCount = classIds.MAX_COL_NUM; int colInd[] = new int[colCount]; // индексы колонок dataGraph = new PaintData[ flagSn ? DbHelper.countElements_n : DbHelper.countElements]; // 1 элемент хранит данные 1 строки Cursor mCursor = db.rawQuery(DbHelper.selectGrupGrid, null); if (mCursor.moveToFirst()) { rowCount = mCursor.getCount(); if (DISPLAYLOG) Log.d(TAG, "f_readData rowCount= " + rowCount + " flagSn= "+ flagSn + " mCursor.getCount()= " + mCursor.getCount() + " colCount = " + colCount + " countSylowGrup="+countSylowGrup + "\n selectGrupGrid=\n" + DbHelper.selectGrupGrid); if (rowCount > 0) { for (i = 0; i < colCount; i++) colInd[i] = mCursor.getColumnIndex(DbHelper.grupRow.get(i)); int id_element = mCursor.getColumnIndex("id_element"), idCls = mCursor.getColumnIndex("class_area"); if (mCursor.moveToFirst()) { do { id = mCursor.getInt(id_element); // класс = цвет cls = mCursor.getInt(idCls); dataGraph[nRow] = new PaintData(colCount, id, cls); if (flagSn) { // подписать данные подгруппы Cursor cursorCeckId = db.rawQuery("select class_area from pairing_area_n P, elements_n N " + "where P.id_subs = N.link_to_elements and N.id_true = " + id + ";" , null); if (cursorCeckId.moveToFirst()) { if (DISPLAYLOG) Log.d(TAG, "f_readData id= " + id + " cursorCeckId.getCount() = " + cursorCeckId.getCount()); if (cursorCeckId.getCount() > 0) { // есть элемент в подгруппе idArea = cursorCeckId.getColumnIndex("class_area"); class_area = cursorCeckId.getInt(idArea); if (DISPLAYLOG) Log.d(TAG, "SQL_LOG f_readData id= " + id + " classSubGr = " + class_area ); dataGraph[nRow].classSubGr = class_area; } } cursorCeckId.close(); } if (DISPLAYLOG) Log.d(TAG, "f_readData id= " + id + " nRow = " + nRow + " flagSn = " + flagSn + " dataGraph = " + dataGraph.length); for (i = 0; i < colCount; i++) dataGraph[nRow].strData[i] = mCursor.getInt(colInd[i]); nRow++; } while (mCursor.moveToNext()); } } } mCursor.close(); } private void f_putOtchet() { // вывод итоговой строки с заголовком, вызывается из основного потока dbH.f_buildSelectSubgrups(countSylowGrup, true, true, flagSn); String SQL = DbHelper.selectGrupSum; colCount = DbHelper.grupZag.size(); if (colCount > classIds.MAX_COL_NUM) colCount = classIds.MAX_COL_NUM; if (DISPLAYLOG) Log.e(TAG, "SQL_LOG f_putOtchet flagSn= "+ flagSn + " ccolCount = " + colCount + " countSylowGrup="+countSylowGrup + " dbH.grupZag.size()=" + DbHelper.grupZag.size()+ " IsCreat=" + IsCreat); String sFrom[] = new String[colCount]; int aTo[] = new int[colCount]; for (int i = 0; i < colCount; i++) { sFrom[i] = DbHelper.grupRow.get(i); aTo[i] = classIds.toA[i]; } int dbNItem = R.layout.db_item30; Cursor mCursor = db.rawQuery(SQL, null); SimpleCursorAdapter mCursorAd = new SimpleCursorAdapter(this, dbNItem, mCursor, sFrom, aTo, 0); LinearLayout ll = (LinearLayout) LayoutInflater.from(getApplication()).inflate(dbNItem, null); tableListView.setAdapter(mCursorAd); tableListView.setClickable(true); tableListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); f_OtchetText(colCount, ll); } private void f_OtchetText(int colCnt, LinearLayout ll) { // настройка текстов шапки int i; for (i = 0; i < classIds.MAX_COL_NUM; i++) { if (colCnt > i) textView[i] = ll.findViewById(classIds.idbN[i]); } LinearLayout.LayoutParams lpView = null; // для настройка заголовкров по таблице данных TextView tvz1; for (i = 0; i < classIds.MAX_COL_NUM; i++) { // Log.e(TAG, "f_OtchetText colCount =" + colCnt + " i=" + i + " MAX_COL_NUM=" + classIds.MAX_COL_NUM); if (i < colCnt) { lpView = (LinearLayout.LayoutParams) textView[i].getLayoutParams(); } textView[i] = tvz1 = findViewById(classIds.idbZ[i]); if (i == 0) { dl = 10 + lpView.width; // шаг по X sw = colCnt * (10 + lpView.width); LinearLayout.LayoutParams lSw = (LinearLayout.LayoutParams) view.getLayoutParams(); lSw.width = sw; view.setLayoutParams(lSw); } if (i < colCnt) { tvz1.setLayoutParams(lpView); tvz1.setText(DbHelper.grupZag.get(i)); startCol[i] = dl * i; // if (DISPLAYLOG) // Log.e(TAG, "f_OtchetText startCol[i] =" + startCol[i] + " i= " + i + " textView[i]=" + textView[i].getX() + " textView[i]=" + textView[i].getText() + " width=" + lpView.width + " gravity=" + lpView.gravity + " leftMargin=" + lpView.leftMargin + " weight=" + lpView.weight + " rightMargin=" + lpView.rightMargin + " topMargin=" + lpView.topMargin); tvz1.setVisibility(View.VISIBLE); textView[i].setClickable(true); textView[i].setOnTouchListener(new View.OnTouchListener() { @SuppressLint("UseCompatLoadingForDrawables") @Override public boolean onTouch(View v, MotionEvent event) { // onTouch на заголовке колонки if (event.getAction() == MotionEvent.ACTION_UP) { // выделить кликнутую колонку int ids = v.getId(); int i, iy = -1; Drawable backgroundDrawable; for (i = 0; i < colCnt; i++) if (ids == classIds.idbZ[i]) { iy = i; break; } if (iy >= 0) { clickCol[iy] = ! clickCol[iy]; if (DISPLAYLOG) Log.e(TAG, "f_OtchetText.onTouch iy =" + iy + " tekClickIndex="+ tekClickIndex + " clickCol=" + clickCol[iy] ); if (clickCol[iy]) { tekClickIndex = iy; backgroundDrawable = getResources().getDrawable(R.drawable.textview_selected); } else backgroundDrawable = getResources().getDrawable(R.drawable.textview_border); v.setBackground(backgroundDrawable); } } v.performClick(); return true; } }); } else { tvz1.setText(""); startCol[i] = 0f; tvz1.setVisibility(View.GONE); } tvz1.requestLayout(); clickCol[i] = false; } } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { if (DISPLAYLOG) Log.d(TAG, "surfaceChanged width=" + width + " height=" + height); IsCreat = true; repaint(); } @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { IsCreat = true; if (DISPLAYLOG) Log.d(TAG, "surfaceCreated"); repaint(); } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { IsCreat = false; } @Override protected void onStop() { super.onStop(); if (DISPLAYLOG) Log.d(TAG, "=== onStop"); stopPotok(); mApp.activityGrp = null; } @Override protected void onDestroy() { super.onDestroy(); if (DISPLAYLOG) Log.d(TAG, "=== onDestroy"); stopPotok(); } @Override protected void onResume() { super.onResume(); mApp = (mAplication) getApplication(); mApp.activityGrp = this; dbH = mApp.dbH; classSubs = mApp.classSubs; db = dbH.getReadableDatabase(); whatToOutput = ujeYes = 0; } @Override protected void onRestart() { super.onRestart(); if (DISPLAYLOG) Log.d(TAG, "=== onRestart"); } @Override protected void onPause() { super.onPause(); //Log.d("SQL", "=== onPause txtKak="+txtKak ); stopPotok(); } public void startPotok() {// запустить поток для рисования paintGrup = new PaintGrup(this, view); paintGrup.setRunning(true); paintGrup.setName("paintGrup"); paintGrup.setPriority(1); paintGrup.start(); // запустить поток if (DISPLAYLOG) Log.d(TAG, "startPotok " ); } public void stopPotok() {// остановитьпоток рисования if (paintGrup != null) { if (paintGrup.running.get()) { paintGrup.stopPotok(); boolean retry = true; while (retry) { try {// ожидание завершение потока paintGrup.join(); retry = false; } catch (InterruptedException e) { Log.e(TAG, "Error stopPotok " + e.getMessage()); // Toast.makeText(getApplicationContext(), "Error stopPotok " + e.toString(), //??? Toast.LENGTH_LONG).show(); mApp.curExeption = e; mApp.f_messError(4,"stopPotok", true); } } } paintGrup = null; } if (DISPLAYLOG) Log.e(TAG, "stopPotok colCount=" + colCount + " IsCreat=" + IsCreat); } public void repaint() { if (IsCreat) { if (DISPLAYLOG) Log.d(TAG, "repaint rowCount= "+ rowCount); if (paintGrup == null) startPotok(); } } public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_group, menu); MenuItem mItem_sn_graf = menu.findItem(R.id.action_sn_grp); // флаг Sn не доступен если Sn не сохранена mItem_sn_graf.setEnabled(dbH.f_testFn()); return super.onCreateOptionsMenu(menu); } public boolean onOptionsItemSelected(MenuItem item) { Intent intent = new Intent(GrupActivity.this, helpActivity.class); switch (item.getItemId()) { case R.id.action_exit_grp: finish(); break; case R.id.action_help_grp: startActivity(intent); break; case R.id.action_sn_grp: item.setChecked( ! item.isChecked()); flagSn = item.isChecked(); stopPotok(); f_goOtchet(); // Log.d(TAG, "isChecked() = "+ flagSn); break; } return super.onOptionsItemSelected(item); } @Override public void f_go(int chislo) { //сюда передается введенное число // интерфейс ввода числа if (DISPLAYLOG) Log.e(TAG, "f_go " + chislo); countSylowGrup = chislo; f_next(); f_putOtchet(); } public class PaintGrup extends Thread { // рисование на canvas final private GrupActivity activity; final private SurfaceView view; volatile AtomicBoolean running; public PaintGrup(GrupActivity cActivity, SurfaceView view) { activity = cActivity; this.view = view; running = new AtomicBoolean(); running.set(false); } public void setRunning(boolean run) { if (DISPLAYLOG) Log.d(TAG, "setRunning"); running.set(run); } public void run() { while (running.get()) { if (isInterrupted()) return; canvas = null; // своя ссылка на канву try { // подготовка Canvas-а canvas = view.getHolder().lockCanvas(); if (canvas == null) continue; synchronized (view.getHolder()) { activity.f_paint(); // собственно рисование if (DISPLAYLOG) Log.d(TAG, "***running "); } } catch (Exception e) { StackTraceElement ste[] = e.getStackTrace(); Log.e(TAG, "***Error " + e.getMessage() + " 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(); mApp.curExeption = e; mApp.f_messError(4,"run", true); } finally { // try закончился if (canvas != null) { view.getHolder().unlockCanvasAndPost(canvas); } } } } public void stopPotok() { //прервать рисование if (DISPLAYLOG) Log.e(TAG, "stopPotok PaintGrup running=" + running ); running.set(false); // текущая итерация - последняя this.interrupt(); // и заканчивается она прямо сейчас } } static public class PaintData { // 1 элемент хранит данные 1 строки = 1 элемент группы public int strData[]; // данные колонок: 1 или нет, всего colCount public int id; // _id элемента группы public int classSubGr; // >= 0 - элемент содержится в подгруппе и это его class_area public float yPoint; // y начала отрезка на графике, длина для 1-го id = dk final private int col; // № класса = цвет public PaintData(int sizeWidth, int _id, int _cls) { strData = new int[sizeWidth]; id = _id; classSubGr = -1; col = _cls % colorSelector.colorArray.length; if (DISPLAYLOG) Log.e(TAG, "PaintData id=" + id + " col=" + col + " " + colorSelector.colorArray[col] ); } } private static class adapterShowGrupp { // открывает список элементов P подгруппы public androidx.appcompat.app.AlertDialog.Builder builder; public adapterShowGrupp(GrupActivity actTaEsche, DbHelper dbH, int rej) { // rej = 0 - вывести содержимое подгруппы // 1 - пересечение всех выделенных подгрупп // rej = 2 - вывести список Классов подгруппы // rej = 3 - вывести список Общие классы подгрупп String SelText = "select distinct 'Class= ' || P.class_area || ' ' || P.cykl_len as stext from elements" + mApp.tableNameEnd + " E, subgrups" + mApp.tableNameEnd + " S, pairing_area" + mApp.tableNameEnd + " P", titlos = "", where = " E._id = S.id_element and S.id_element = P.id_subs"; int i, k = 0; if (actTaEsche.flagSn) { SelText = "select distinct 'Class= ' || P.class_area || ' ' || P.cykl_len as stext from elements_n E, subgrups_n S, pairing_area_n P"; where = " E.id_true = S.id_element and S.id_element = P.id_subs"; } /* select distinct 'Класс '||class|| ' ' || cykl || ' всего элементов в классе ' || sum(ccc) ||' в подгруппы из класса '|| sum(nnn) as stext from ( select P.class_area class, ' ' cykl, 0 ccc, count(distinct P.id_subs) nnn from elements E, subgrups S, pairing_area" + mApp.tableNameEnd + " P where P.id_subs = S.id_element and E.pe = 2 and S.flag_stab_3 = 1 and P.cykl_len isnull group by P.class_area, P.cykl_len union all select P.class_area class, P.cykl_len cykl, 0 ccc, count(distinct P.id_subs) nnn from elements E, subgrups S, pairing_area" + mApp.tableNameEnd + " P where P.id_subs = S.id_element and E.pe = 2 and S.flag_stab_3 = 1 and not P.cykl_len isnull group by P.class_area, P.cykl_len union all select P.class_area class, P.cykl_len cykl, count(distinct P.id_subs) ccc, 0 nnn from pairing_area" + mApp.tableNameEnd + " P where not P.cykl_len isnull and P.class_area in ( select P.class_area from elements E, subgrups S, pairing_area" + mApp.tableNameEnd + " P where P.id_subs = S.id_element and E.pe = 2 and S.flag_stab_3 = 1 and not P.cykl_len isnull ) GROUP by P.class_area, P.cykl_len union all select P.class_area class, ' ' cykl, count(distinct P.id_subs) ccc, 0 nnn from pairing_area" + mApp.tableNameEnd + " P where P.cykl_len isnull GROUP by P.class_area, P.cykl_len ) GROUP by class, cykl */ if (rej < 2) { // содержимое if (actTaEsche.flagSn) { SelText = "select 'Id= ' || E._id || ' ' || E.substitution || ' ' || E.ciklos as stext from elements_n E, subgrups_n S "; where = "E.id_true = S.id_element"; } else { SelText = "select 'Id= ' || E._id || ' ' || E.substitution || ' ' || E.ciklos as stext from elements" + mApp.tableNameEnd + " E, subgrups" + mApp.tableNameEnd + " S "; where = "E._id = S.id_element"; } } for (i = 1; i < colCount; i++) { // несколько подгрупп if (clickCol[i]) { where += " and S." + DbHelper.grupRow.get(i) + " = 1"; k = 1; } } if (k == 0 && tekClickIndex >= 0) where += " and S." + DbHelper.grupRow.get(tekClickIndex) + " = 1"; if (rej < 2) SelText += " where " + where + " order by 1 asc ;"; else { // вывести классы if (actTaEsche.flagSn) SelText = "select distinct 'Класс '||class|| ' ' || cykl || ' всего элементов в классе ' || sum(ccc) ||' в подгруппы из класса '|| sum(nnn) as stext from\n" + " (\n" + "select P.class_area class, ' ' cykl, 0 ccc, count(distinct P.id_subs) nnn\n" + " from elements_n E, subgrups_n S, pairing_area_n P\n" + " where " + where + " \n" + " and P.cykl_len isnull\n" + " group by P.class_area, P.cykl_len\n" + " union all\n" + " select P.class_area class, P.cykl_len cykl, 0 ccc, count(distinct P.id_subs) nnn\n" + " from elements_n E, subgrups_n S, pairing_area_n P\n" + " where " + where + " \n" + " and not P.cykl_len isnull\n" + " group by P.class_area, P.cykl_len\n" + " union all\n" + " select P.class_area class, P.cykl_len cykl, count(distinct P.id_subs) ccc, 0 nnn\n" + " from pairing_area_n P\n" + " where not P.cykl_len isnull and P.class_area in (\n" + " select P.class_area\n" + " from elements_n E, subgrups_n S, pairing_area_n P\n" + " where " + where + " \n" + " and not P.cykl_len isnull\n" + " )\n" + " GROUP by P.class_area, P.cykl_len\n" + " union all\n" + " select P.class_area class, ' ' cykl, count(distinct P.id_subs) ccc, 0 nnn\n" + " from pairing_area_n P\n" + " where P.cykl_len isnull\n" + " GROUP by P.class_area, P.cykl_len\n" + " )\n" + " GROUP by class, cykl order by 1 asc;"; else SelText = "select distinct 'Класс '||class|| ' ' || cykl || ' всего элементов в классе ' || sum(ccc) ||' в подгруппы из класса '|| sum(nnn) as stext from\n" + " (\n" + "select P.class_area class, ' ' cykl, 0 ccc, count(distinct P.id_subs) nnn\n" + " from elements E, subgrups" + mApp.tableNameEnd + " S, pairing_area" + mApp.tableNameEnd + " P\n" + " where " + where + " \n" + " and P.cykl_len isnull\n" + " group by P.class_area, P.cykl_len\n" + " union all\n" + " select P.class_area class, P.cykl_len cykl, 0 ccc, count(distinct P.id_subs) nnn\n" + " from elements E, " + mApp.tableNameEnd + " S, pairing_area" + mApp.tableNameEnd + " P\n" + " where " + where + " \n" + " and not P.cykl_len isnull\n" + " group by P.class_area, P.cykl_len\n" + " union all\n" + " select P.class_area class, P.cykl_len cykl, count(distinct P.id_subs) ccc, 0 nnn\n" + " from pairing_area" + mApp.tableNameEnd + " P\n" + " where not P.cykl_len isnull and P.class_area in (\n" + " select P.class_area\n" + " from elements E, subgrups" + mApp.tableNameEnd + " S, pairing_area" + mApp.tableNameEnd + " P\n" + " where " + where + " \n" + " and not P.cykl_len isnull\n" + " )\n" + " GROUP by P.class_area, P.cykl_len\n" + " union all\n" + " select P.class_area class, ' ' cykl, count(distinct P.id_subs) ccc, 0 nnn\n" + " from pairing_area" + mApp.tableNameEnd + " P\n" + " where P.cykl_len isnull\n" + " GROUP by P.class_area, P.cykl_len\n" + " )\n" + " GROUP by class, cykl order by 1 asc;"; } switch (rej) { case 0: titlos = "Элементы подгруппы " + DbHelper.grupZag.get(tekClickIndex); break; case 1: titlos = "Общие элементы подгрупп "; break; case 2: titlos = "Классы подгруппы " + DbHelper.grupZag.get(tekClickIndex); break; default: titlos = "Общие классы для выделенных подгрупп"; } if (DISPLAYLOG) Log.e(TAG, "adapterShowGrupp rej="+ rej + " flagSn="+ actTaEsche.flagSn + " tekClickIndex="+ tekClickIndex + " AdapterShow where= " + where + " title = " + titlos + " SelText = " + SelText + " всего " + i); i = dbH.f_getMas(SelText); titlos += ", всего " + i + " строк"; new ArrayAdapter<>(actTaEsche, R.layout.db_item1, DbHelper.selectedMas); builder = new androidx.appcompat.app.AlertDialog.Builder(actTaEsche); builder.setTitle(titlos) .setItems(DbHelper.selectedMas, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }) .setCancelable(true); builder.setNegativeButton("Отменить", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); builder.create(); builder.show(); } } @Override protected void onStart(){ super.onStart(); mApp.activityGrp = this; } } //==========================