package Common.Visual; import Common.CommonConstants; import Common.Database.Objects.DBObject; import Common.Database.Objects.Grid.TableVisualData; import Common.Database.Tables.DBTable; import Common.Database.Tables.DataSet; import Common.Database.Tables.FKBehaviour; import Common.MainModule_; import Common.Utils.Utils_; import Common.Visual.Menus.DataMenuBar; import Common.Visual.Menus.TableMenu; import Common.Visual.Tables.*; import Common.Visual.Tables.Grid.GridAnchestor; import javax.swing.*; import javax.swing.table.TableColumn; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.Arrays; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.Vector; import java.util.stream.Collectors; import java.util.stream.IntStream; public class DataSetControlForm extends ControlForm { protected DataSet dataSource; //источник данных protected DataMenuBar bar = null; //верхняя панель меню protected int current_row_i; //индекс текущей строки. protected boolean events_on = true; protected String colNamesAndSizes = ""; protected Vector columns = new Vector<>(); //информация о столбцах и их оформлении protected Vector filtersMenus = new Vector<>(); //выпадающие меню фильтрации protected LinkedHashMap headersTextFilters = new LinkedHashMap<>(); //текстовые фильтры столбцов //фильтры и подсчеты. todo слить с баром (?) MatchesCounter f_ui = null; //-- Object savedCurrentKey = null; Vector savedSelectedKeys = new Vector<>(); //-- public DataSetControlForm(DataSet dataSource_in, JPanel mountPanel_in) { super(DataTable.class, mountPanel_in); dataSource = dataSource_in; createFilters(); if (hasMenuBar()) { try { if (!MainModule_.instance.getUI().menuBars.containsKey(dataSource.getClass())) { bar = createMenuBar(); if (hasCheckBox()) bar.createSelectionButtons(dataSource); MainModule_.instance.getUI().menuBars.put(dataSource.getClass(), bar); } else { bar = MainModule_.instance.getUI().menuBars.get(dataSource.getClass()); } mountPanel.add(bar, BorderLayout.NORTH); //-- f_ui = (count -> bar.countLabel.setText(String.valueOf(count))); //-- if (!filtersMenus.isEmpty()) { for (DataSetFiltersMenu filter : filtersMenus) bar.addMenus(filter.getMenu()); } } catch (Exception ex) { ex.printStackTrace(); } } } public ColumnInfo getColumnInfo(int i) { return columns.get(i); } protected String[] getUIColumnNames() { return new String[]{}; } //---------для отображения. protected Object getFieldAt(D object, int coulmnIndex) { return null; } public void SaveColumns() { if (MainModule_.instance.getDb() != null) { try { if (dataSource.CurrentName() != null) { String tableName = dataSource.CurrentName().toString(); Vector widths = IntStream.range(0, columns.size()).mapToObj(i -> String.valueOf(control.getColumnModel().getColumn(i).getWidth())).collect(Collectors.toCollection(Vector::new)); String packed = String.join("|", widths); TableVisualData tableVisualData; if (MainModule_.instance.getDb().tablesVisualData.containsKey(tableName)) { tableVisualData = MainModule_.instance.getDb().tablesVisualData.get(tableName); } else { tableVisualData = new TableVisualData(tableName); MainModule_.instance.getDb().Insert(tableVisualData); } tableVisualData.sizes = packed; MainModule_.instance.getDb().Update(tableVisualData); } } catch (Exception ex) { ex.printStackTrace(); } } } private Vector getHeaders() { return columns.stream().map(ColumnInfo::getName).collect(Collectors.toCollection(Vector::new)); } protected void CreateColumnsInfo() { columns.clear(); columns.add(new ColumnInfo(dataSource.getPKName())); if (hasCheckBox()) { columns.add(new ColumnInfo("", DBObjectSelectionRenderer.class, DBObjectSelector.class)); columns.get(1).setMinWidth(25); columns.get(1).setMaxWidth(25); } Arrays.stream(getUIColumnNames()).forEach(name -> columns.add(new ColumnInfo(name))); AdditionalInitColumns(); } protected void AdditionalInitColumns() { //уточнение инфы по столбцам. } protected Comparator getDefaultComparator() { return null; } public boolean isObjectVisible(D object) { return ApplyFilters(object); } Vector getVisibleKeys() { Comparator comparator = getDefaultComparator(); Vector res_keys = new Vector<>(); if (comparator == null) { for (D object : dataSource.Data.values()) { if (isObjectVisible(object)) res_keys.add(object.getPK()); } } else { Vector raw = new Vector<>(); for (D object : dataSource.Data.values()) { if (isObjectVisible(object)) raw.add(object); } raw.sort(comparator); for (D object : raw) res_keys.add(object.getPK()); } return res_keys; } @SuppressWarnings("unchecked") @Override protected void createControl() { CreateColumnsInfo(); GridAnchestor table_data_model = new GridAnchestor(getHeaders(), getVisibleKeys()) { @SuppressWarnings("unchecked") @Override public Object getValueAt(int rowIndex, int columnIndex) { Object key = data.get(rowIndex); if (columnIndex == 0) return key; D object = dataSource.get((key)); if ((columnIndex == 1) && hasCheckBox()) return object.isSelected(); return getFieldAt(object, columnIndex); } @Override public boolean isCellEditable(int row, int col) { return columns.get(col).isEditable(); } //------------------------------------------------------------------------------------ @Override public void setValueAt(Object value, int row, int col) { fireTableCellUpdated(row, col); } }; control = new DataTable(table_data_model) { @Override public TableMenu CreateMenu() { return new TableMenu(this); } //строго говоря эта штука нужна только для рендереров и едиторов клеток. @Override public DBObject getRowObject(int rowIndex) { //вот так делать НЕЛЬЗЯ. модель только для внутреннего пользования // Object key = table_data_model.data.get(rowIndex); //из таблицы можно пользоваться только getValueAt //иначе сортировка не будет работать. Object key = getValueAt(rowIndex, 0); return dataSource.get(key); } //-----------------------------NEW------------------------------------- @Override public void CorrectColumnsSizes() { if ((MainModule_.instance.getDb() != null) && dataSource.CurrentName() != null && MainModule_.instance.getDb().tablesVisualData.containsKey(dataSource.CurrentName().toString())) { if (!getColumnsProfile().equalsIgnoreCase(colNamesAndSizes)) { TableVisualData grid = MainModule_.instance.getDb().tablesVisualData.get(dataSource.CurrentName().toString()); String[] data = grid.sizes.split("\\|"); for (int i = 0; i < columns.size(); ++i) { if (i <= (data.length - 1)) { int width = Integer.parseInt(data[i]); getColumnModel().getColumn(i).setPreferredWidth(width); getColumnModel().getColumn(i).setWidth(width); } } } } else super.CorrectColumnsSizes(); //обычный авторазмер. } public String getColumnsProfile() { String res = ""; for (int i = 0; i < getColumnModel().getColumnCount(); i++) { if (i > 0) res += ","; TableColumn column = getColumnModel().getColumn(i); res += column.getHeaderValue(); res += ":"; res += column.getWidth(); } return res; } @Override public void Init() { for (int i = 0; i < columns.size(); i++) { ColumnInfo columnInfo = columns.get(i); if (columnInfo.isVisible()) { if (columnInfo.hasRenderer()) getColumnModel().getColumn(i).setCellRenderer(MainModule_.instance.getUI().getTableRenderer(columnInfo.getRendererClass())); if (columnInfo.hasEditor()) getColumnModel().getColumn(i).setCellEditor(MainModule_.instance.getUI().getTableEditor(columnInfo.getEditorClass())); if (columnInfo.hasMaxWidth()) getColumnModel().getColumn((i)).setMaxWidth(columnInfo.getMaxWidth()); if (columnInfo.hasMinWidth()) getColumnModel().getColumn((i)).setMinWidth(columnInfo.getMinWidth()); } else { getColumnModel().getColumn(i).setMinWidth(0); getColumnModel().getColumn(i).setMaxWidth(0); } } //обновление в БД при ручном изменении размера столбиков.--------->> getTableHeader().addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent arg0) { String new_colNamesAndSizes = getColumnsProfile(); // check if changed, if yes, persist... if (!colNamesAndSizes.equals(new_colNamesAndSizes)) { colNamesAndSizes = new_colNamesAndSizes; SaveColumns(); } } }); //------------------------->> } }; if (dataSource.CurrentName() != null) { current_row_i = CommonConstants.Nan; ListSelectionModel selModel = control.getSelectionModel(); selModel.addListSelectionListener(e -> { int row = control.getSelectedRow(); if ((row >= 0)) { if (row != current_row_i) { current_row_i = row; dataSource.setCurrent((D) control.getRowObject(row)); if (events_on) { try { ShowCurrentObject(); } catch (Exception ex) { Utils_.MainLog.PrintException(ex); } } } } else { current_row_i = CommonConstants.Nan; dataSource.dropCurrent(); if (events_on) { try { ShowNoCurrentObject(); } catch (Exception ex) { Utils_.MainLog.PrintException(ex); } } } }); //двойной клик мыши.------------------------------------------------------ control.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if ((e.getClickCount() == 2) && (dataSource.getCurrent() != null)) { try { MouseAction2(); } catch (Exception ex) { Utils_.MainLog.PrintException(ex); } } } }); control.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_DELETE: if (dataSource.getDeletePassCode() != null) { MainModule_.instance.getPass(dataSource.getDeletePassCode()).Do(); } break; case KeyEvent.VK_ENTER: try { MouseAction2(); } catch (Exception ex) { Utils_.MainLog.PrintException(ex); } break; } } } ); //---------------------------------------------------------------------------- //при переотображении таблицы скидываем текущий объект!! dataSource.dropCurrent(); try { ShowNoCurrentObject(); } catch (Exception e) { Utils_.MainLog.PrintException(e); } } for (HeaderTextFilter filter : headersTextFilters.values()) { filter.Mount(getControl()); } } protected DataMenuBar createMenuBar() { return new DataMenuBar(dataSource.getPluralDescription()); } protected void createFilters() { } protected boolean applyFiltersMenus(DBObject object) { for (DataSetFiltersMenu filterMenu : filtersMenus) { if (!filterMenu.Validate(object)) return false; } return true; } public boolean ApplyFilters(DBObject object) { //могут быть и другие фильтры ( например свои/активные). перенести их сюда и обобщить return applyFiltersMenus(object); } @Override protected void redrawControl() { control.CorrectSizes(); } @Override public void Show() { for (DataSetFiltersMenu filterMenu : filtersMenus) filterMenu.Drop(); super.Show(); if (f_ui != null) f_ui.ShowMatchesCount(getRowCount()); for (DataSetFiltersMenu filterMenu : filtersMenus) filterMenu.Refresh(); } public void Show(Object pk) { Show(); SetCurrentByPK(pk); } public void SetCurrentByPK(Object pk) { if (isShown()) control.SelectRowByPK(pk); } public void ClearSelection() { if (isShown()) control.clearSelection(); //строка сбросится сама. благодаря сбросу события выбора } @Override public void Clear() { super.Clear(); if (f_ui != null) f_ui.ShowNoMatches(); } public int getRowCount() { return control.getRowCount(); } public void ShowCurrentObject() throws Exception { if (dataSource instanceof DBTable) { DBTable table = (DBTable) dataSource; for (Class dep : table.getFKDependencies().keySet()) { FKBehaviour behaviour = table.getFKDependencies().get(dep); switch (behaviour.ui) { case ACTIVE: table.getDb().getTable(dep).ShowUI(); break; case PASSIVE: break; } } } } public void ShowNoCurrentObject() throws Exception { if (dataSource instanceof DBTable) { DBTable table = (DBTable) dataSource; for (Class dep : table.getFKDependencies().keySet()) { FKBehaviour behaviour = table.getFKDependencies().get(dep); switch (behaviour.ui) { case ACTIVE: table.getDb().getTable(dep).ClearUI(); break; case PASSIVE: break; } } } } public void MouseAction2() throws Exception { } //- public boolean hasCheckBox() { return false; } public boolean hasMenuBar() { return true; } //- public void SaveLastCurrent() { savedCurrentKey = null; savedSelectedKeys.clear(); if ((dataSource.CurrentName() != null) && (dataSource.getCurrent() != null)) { savedCurrentKey = dataSource.getCurrent().getPK(); } savedSelectedKeys = (Vector) dataSource.getSelectedKeys(); } public void RestoreLastCurrent() { for (Object key : savedSelectedKeys) { if (dataSource.containsKey(key)) dataSource.get(key).Select(true); } if ((savedCurrentKey != null) && (dataSource.containsKey(savedCurrentKey))) { SetCurrentByPK(savedCurrentKey); } } }