Java tutorial
/************************************************************************** Skarynka - software for scan, process scanned images and build books Copyright (C) 2016 Ale Buoj?yk This file is part of Skarynka. Skarynka is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Skarynka is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. **************************************************************************/ package org.alex73.skarynka.scan.ui.book; import java.awt.Component; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableModel; import javax.swing.text.AbstractDocument; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DocumentFilter; import org.alex73.skarynka.scan.ActionErrorListener; import org.alex73.skarynka.scan.Book2; import org.alex73.skarynka.scan.Context; import org.alex73.skarynka.scan.DataStorage; import org.alex73.skarynka.scan.IBookIterator; import org.alex73.skarynka.scan.ITabController; import org.alex73.skarynka.scan.Messages; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Controller for books list panel. * * @author Ale Buoj?yk <alex73mail@gmail.com> */ public class BooksController implements ITabController { private static Logger LOG = LoggerFactory.getLogger(BooksController.class); private BooksPanel panel; private List<BookRow> books = new ArrayList<>(); private Set<String> currentBooksNames = new HashSet<>(); @Override public String getTabName() { return Messages.getString("PANEL_BOOK_TITLE"); } @Override public Component getTabComponent() { return panel; } @Override public void activate() { DataStorage.mainFrame.workMenu.setEnabled(false); DataStorage.mainFrame.viewMenu.setEnabled(false); refresh(); } @Override public void deactivate() { } @Override public void close() { } public void refresh() { int selected = panel.table.getSelectedRow(); try { listScanDirs(); } catch (Throwable ex) { LOG.error("Error list books", ex); JOptionPane.showMessageDialog(DataStorage.mainFrame, "Error: " + ex.getClass() + " / " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } ((AbstractTableModel) panel.table.getModel()).fireTableDataChanged(); if (selected >= 0) { panel.table.setRowSelectionInterval(selected, selected); } } public BooksController() { try { panel = new BooksPanel(); ((AbstractDocument) panel.txtNewName.getDocument()).setDocumentFilter(bookNameFilter); listScanDirs(); panel.table.setModel(model()); panel.table.setRowSelectionAllowed(true); panel.table.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) { BookRow b = books.get(panel.table.getSelectedRow()); DataStorage.openBook(b.bookName, true); } } @Override public void mousePressed(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)) { for (int i = 0; i < panel.menuProcess.getComponentCount(); i++) { Component item = panel.menuProcess.getComponent(i); if ((item instanceof JMenuItem) && (item.getName() != null)) { panel.menuProcess.remove(i); i--; } } if (Context.getPermissions().BookControl) { for (int scale : new int[] { 25, 50, 75, 100, 200 }) { JMenuItem item = new JMenuItem(scale + "%"); item.setName(scale + "%"); item.addActionListener(new ChangeScale(scale)); panel.menuProcess.add(item); } } currentBooksNames.clear(); int[] selected = panel.table.getSelectedRows(); boolean allLocals = true; boolean processAllowed = Context.getPermissions().BookControl; for (int row : selected) { BookRow b = books.get(panel.table.convertRowIndexToModel(row)); currentBooksNames.add(b.bookName); if (!b.local) { allLocals = false; } } panel.itemFinish.setVisible(allLocals); if (processAllowed) { for (Map.Entry<String, String> en : Context.getProcessCommands().entrySet()) { JMenuItem item = new JMenuItem(en.getValue()); item.setName(en.getKey()); item.addActionListener(commandListener); panel.menuProcess.add(item); } } panel.menuProcess.show(panel.table, e.getX(), e.getY()); } } }); panel.btnCreate.setEnabled(false); panel.btnCreate.addActionListener( new ActionErrorListener(panel, "ERROR_BOOK_CREATE", LOG, "Error create book") { protected void action(ActionEvent e) throws Exception { File bookDir = new File(Context.getBookDir(), panel.txtNewName.getText()); if (bookDir.exists()) { JOptionPane.showMessageDialog(panel, Messages.getString("PANEL_BOOK_NEW_BOOK_EXIST"), Messages.getString("PANEL_BOOK_TITLE"), JOptionPane.WARNING_MESSAGE); return; } DataStorage.openBook(panel.txtNewName.getText(), true); } }); setMenuListeners(); } catch (Throwable ex) { LOG.error("Error list books", ex); JOptionPane.showMessageDialog(DataStorage.mainFrame, "Error: " + ex.getClass() + " / " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } ActionListener commandListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String command = ((JMenuItem) e.getSource()).getName(); DataStorage.iterateByBooks(currentBooksNames, new IBookIterator() { @Override public void onBook(Book2 currentBook) throws Exception { try { File done = new File(currentBook.getBookDir(), ".process.done"); if (done.exists() && !done.delete()) { throw new Exception("Error delete .done file"); } File errors = new File(currentBook.getBookDir(), ".errors"); if (errors.exists() && !errors.delete()) { throw new Exception("Error delete .errors file"); } FileUtils.writeStringToFile(new File(currentBook.getBookDir(), ".process"), command, "UTF-8"); } catch (Throwable ex) { LOG.error("Error set comand to book", ex); JOptionPane.showMessageDialog(DataStorage.mainFrame, "Error: " + ex.getClass() + " / " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } }); refresh(); } }; class ChangeScale implements ActionListener { private final int scale; public ChangeScale(int scale) { this.scale = scale; } @Override public void actionPerformed(ActionEvent e) { DataStorage.iterateByBooks(currentBooksNames, new IBookIterator() { @Override public void onBook(Book2 currentBook) throws Exception { try { currentBook.scale = scale; currentBook.save(); } catch (Throwable ex) { LOG.error("Error set scale to book", ex); JOptionPane.showMessageDialog(DataStorage.mainFrame, "Error: " + ex.getClass() + " / " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } }); refresh(); } }; void setMenuListeners() { panel.itemFinish.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { DataStorage.iterateByBooks(currentBooksNames, new IBookIterator() { @Override public void onBook(Book2 currentBook) throws Exception { new File(currentBook.getBookDir(), ".local").delete(); currentBook.local = false; try { currentBook.save(); } catch (Exception ex) { LOG.error("Error save book '" + currentBook.getName() + "'", ex); JOptionPane.showMessageDialog(DataStorage.mainFrame, Messages.getString("ERROR_BOOK_SAVE", currentBook.getName(), ex.getMessage()), Messages.getString("ERROR_TITLE"), JOptionPane.ERROR_MESSAGE); } } }); panel.table.repaint(); } }); // panel.itemEdit.addActionListener(new ActionListener() { // @Override // public void actionPerformed(ActionEvent e) { // try { // z // } catch (Exception ex) { // LOG.error("Error save book '" + currentBook.getName() + "'", ex); // JOptionPane.showMessageDialog(DataStorage.mainFrame, // Messages.getString("ERROR_BOOK_SAVE", currentBook.getName(), ex.getMessage()), // Messages.getString("ERROR_TITLE"), JOptionPane.ERROR_MESSAGE); // } // } // }); } TableModel model() { return new DefaultTableModel() { @Override public int getColumnCount() { return Context.getPermissions().BookControl ? 4 : 3; } @Override public int getRowCount() { return books.size(); } @Override public String getColumnName(int column) { switch (column) { case 0: return Messages.getString("PANEL_BOOK_TABLE_NAME"); case 1: return Messages.getString("PANEL_BOOK_TABLE_PAGES"); case 2: return Messages.getString("PANEL_BOOK_TABLE_PAGE_SIZE"); case 3: return Messages.getString("PANEL_BOOK_TABLE_STATUS"); } return null; } @Override public boolean isCellEditable(int row, int column) { return false; } @Override public Object getValueAt(int row, int column) { BookRow b = books.get(row); switch (column) { case 0: return b.bookName; case 1: return b.pagesCount; case 2: return b.info; case 3: return b.status; } return null; } }; } public void listScanDirs() throws Exception { books.clear(); DataStorage.iterateByBooks(null, new IBookIterator() { @Override public void onBook(Book2 book) throws Exception { if (Context.getPermissions().ShowNonLocalBooks) { books.add(new BookRow(book)); } else { if (book.local) { books.add(new BookRow(book)); } } } }); } static final Pattern RE_NAME = Pattern.compile("[A-Za-z0-9_\\-]+"); DocumentFilter bookNameFilter = new DocumentFilter() { protected String check(String data) { return RE_NAME.matcher(data).matches() ? data.toLowerCase() : null; } @Override public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { super.remove(fb, offset, length); update(fb); } @Override public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { string = check(string); if (string != null) { super.insertString(fb, offset, string, attr); update(fb); } else { Toolkit.getDefaultToolkit().beep(); } } @Override public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { text = check(text); if (text != null) { super.replace(fb, offset, length, text, attrs); update(fb); } else { Toolkit.getDefaultToolkit().beep(); } } void update(FilterBypass fb) { panel.btnCreate.setEnabled(fb.getDocument().getLength() > 0); } }; }