src/main/java/cz/frantovo/rozsireneatributy/gui/Panel.java
author František Kučera <franta-hg@frantovo.cz>
Sun, 24 Dec 2023 00:38:41 +0100
branchv_0
changeset 42 d2414701ce09
parent 41 64e564c2f069
permissions -rw-r--r--
režimy zamykání:

- vypnuté: tlačítko pro zamykání je skryté a soubor se nezamyká
- volitelné: uživatel může soubor zamknout, ale může editovat i bez toho
- povinné: uživatel musí soubor zamknout, aby mohl atributy editovat

Změny v atributech se vždy propisují okamžitě - na ně zámek nemá vliv.
Zámek je na souboru (ne metadatech) a slouží pro kooperující procesy.
Proces, který soubor/metadata čte, si jednak může soubor zamknout (POSIX)
a tím mít jistotu, že zrovna neprobíhá editace.
A jednak může reagovat na notifikace CLOSE_WRITE (inotify).
Notifikaci mu pošleme tím, že soubor odemkneme (čímž se i zavře).
franta-hg@19
     1
/**
franta-hg@19
     2
 * Rozšířené atributy – program na správu rozšířených atributů souborů
franta-hg@19
     3
 * Copyright © 2012 František Kučera (frantovo.cz)
franta-hg@22
     4
 *
franta-hg@19
     5
 * This program is free software: you can redistribute it and/or modify
franta-hg@19
     6
 * it under the terms of the GNU General Public License as published by
franta-hg@27
     7
 * the Free Software Foundation, either version 3 of the License.
franta-hg@22
     8
 *
franta-hg@19
     9
 * This program is distributed in the hope that it will be useful,
franta-hg@19
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
franta-hg@22
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
franta-hg@19
    12
 * GNU General Public License for more details.
franta-hg@22
    13
 *
franta-hg@19
    14
 * You should have received a copy of the GNU General Public License
franta-hg@22
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
franta-hg@19
    16
 */
franta-hg@28
    17
package cz.frantovo.rozsireneatributy.gui;
franta-hg@6
    18
franta-hg@28
    19
import cz.frantovo.rozsireneatributy.Atribut;
franta-hg@35
    20
import cz.frantovo.rozsireneatributy.CSV;
franta-hg@42
    21
import cz.frantovo.rozsireneatributy.Konfigurace;
franta-hg@35
    22
import java.awt.Toolkit;
franta-hg@35
    23
import java.awt.datatransfer.StringSelection;
franta-hg@41
    24
import java.awt.event.KeyEvent;
franta-hg@10
    25
import java.io.IOException;
franta-hg@35
    26
import java.io.StringWriter;
franta-hg@15
    27
import java.util.ResourceBundle;
franta-hg@10
    28
import java.util.logging.Level;
franta-hg@10
    29
import java.util.logging.Logger;
franta-hg@10
    30
import javax.swing.JOptionPane;
franta-hg@16
    31
import javax.swing.JTable;
franta-hg@41
    32
import javax.swing.KeyStroke;
franta-hg@16
    33
import javax.swing.ListSelectionModel;
franta-hg@10
    34
import javax.swing.event.ListSelectionEvent;
franta-hg@10
    35
import javax.swing.event.ListSelectionListener;
franta-hg@42
    36
import javax.swing.table.TableCellEditor;
franta-hg@6
    37
franta-hg@6
    38
/**
franta-hg@30
    39
 * @author Ing. František Kučera (frantovo.cz)
franta-hg@6
    40
 */
franta-hg@6
    41
public class Panel extends javax.swing.JPanel {
franta-hg@6
    42
franta-hg@32
    43
	public static final int SLOUPEC_NÁZVU = 0;
franta-hg@32
    44
	public static final int SLOUPEC_HODNOTY = 1;
franta-hg@29
    45
	private static final Logger log = Logger
franta-hg@29
    46
		.getLogger(Panel.class.getSimpleName());
franta-hg@29
    47
	private static final ResourceBundle překlady = ResourceBundle
franta-hg@29
    48
		.getBundle(Atribut.class.getPackageName() + ".Překlady");
franta-hg@10
    49
	private Model model;
franta-hg@10
    50
	private Atribut vybranýAtribut;
franta-hg@16
    51
	private JTable tabulka;
franta-hg@6
    52
franta-hg@10
    53
	public Panel(Model model) {
franta-hg@6
    54
		this.model = model;
franta-hg@10
    55
		initComponents();
franta-hg@16
    56
franta-hg@30
    57
		tlačítkoZamknout.setEnabled(model.isZámekPodporovaný());
franta-hg@30
    58
		tlačítkoZamknout.setToolTipText(model.isZámekPodporovaný()
franta-hg@30
    59
			? překlady.getString("zamknout.popis")
franta-hg@30
    60
			: překlady.getString("chyba.lzeZamknoutJenSoubor"));
franta-hg@30
    61
franta-hg@16
    62
		tabulka = new JTable(model);
franta-hg@23
    63
		nastavEditor();
franta-hg@16
    64
		tabulka.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
franta-hg@16
    65
		posuvnýPanel.setViewportView(tabulka);
franta-hg@35
    66
franta-hg@33
    67
		tabulka.setRowHeight((int) (tabulka.getRowHeight() * 1.3));
franta-hg@33
    68
franta-hg@41
    69
		// Výběr aktuálního atributu v tabulce:
franta-hg@29
    70
		tabulka.getSelectionModel().addListSelectionListener(
franta-hg@29
    71
			new ListSelectionListener() {
franta-hg@6
    72
franta-hg@22
    73
			@Override
franta-hg@10
    74
			public void valueChanged(ListSelectionEvent e) {
franta-hg@10
    75
				int řádek = tabulka.getSelectedRow();
franta-hg@42
    76
				if (řádek < 0) vybranýAtribut = null;
franta-hg@42
    77
				else vybranýAtribut = getModel().getAtribut(řádek);
franta-hg@42
    78
				aktualizujPovolenéÚpravy();
franta-hg@10
    79
			}
franta-hg@10
    80
		});
franta-hg@41
    81
franta-hg@41
    82
		// Buňky tabulky editovatelné po stisku mezerníku:
franta-hg@41
    83
		tabulka.getInputMap()
franta-hg@41
    84
			.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "startEditing");
franta-hg@42
    85
franta-hg@42
    86
		aktualizujPovolenéÚpravy();
franta-hg@42
    87
franta-hg@42
    88
		// TODO: Provádět IO operace v jiném vlákně
franta-hg@42
    89
		// SwingWorker.doInBackground() + SwingUtilities.invokeLater()
franta-hg@42
    90
	}
franta-hg@42
    91
franta-hg@42
    92
	private void aktualizujPovolenéÚpravy() {
franta-hg@42
    93
		Konfigurace k = model.getKonfigurace();
franta-hg@42
    94
		switch (k.getRežimZamykání()) {
franta-hg@42
    95
			case VYPNUTÉ:
franta-hg@42
    96
				tlačítkoZamknout.setVisible(false);
franta-hg@42
    97
				setPovolenéÚpravy(true);
franta-hg@42
    98
				break;
franta-hg@42
    99
			case VOLITELNÉ:
franta-hg@42
   100
				setPovolenéÚpravy(true);
franta-hg@42
   101
				break;
franta-hg@42
   102
			case POVINNÉ:
franta-hg@42
   103
				setPovolenéÚpravy(tlačítkoZamknout.isSelected());
franta-hg@42
   104
				break;
franta-hg@42
   105
			default:
franta-hg@42
   106
				break;
franta-hg@42
   107
		}
franta-hg@42
   108
	}
franta-hg@42
   109
franta-hg@42
   110
	private void setPovolenéÚpravy(boolean povolené) {
franta-hg@42
   111
		if (!povolené) {
franta-hg@42
   112
			TableCellEditor ce = tabulka.getCellEditor();
franta-hg@42
   113
			if (ce != null) ce.cancelCellEditing();
franta-hg@42
   114
			tabulka.clearSelection();
franta-hg@42
   115
		}
franta-hg@42
   116
franta-hg@42
   117
		tabulka.setEnabled(povolené);
franta-hg@42
   118
		tlačítkoPřidat.setEnabled(povolené);
franta-hg@42
   119
		tlačítkoSmazat.setEnabled(povolené && tabulka.getSelectedRow() > -1);
franta-hg@10
   120
	}
franta-hg@10
   121
franta-hg@23
   122
	private void nastavEditor() {
franta-hg@29
   123
		tabulka.getColumnModel().getColumn(SLOUPEC_NÁZVU)
franta-hg@31
   124
			.setCellEditor(new EditorNázvůAtributů(model.getKonfigurace()));
franta-hg@32
   125
		tabulka.getColumnModel().getColumn(SLOUPEC_HODNOTY)
franta-hg@32
   126
			.setCellEditor(new EditorHodnotAtributů(model.getKonfigurace()));
franta-hg@23
   127
	}
franta-hg@23
   128
franta-hg@10
   129
	private Model getModel() {
franta-hg@10
   130
		return model;
franta-hg@10
   131
	}
franta-hg@10
   132
franta-hg@23
   133
	public void setModel(Model model) {
franta-hg@23
   134
		this.model = model;
franta-hg@23
   135
		tabulka.setModel(model);
franta-hg@23
   136
		nastavEditor();
franta-hg@23
   137
	}
franta-hg@23
   138
franta-hg@10
   139
	private void zobrazChybovouHlášku(String hláška, Throwable chyba) {
franta-hg@30
   140
		JOptionPane.showMessageDialog(this, hláška + "\n"
franta-hg@30
   141
			+ chyba.getLocalizedMessage(),
franta-hg@30
   142
			překlady.getString("chyba.titulek"), JOptionPane.ERROR_MESSAGE);
franta-hg@10
   143
		log.log(Level.WARNING, hláška, chyba);
franta-hg@10
   144
	}
franta-hg@42
   145
franta-hg@35
   146
	private void kopírujDoSchránky() {
franta-hg@35
   147
		try {
franta-hg@35
   148
			StringWriter výstup = new StringWriter();
franta-hg@35
   149
			CSV csv = new CSV(výstup);
franta-hg@35
   150
franta-hg@35
   151
			csv.hodnota(překlady.getString("tabulka.název").toLowerCase());
franta-hg@35
   152
			csv.hodnota(překlady.getString("tabulka.hodnota").toLowerCase());
franta-hg@35
   153
			csv.konecŘádku();
franta-hg@35
   154
franta-hg@35
   155
			for (int i = 0; i < model.getRowCount(); i++) {
franta-hg@35
   156
				csv.hodnota(String.valueOf(model.getValueAt(i, 0)));
franta-hg@35
   157
				csv.hodnota(String.valueOf(model.getValueAt(i, 1)));
franta-hg@35
   158
				csv.konecŘádku();
franta-hg@35
   159
			}
franta-hg@35
   160
franta-hg@35
   161
			Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
franta-hg@35
   162
				new StringSelection(výstup.toString()),
franta-hg@35
   163
				null
franta-hg@35
   164
			);
franta-hg@35
   165
		} catch (Exception e) {
franta-hg@35
   166
			zobrazChybovouHlášku(překlady
franta-hg@35
   167
				.getString("chyba.nepodařiloSeZkopírovat"), e);
franta-hg@35
   168
		}
franta-hg@35
   169
	}
franta-hg@10
   170
franta-hg@10
   171
	@SuppressWarnings("unchecked")
franta-hg@6
   172
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
franta-hg@6
   173
    private void initComponents() {
franta-hg@6
   174
franta-hg@10
   175
        posuvnýPanel = new javax.swing.JScrollPane();
franta-hg@10
   176
        tlačítkoPřidat = new javax.swing.JButton();
franta-hg@10
   177
        tlačítkoSmazat = new javax.swing.JButton();
franta-hg@10
   178
        tlačítkoZnovuNačíst = new javax.swing.JButton();
franta-hg@30
   179
        tlačítkoZamknout = new javax.swing.JToggleButton();
franta-hg@35
   180
        tlačítkoKopírovat = new javax.swing.JButton();
franta-hg@6
   181
franta-hg@11
   182
        tlačítkoPřidat.setMnemonic('p');
franta-hg@28
   183
        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("cz/frantovo/rozsireneatributy/Překlady"); // NOI18N
franta-hg@15
   184
        tlačítkoPřidat.setText(bundle.getString("přidatAtribut")); // NOI18N
franta-hg@10
   185
        tlačítkoPřidat.addActionListener(new java.awt.event.ActionListener() {
franta-hg@10
   186
            public void actionPerformed(java.awt.event.ActionEvent evt) {
franta-hg@10
   187
                tlačítkoPřidatActionPerformed(evt);
franta-hg@10
   188
            }
franta-hg@10
   189
        });
franta-hg@10
   190
franta-hg@11
   191
        tlačítkoSmazat.setMnemonic('s');
franta-hg@15
   192
        tlačítkoSmazat.setText(bundle.getString("smazatAtribut")); // NOI18N
franta-hg@10
   193
        tlačítkoSmazat.setEnabled(false);
franta-hg@10
   194
        tlačítkoSmazat.addActionListener(new java.awt.event.ActionListener() {
franta-hg@10
   195
            public void actionPerformed(java.awt.event.ActionEvent evt) {
franta-hg@10
   196
                tlačítkoSmazatActionPerformed(evt);
franta-hg@10
   197
            }
franta-hg@10
   198
        });
franta-hg@10
   199
franta-hg@11
   200
        tlačítkoZnovuNačíst.setMnemonic('z');
franta-hg@15
   201
        tlačítkoZnovuNačíst.setText(bundle.getString("znovuNačíst")); // NOI18N
franta-hg@10
   202
        tlačítkoZnovuNačíst.addActionListener(new java.awt.event.ActionListener() {
franta-hg@10
   203
            public void actionPerformed(java.awt.event.ActionEvent evt) {
franta-hg@10
   204
                tlačítkoZnovuNačístActionPerformed(evt);
franta-hg@10
   205
            }
franta-hg@10
   206
        });
franta-hg@6
   207
franta-hg@30
   208
        tlačítkoZamknout.setText(bundle.getString("zamknout")); // NOI18N
franta-hg@30
   209
        tlačítkoZamknout.addActionListener(new java.awt.event.ActionListener() {
franta-hg@30
   210
            public void actionPerformed(java.awt.event.ActionEvent evt) {
franta-hg@30
   211
                tlačítkoZamknoutActionPerformed(evt);
franta-hg@30
   212
            }
franta-hg@30
   213
        });
franta-hg@30
   214
franta-hg@35
   215
        tlačítkoKopírovat.setText(bundle.getString("schránka.kopírovat")); // NOI18N
franta-hg@35
   216
        tlačítkoKopírovat.addActionListener(new java.awt.event.ActionListener() {
franta-hg@35
   217
            public void actionPerformed(java.awt.event.ActionEvent evt) {
franta-hg@35
   218
                tlačítkoKopírovatActionPerformed(evt);
franta-hg@35
   219
            }
franta-hg@35
   220
        });
franta-hg@35
   221
franta-hg@6
   222
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
franta-hg@6
   223
        this.setLayout(layout);
franta-hg@6
   224
        layout.setHorizontalGroup(
franta-hg@6
   225
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
franta-hg@10
   226
            .addGroup(layout.createSequentialGroup()
franta-hg@10
   227
                .addContainerGap()
franta-hg@10
   228
                .addComponent(tlačítkoPřidat)
franta-hg@10
   229
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
franta-hg@10
   230
                .addComponent(tlačítkoSmazat)
franta-hg@10
   231
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
franta-hg@10
   232
                .addComponent(tlačítkoZnovuNačíst)
franta-hg@30
   233
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
franta-hg@30
   234
                .addComponent(tlačítkoZamknout)
franta-hg@35
   235
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
franta-hg@35
   236
                .addComponent(tlačítkoKopírovat)
franta-hg@35
   237
                .addContainerGap(25, Short.MAX_VALUE))
franta-hg@11
   238
            .addComponent(posuvnýPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 543, Short.MAX_VALUE)
franta-hg@6
   239
        );
franta-hg@6
   240
        layout.setVerticalGroup(
franta-hg@6
   241
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
franta-hg@10
   242
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
franta-hg@10
   243
                .addComponent(posuvnýPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 277, Short.MAX_VALUE)
franta-hg@10
   244
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
franta-hg@10
   245
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
franta-hg@10
   246
                    .addComponent(tlačítkoPřidat)
franta-hg@10
   247
                    .addComponent(tlačítkoSmazat)
franta-hg@30
   248
                    .addComponent(tlačítkoZnovuNačíst)
franta-hg@35
   249
                    .addComponent(tlačítkoZamknout)
franta-hg@35
   250
                    .addComponent(tlačítkoKopírovat))
franta-hg@10
   251
                .addContainerGap())
franta-hg@6
   252
        );
franta-hg@6
   253
    }// </editor-fold>//GEN-END:initComponents
franta-hg@6
   254
franta-hg@10
   255
	private void tlačítkoPřidatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tlačítkoPřidatActionPerformed
franta-hg@10
   256
		model.přidejAtribut(new Atribut());
franta-hg@10
   257
	}//GEN-LAST:event_tlačítkoPřidatActionPerformed
franta-hg@6
   258
franta-hg@10
   259
	private void tlačítkoSmazatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tlačítkoSmazatActionPerformed
franta-hg@10
   260
		try {
franta-hg@10
   261
			model.odeberAtribut(vybranýAtribut);
franta-hg@10
   262
		} catch (IOException e) {
franta-hg@29
   263
			zobrazChybovouHlášku(překlady
franta-hg@29
   264
				.getString("chyba.nepodařiloSeSmazat"), e);
franta-hg@10
   265
		}
franta-hg@10
   266
	}//GEN-LAST:event_tlačítkoSmazatActionPerformed
franta-hg@10
   267
franta-hg@10
   268
	private void tlačítkoZnovuNačístActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tlačítkoZnovuNačístActionPerformed
franta-hg@10
   269
		try {
franta-hg@10
   270
			model.načtiAtributy();
franta-hg@10
   271
		} catch (IOException e) {
franta-hg@29
   272
			zobrazChybovouHlášku(překlady
franta-hg@29
   273
				.getString("chyba.nepodařiloSeNačíst"), e);
franta-hg@10
   274
		}
franta-hg@10
   275
	}//GEN-LAST:event_tlačítkoZnovuNačístActionPerformed
franta-hg@30
   276
franta-hg@30
   277
    private void tlačítkoZamknoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tlačítkoZamknoutActionPerformed
franta-hg@35
   278
		try {
franta-hg@42
   279
			aktualizujPovolenéÚpravy();
franta-hg@30
   280
			model.nastavZámek(tlačítkoZamknout.isSelected());
franta-hg@30
   281
		} catch (Exception e) {
franta-hg@30
   282
			zobrazChybovouHlášku(překlady
franta-hg@30
   283
				.getString("chyba.nepodařiloSeNastavitZámek"), e);
franta-hg@30
   284
		}
franta-hg@30
   285
    }//GEN-LAST:event_tlačítkoZamknoutActionPerformed
franta-hg@30
   286
franta-hg@35
   287
    private void tlačítkoKopírovatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tlačítkoKopírovatActionPerformed
franta-hg@35
   288
		kopírujDoSchránky();
franta-hg@35
   289
    }//GEN-LAST:event_tlačítkoKopírovatActionPerformed
franta-hg@35
   290
franta-hg@6
   291
    // Variables declaration - do not modify//GEN-BEGIN:variables
franta-hg@10
   292
    private javax.swing.JScrollPane posuvnýPanel;
franta-hg@35
   293
    private javax.swing.JButton tlačítkoKopírovat;
franta-hg@10
   294
    private javax.swing.JButton tlačítkoPřidat;
franta-hg@10
   295
    private javax.swing.JButton tlačítkoSmazat;
franta-hg@30
   296
    private javax.swing.JToggleButton tlačítkoZamknout;
franta-hg@10
   297
    private javax.swing.JButton tlačítkoZnovuNačíst;
franta-hg@6
   298
    // End of variables declaration//GEN-END:variables
franta-hg@6
   299
}