Java tutorial
/* * Copyright 2016 Igor Maznitsa. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.igormaznitsa.sciareto.ui; import com.igormaznitsa.sciareto.ui.tabs.EditorTabPane; import com.igormaznitsa.sciareto.ui.tabs.TabTitle; import com.igormaznitsa.sciareto.preferences.PreferencesPanel; import com.igormaznitsa.sciareto.ui.tree.ExplorerTree; import com.igormaznitsa.sciareto.ui.misc.AboutPanel; import com.igormaznitsa.sciareto.ui.editors.PictureViewer; import com.igormaznitsa.sciareto.ui.editors.TextEditor; import com.igormaznitsa.sciareto.ui.editors.MMDEditor; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.KeyEventDispatcher; import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButtonMenuItem; import javax.swing.JSplitPane; import javax.swing.JWindow; import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; import javax.swing.filechooser.FileView; import org.apache.commons.io.FilenameUtils; import com.igormaznitsa.meta.annotation.MustNotContainNull; import com.igormaznitsa.mindmap.model.MindMap; import com.igormaznitsa.mindmap.model.logger.Logger; import com.igormaznitsa.mindmap.model.logger.LoggerFactory; import com.igormaznitsa.mindmap.swing.panel.utils.Utils; import com.igormaznitsa.sciareto.Context; import com.igormaznitsa.sciareto.Main; import com.igormaznitsa.sciareto.preferences.FileHistoryManager; import com.igormaznitsa.sciareto.preferences.PreferencesManager; import com.igormaznitsa.sciareto.ui.misc.DonateButton; import com.igormaznitsa.sciareto.ui.tree.NodeFileOrFolder; import com.igormaznitsa.sciareto.ui.tree.NodeProject; public final class MainFrame extends javax.swing.JFrame implements Context { private static final long serialVersionUID = 3798040833406256900L; private static final Logger LOGGER = LoggerFactory.getLogger(MainFrame.class); private static final boolean DELETE_MOVING_FILE_TO_TRASH = true; private final EditorTabPane tabPane; private final ExplorerTree explorerTree; private final boolean stateless; private final AtomicReference<Runnable> taskToEndFullScreen = new AtomicReference<>(); private final JPanel stackPanel; public MainFrame(@Nonnull @MustNotContainNull final String... args) { super(); initComponents(); this.stackPanel = new JPanel(); this.stackPanel.setFocusable(false); this.stackPanel.setOpaque(false); this.stackPanel.setBorder(BorderFactory.createEmptyBorder(32, 32, 16, 32)); this.stackPanel.setLayout(new BoxLayout(this.stackPanel, BoxLayout.Y_AXIS)); final JPanel glassPanel = (JPanel) this.getGlassPane(); glassPanel.setOpaque(false); this.setGlassPane(glassPanel); glassPanel.setLayout(new BorderLayout(8, 8)); glassPanel.add(Box.createGlue(), BorderLayout.CENTER); final JPanel ppanel = new JPanel(new BorderLayout(0, 0)); ppanel.setFocusable(false); ppanel.setOpaque(false); ppanel.setCursor(null); ppanel.add(this.stackPanel, BorderLayout.SOUTH); glassPanel.add(ppanel, BorderLayout.EAST); this.stackPanel.add(Box.createGlue()); glassPanel.setVisible(false); this.setTitle("Scia Reto"); setIconImage(UiUtils.loadImage("logo256x256.png")); this.stateless = args.length > 0; final MainFrame theInstance = this; this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(@Nonnull final WindowEvent e) { if (doClosing()) { dispose(); } } }); this.tabPane = new EditorTabPane(this); this.explorerTree = new ExplorerTree(this); final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); splitPane.setOneTouchExpandable(true); splitPane.setDividerLocation(250); splitPane.setResizeWeight(0.0d); splitPane.setLeftComponent(this.explorerTree); splitPane.setRightComponent(this.tabPane); add(splitPane, BorderLayout.CENTER); this.menuOpenRecentProject.addMenuListener(new MenuListener() { @Override public void menuSelected(MenuEvent e) { final File[] lastOpenedProjects = FileHistoryManager.getInstance().getLastOpenedProjects(); if (lastOpenedProjects.length > 0) { for (final File folder : lastOpenedProjects) { final JMenuItem item = new JMenuItem(folder.getName()); item.setToolTipText(folder.getAbsolutePath()); item.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { openProject(folder, false); } }); menuOpenRecentProject.add(item); } } } @Override public void menuDeselected(MenuEvent e) { menuOpenRecentProject.removeAll(); } @Override public void menuCanceled(MenuEvent e) { } }); this.menuOpenRecentFile.addMenuListener(new MenuListener() { @Override public void menuSelected(MenuEvent e) { final File[] lastOpenedFiles = FileHistoryManager.getInstance().getLastOpenedFiles(); if (lastOpenedFiles.length > 0) { for (final File file : lastOpenedFiles) { final JMenuItem item = new JMenuItem(file.getName()); item.setToolTipText(file.getAbsolutePath()); item.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { openFileAsTab(file); } }); menuOpenRecentFile.add(item); } } } @Override public void menuDeselected(MenuEvent e) { menuOpenRecentFile.removeAll(); } @Override public void menuCanceled(MenuEvent e) { } }); if (!this.stateless) { restoreState(); } else { boolean openedProject = false; for (final String filePath : args) { final File file = new File(filePath); if (file.isDirectory()) { openedProject = true; openProject(file, true); } else if (file.isFile()) { openFileAsTab(file); } } if (!openedProject) { //TODO try to hide project panel! } } final LookAndFeel current = UIManager.getLookAndFeel(); final ButtonGroup lfGroup = new ButtonGroup(); final String currentLFClassName = current.getClass().getName(); for (final UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { final JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(info.getName()); lfGroup.add(menuItem); if (currentLFClassName.equals(info.getClassName())) { menuItem.setSelected(true); } menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(@Nonnull final ActionEvent e) { try { UIManager.setLookAndFeel(info.getClassName()); SwingUtilities.updateComponentTreeUI(theInstance); PreferencesManager.getInstance().getPreferences().put(Main.PROPERTY_LOOKANDFEEL, info.getClassName()); PreferencesManager.getInstance().flush(); } catch (Exception ex) { LOGGER.error("Can't change LF", ex); } } }); this.menuLookAndFeel.add(menuItem); } } public JPanel getStackPanel() { return this.stackPanel; } private boolean doClosing() { endFullScreenIfActive(); boolean hasUnsaved = false; for (final TabTitle t : tabPane) { hasUnsaved |= t.isChanged(); } if (hasUnsaved) { if (!DialogProviderManager.getInstance().getDialogProvider().msgConfirmOkCancel( "Detected non-saved documents", "Detected unsaved documents! Close application?")) { return false; } } if (!this.stateless) { saveState(); } return true; } @Override public void notifyFileRenamed(@Nonnull final File oldFile, @Nonnull final File newFile) { this.tabPane.replaceFileLink(oldFile, newFile); } @Override public boolean safeCloseEditorsForFile(@Nonnull final File file) { boolean changed = false; final List<TabTitle> list = new ArrayList<>(); for (final TabTitle t : this.tabPane) { if (t.belongFolderOrSame(file)) { list.add(t); changed |= t.isChanged(); } } if (changed && !DialogProviderManager.getInstance().getDialogProvider().msgConfirmOkCancel("Confirmation", "Some changed file will be affected! To close them?")) { return false; } closeTab(list.toArray(new TabTitle[list.size()])); return true; } private void restoreState() { try { final File[] activeProjects = FileHistoryManager.getInstance().getActiveProjects(); for (final File f : activeProjects) { if (f.isDirectory()) { openProject(f, true); } } final File[] activeFiles = FileHistoryManager.getInstance().getActiveFiles(); for (final File f : activeFiles) { if (f.isFile()) { openFileAsTab(f); } } } catch (IOException ex) { LOGGER.error("Can't restore state", ex); } } private void saveState() { try { final List<File> files = new ArrayList<>(); for (final NodeProject p : this.explorerTree.getCurrentGroup()) { final File f = p.getFolder(); if (f.isDirectory()) { files.add(f); } } FileHistoryManager.getInstance().saveActiveProjects(files.toArray(new File[files.size()])); files.clear(); for (final TabTitle p : this.tabPane) { final File f = p.getAssociatedFile(); if (f != null && f.isFile()) { files.add(f); } } FileHistoryManager.getInstance().saveActiveFiles(files.toArray(new File[files.size()])); } catch (IOException ex) { LOGGER.error("Can't save state", ex); } } @Override public boolean openFileAsTab(@Nonnull final File file) { boolean result = false; if (file.isFile()) { if (this.tabPane.focusToFile(file)) { result = true; } else { final String ext = FilenameUtils.getExtension(file.getName()).toLowerCase(Locale.ENGLISH); if (ext.equals("mmd")) { try { final MMDEditor panel = new MMDEditor(this, file); this.tabPane.createTab(panel); result = true; } catch (IOException ex) { LOGGER.error("Can't load mind map", ex); } } else if (PictureViewer.SUPPORTED_FORMATS.contains(ext)) { try { final PictureViewer panel = new PictureViewer(this, file); this.tabPane.createTab(panel); result = true; } catch (IOException ex) { LOGGER.error("Can't load file as image", ex); } } else { if (file.length() >= (2L * 1024L * 1024L) && !DialogProviderManager.getInstance().getDialogProvider().msgConfirmYesNo( "Very big file", "It is a very big file! Are you sure to open it?")) { return true; } try { final TextEditor panel = new TextEditor(this, file); this.tabPane.createTab(panel); result = true; } catch (IOException ex) { LOGGER.error("Can't load file as text", ex); } } } } if (result) { try { FileHistoryManager.getInstance().registerOpenedFile(file); } catch (IOException x) { LOGGER.error("Can't register last opened file", x); } } return result; } @Override public void focusInTree(@Nonnull final TabTitle title) { final File file = title.getAssociatedFile(); if (file != null) { this.explorerTree.focusToFileItem(file); } } @Override public void focusInTree(@Nonnull final File file) { this.explorerTree.focusToFileItem(file); } @Override public void closeTab(@Nonnull final TabTitle... titles) { for (final TabTitle t : titles) { this.tabPane.removeTab(t); } } @Override @Nullable public NodeProject findProjectForFile(@Nonnull final File file) { return this.explorerTree.getCurrentGroup().findProjectForFile(file); } @Override public void notifyReloadConfig() { for (final TabTitle t : this.tabPane) { final JComponent editor = t.getProvider().getMainComponent(); if (editor instanceof MMDEditor) { ((MMDEditor) editor).refreshConfig(); } } } @Override public void onCloseProject(@Nonnull final NodeProject project) { final File projectFolder = project.getFolder(); for (final TabTitle t : this.tabPane) { if (t.belongFolderOrSame(projectFolder)) { t.doSafeClose(); } } } @Nullable @MustNotContainNull private List<File> selectAffectedFiles(final List<File> files) { final FileListPanel panel = new FileListPanel(files); if (DialogProviderManager.getInstance().getDialogProvider().msgOkCancel("Affected files", panel)) { return panel.getSelectedFiles(); } return null; } @Override public boolean deleteTreeNode(@Nonnull final NodeFileOrFolder node) { final File file = node.makeFileForNode(); if (file != null && file.exists()) { final List<TabTitle> tabsToClose = this.tabPane.findListOfRelatedTabs(file); boolean hasUnsaved = false; for (final TabTitle t : tabsToClose) { hasUnsaved |= t.isChanged(); } if (hasUnsaved && !DialogProviderManager.getInstance().getDialogProvider() .msgConfirmOkCancel("Confirmation", "Are you sure to delete changed unsaved file?")) { return false; } closeTab(tabsToClose.toArray(new TabTitle[tabsToClose.size()])); final NodeProject project = findProjectForFile(file); List<File> affectedFiles = project == null ? Collections.EMPTY_LIST : project.findAffectedFiles(file); final Iterator<File> iterator = affectedFiles.iterator(); final Path removingFile = file.toPath(); while (iterator.hasNext()) { if (iterator.next().toPath().startsWith(removingFile)) { iterator.remove(); } } if (!affectedFiles.isEmpty()) { affectedFiles = selectAffectedFiles(affectedFiles); if (affectedFiles == null) { return false; } } boolean ok = false; if (file.isDirectory()) { if (SystemUtils.deleteFile(file, DELETE_MOVING_FILE_TO_TRASH)) { ok = true; } else { DialogProviderManager.getInstance().getDialogProvider() .msgError("Can't delete directory, see the log!"); } } else { ok = SystemUtils.deleteFile(file, DELETE_MOVING_FILE_TO_TRASH); if (!ok) { DialogProviderManager.getInstance().getDialogProvider().msgError("Can't delete file!"); } } if (ok) { explorerTree.deleteNode(node); } if (!affectedFiles.isEmpty()) { project.deleteAllLinksToFile(affectedFiles, file); } return ok; } return false; } /** * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always regenerated by the Form * Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jMenuBar1 = new javax.swing.JMenuBar(); menuFile = new javax.swing.JMenu(); menuNewProject = new javax.swing.JMenuItem(); jSeparator2 = new javax.swing.JPopupMenu.Separator(); menuOpenProject = new javax.swing.JMenuItem(); menuOpenRecentProject = new javax.swing.JMenu(); menuOpenFile = new javax.swing.JMenuItem(); menuOpenRecentFile = new javax.swing.JMenu(); jSeparator3 = new javax.swing.JPopupMenu.Separator(); menSave = new javax.swing.JMenuItem(); menuSaveAs = new javax.swing.JMenuItem(); menuSaveAll = new javax.swing.JMenuItem(); jSeparator1 = new javax.swing.JPopupMenu.Separator(); menuExit = new javax.swing.JMenuItem(); menuEdit = new javax.swing.JMenu(); menuPreferences = new javax.swing.JMenuItem(); menuView = new javax.swing.JMenu(); menuFullScreen = new javax.swing.JMenuItem(); menuLookAndFeel = new javax.swing.JMenu(); menuHelp = new javax.swing.JMenu(); menuAbout = new javax.swing.JMenuItem(); jSeparator4 = new javax.swing.JPopupMenu.Separator(); menuMakeDonation = new javax.swing.JMenuItem(); setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); setLocationByPlatform(true); menuFile.setText("File"); menuNewProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/box_closed.png"))); // NOI18N menuNewProject.setText("New Project"); menuNewProject.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuNewProjectActionPerformed(evt); } }); menuFile.add(menuNewProject); menuFile.add(jSeparator2); menuOpenProject.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.SHIFT_MASK | java.awt.event.InputEvent.CTRL_MASK)); menuOpenProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/open_folder.png"))); // NOI18N menuOpenProject.setText("Open Project"); menuOpenProject.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuOpenProjectActionPerformed(evt); } }); menuFile.add(menuOpenProject); menuOpenRecentProject.setText("Open Recent Project"); menuFile.add(menuOpenRecentProject); menuOpenFile.setText("Open File"); menuOpenFile.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuOpenFileActionPerformed(evt); } }); menuFile.add(menuOpenFile); menuOpenRecentFile.setText("Open Recent File"); menuFile.add(menuOpenRecentFile); menuFile.add(jSeparator3); menSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/diskette.png"))); // NOI18N menSave.setText("Save"); menSave.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menSaveActionPerformed(evt); } }); menuFile.add(menSave); menuSaveAs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/file_save_as.png"))); // NOI18N menuSaveAs.setText("Save As"); menuSaveAs.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuSaveAsActionPerformed(evt); } }); menuFile.add(menuSaveAs); menuSaveAll.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK)); menuSaveAll.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/disk_multiple.png"))); // NOI18N menuSaveAll.setText("Save All"); menuSaveAll.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuSaveAllActionPerformed(evt); } }); menuFile.add(menuSaveAll); menuFile.add(jSeparator1); menuExit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F4, java.awt.event.InputEvent.ALT_MASK)); menuExit.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/door_in.png"))); // NOI18N menuExit.setText("Exit"); menuExit.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuExitActionPerformed(evt); } }); menuFile.add(menuExit); jMenuBar1.add(menuFile); menuEdit.setText("Edit"); menuPreferences.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/setting_tools.png"))); // NOI18N menuPreferences.setText("Preferences"); menuPreferences.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuPreferencesActionPerformed(evt); } }); menuEdit.add(menuPreferences); jMenuBar1.add(menuEdit); menuView.setText("View"); menuFullScreen.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F11, 0)); menuFullScreen.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/monitor.png"))); // NOI18N menuFullScreen.setText("Full screen"); menuFullScreen.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuFullScreenActionPerformed(evt); } }); menuView.add(menuFullScreen); menuLookAndFeel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/application.png"))); // NOI18N menuLookAndFeel.setText("Look and Feel"); menuView.add(menuLookAndFeel); jMenuBar1.add(menuView); menuHelp.setText("Help"); menuAbout.setIcon(new javax.swing.ImageIcon(getClass().getResource("/menu_icons/information.png"))); // NOI18N menuAbout.setText("About"); menuAbout.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuAboutActionPerformed(evt); } }); menuHelp.add(menuAbout); menuHelp.add(jSeparator4); menuMakeDonation.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/coins_in_hand16.png"))); // NOI18N menuMakeDonation.setText("Make donation"); menuMakeDonation.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuMakeDonationActionPerformed(evt); } }); menuHelp.add(menuMakeDonation); jMenuBar1.add(menuHelp); setJMenuBar(jMenuBar1); pack(); }// </editor-fold>//GEN-END:initComponents private void menuAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuAboutActionPerformed JOptionPane.showMessageDialog(Main.getApplicationFrame(), new AboutPanel(), "About", JOptionPane.PLAIN_MESSAGE); }//GEN-LAST:event_menuAboutActionPerformed private void menuOpenProjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuOpenProjectActionPerformed final JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileView(new FileView() { private Icon KNOWLEDGE_FOLDER_ICO = null; @Override public Icon getIcon(final File f) { if (f.isDirectory()) { final File knowledge = new File(f, ".projectKnowledge"); if (knowledge.isDirectory()) { if (KNOWLEDGE_FOLDER_ICO == null) { final Icon icon = UIManager.getIcon("FileView.directoryIcon"); if (icon != null) { KNOWLEDGE_FOLDER_ICO = new ImageIcon( UiUtils.makeBadgedRightBottom(UiUtils.iconToImage(fileChooser, icon), Icons.MMDBADGE.getIcon().getImage())); } } return KNOWLEDGE_FOLDER_ICO; } else { return super.getIcon(f); } } else if (f.isFile() && f.getName().toLowerCase(Locale.ENGLISH).endsWith(".mmd")) { return Icons.DOCUMENT.getIcon(); } else { return super.getIcon(f); } } }); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); fileChooser.setMultiSelectionEnabled(false); fileChooser.setDialogTitle("Open project folder"); if (fileChooser.showOpenDialog(Main.getApplicationFrame()) == JFileChooser.APPROVE_OPTION) { openProject(fileChooser.getSelectedFile(), false); } }//GEN-LAST:event_menuOpenProjectActionPerformed @Override public boolean openProject(@Nonnull final File folder, final boolean enforceSeparatedProject) { boolean result = false; if (folder.isDirectory()) { final NodeProject alreadyOpened = findProjectForFile(folder); if (alreadyOpened == null || enforceSeparatedProject) { final boolean firstProject = this.explorerTree.getCurrentGroup().getChildCount() == 0; final NodeProject node = this.explorerTree.getCurrentGroup().addProjectFolder(folder); if (firstProject) { this.explorerTree.unfoldProject(node); } try { FileHistoryManager.getInstance().registerOpenedProject(folder); } catch (IOException ex) { LOGGER.error("Can't register last opened project", ex); } } else { this.focusInTree(folder); } result = true; } else { LOGGER.error("Can't find folder : " + folder); DialogProviderManager.getInstance().getDialogProvider().msgError("Can't find project folder!"); } return result; } @Override public void editPreferences() { final PreferencesPanel configPanel = new PreferencesPanel(this); configPanel.load(); if (DialogProviderManager.getInstance().getDialogProvider().msgOkCancel("Preferences", configPanel)) { configPanel.save(); } } private void menuSaveAllActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuSaveAllActionPerformed for (final TabTitle t : this.tabPane) { try { t.save(); } catch (IOException ex) { LOGGER.error("Can't save file", ex); DialogProviderManager.getInstance().getDialogProvider() .msgError("Can't save document, may be it is read-only! See log!"); } } }//GEN-LAST:event_menuSaveAllActionPerformed private void menuPreferencesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuPreferencesActionPerformed editPreferences(); }//GEN-LAST:event_menuPreferencesActionPerformed private void menuOpenFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuOpenFileActionPerformed final File file = DialogProviderManager.getInstance().getDialogProvider().msgOpenFileDialog("open-file", "Open file", null, true, MMDEditor.MMD_FILE_FILTER, "Open"); if (file != null) { if (openFileAsTab(file)) { try { FileHistoryManager.getInstance().registerOpenedProject(file); } catch (IOException ex) { LOGGER.error("Can't register last opened file", ex); } } } }//GEN-LAST:event_menuOpenFileActionPerformed private void menSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menSaveActionPerformed final int index = this.tabPane.getSelectedIndex(); if (index >= 0) { try { ((TabTitle) this.tabPane.getTabComponentAt(index)).save(); } catch (IOException ex) { LOGGER.error("Can't save file", ex); DialogProviderManager.getInstance().getDialogProvider() .msgError("Can't save document, may be it is read-only! See log!"); } } }//GEN-LAST:event_menSaveActionPerformed private void menuSaveAsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuSaveAsActionPerformed final int index = this.tabPane.getSelectedIndex(); if (index >= 0) { try { ((TabTitle) this.tabPane.getTabComponentAt(index)).saveAs(); } catch (IOException ex) { LOGGER.error("Can't save file", ex); DialogProviderManager.getInstance().getDialogProvider() .msgError("Can't save document, may be it is read-only! See log!"); } } }//GEN-LAST:event_menuSaveAsActionPerformed private void menuExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuExitActionPerformed if (doClosing()) { dispose(); } }//GEN-LAST:event_menuExitActionPerformed private void menuNewProjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuNewProjectActionPerformed final JFileChooser folder = new JFileChooser(); folder.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); folder.setDialogTitle("Create project folder"); folder.setApproveButtonText("Create"); folder.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); if (folder.showOpenDialog(Main.getApplicationFrame()) == JFileChooser.APPROVE_OPTION) { final File file = folder.getSelectedFile(); if (file.exists()) { DialogProviderManager.getInstance().getDialogProvider() .msgError("File '" + file.getName() + "' already exists!"); } else if (file.mkdirs()) { if (PreferencesManager.getInstance().getPreferences() .getBoolean(PreferencesPanel.PREFERENCE_KEY_KNOWLEDGEFOLDER_ALLOWED, true)) { final File knowledgeFolder = new File(file, ".projectKnowledge"); knowledgeFolder.mkdirs(); } if (openProject(file, true)) { this.focusInTree(file); } } else { LOGGER.error("Can't create folder : " + file); DialogProviderManager.getInstance().getDialogProvider().msgError("Can't create folder: " + file); } } }//GEN-LAST:event_menuNewProjectActionPerformed private void menuFullScreenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuFullScreenActionPerformed final Component currentComponent = this.tabPane.getSelectedComponent(); if (!(currentComponent instanceof Container)) { LOGGER.warn("Detected attempt to full screen not a container : " + currentComponent); return; } final GraphicsConfiguration gconfig = this.getGraphicsConfiguration(); if (gconfig != null) { final GraphicsDevice device = gconfig.getDevice(); if (device.isFullScreenSupported()) { if (device.getFullScreenWindow() == null) { final JLabel label = new JLabel("Opened in full screen"); final int tabIndex = this.tabPane.getSelectedIndex(); this.tabPane.setComponentAt(tabIndex, label); final JWindow window = new JWindow(Main.getApplicationFrame()); window.setAlwaysOnTop(true); window.setContentPane((Container) currentComponent); endFullScreenIfActive(); final KeyEventDispatcher fullScreenEscCatcher = new KeyEventDispatcher() { @Override public boolean dispatchKeyEvent(@Nonnull final KeyEvent e) { if (e.getID() == KeyEvent.KEY_PRESSED && (e.getKeyCode() == KeyEvent.VK_ESCAPE || e.getKeyCode() == KeyEvent.VK_F11)) { endFullScreenIfActive(); return true; } return false; } }; if (this.taskToEndFullScreen.compareAndSet(null, new Runnable() { @Override public void run() { try { window.dispose(); } finally { tabPane.setComponentAt(tabIndex, currentComponent); device.setFullScreenWindow(null); KeyboardFocusManager.getCurrentKeyboardFocusManager() .removeKeyEventDispatcher(fullScreenEscCatcher); } } })) { try { KeyboardFocusManager.getCurrentKeyboardFocusManager() .addKeyEventDispatcher(fullScreenEscCatcher); device.setFullScreenWindow(window); } catch (Exception ex) { LOGGER.error("Can't turn on full screen", ex); endFullScreenIfActive(); KeyboardFocusManager.getCurrentKeyboardFocusManager() .removeKeyEventDispatcher(fullScreenEscCatcher); } } else { LOGGER.error("Unexpected state, processor is not null!"); } } else { LOGGER.warn("Attempt to full screen device which already in full screen!"); } } else { LOGGER.warn("Device doesn's support full screen"); DialogProviderManager.getInstance().getDialogProvider() .msgWarn("The Device doesn't support full-screen mode!"); } } else { LOGGER.warn("Can't find graphics config for the frame"); } }//GEN-LAST:event_menuFullScreenActionPerformed private void menuMakeDonationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuMakeDonationActionPerformed new DonateButton().doClick(); }//GEN-LAST:event_menuMakeDonationActionPerformed public void endFullScreenIfActive() { final Runnable runnable = this.taskToEndFullScreen.getAndSet(null); if (runnable != null) { Utils.safeSwingCall(runnable); } } @Nullable @Override public File createMindMapFile(@Nullable final File folder) { final JFileChooser chooser = new JFileChooser(folder); chooser.setDialogTitle("Create new Mind Map"); chooser.setFileFilter(MMDEditor.MMD_FILE_FILTER); chooser.setMultiSelectionEnabled(false); chooser.setApproveButtonText("Create"); File result = null; if (chooser.showSaveDialog(Main.getApplicationFrame()) == JFileChooser.APPROVE_OPTION) { File file = chooser.getSelectedFile(); if (!file.getName().endsWith(".mmd")) { file = new File(file.getAbsolutePath() + ".mmd"); } if (file.exists()) { DialogProviderManager.getInstance().getDialogProvider() .msgError("File '" + file + "' already exists!"); } else { try { final MindMap mindMap = new MindMap(null, true); final String text = mindMap.write(new StringWriter()).toString(); SystemUtils.saveUTFText(file, text); result = file; } catch (IOException ex) { DialogProviderManager.getInstance().getDialogProvider() .msgError("Can't save mind map into file '" + file.getName() + "'"); } } } return result; } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JMenuBar jMenuBar1; private javax.swing.JPopupMenu.Separator jSeparator1; private javax.swing.JPopupMenu.Separator jSeparator2; private javax.swing.JPopupMenu.Separator jSeparator3; private javax.swing.JPopupMenu.Separator jSeparator4; private javax.swing.JMenuItem menSave; private javax.swing.JMenuItem menuAbout; private javax.swing.JMenu menuEdit; private javax.swing.JMenuItem menuExit; private javax.swing.JMenu menuFile; private javax.swing.JMenuItem menuFullScreen; private javax.swing.JMenu menuHelp; private javax.swing.JMenu menuLookAndFeel; private javax.swing.JMenuItem menuMakeDonation; private javax.swing.JMenuItem menuNewProject; private javax.swing.JMenuItem menuOpenFile; private javax.swing.JMenuItem menuOpenProject; private javax.swing.JMenu menuOpenRecentFile; private javax.swing.JMenu menuOpenRecentProject; private javax.swing.JMenuItem menuPreferences; private javax.swing.JMenuItem menuSaveAll; private javax.swing.JMenuItem menuSaveAs; private javax.swing.JMenu menuView; // End of variables declaration//GEN-END:variables }