package tk.amberide.ide.gui; import tk.amberide.Amber; import tk.amberide.ide.data.Workspace; import tk.amberide.ide.data.io.FileMonitor; import tk.amberide.ide.data.io.FileMonitor.FileListener; import tk.amberide.ide.data.state.LazyState; import tk.amberide.ide.data.state.Scope; import tk.amberide.ide.data.state.node.IState; import tk.amberide.ide.gui.editor.tool.ToolPanel; import tk.amberide.ide.gui.misc.FileTreeExplorer; import tk.amberide.ide.swing.tabs.CloseableTabbedPane; import tk.amberide.ide.swing.tabs.CloseableTabbedPane.CloseableTabComponent; import tk.amberide.ide.swing.tabs.TabCloseListener; import tk.amberide.ide.swing.tree.SmartExpander; import tk.amberide.ide.swing.tree.Trees; import tk.amberide.ide.swing.tree.filesystem.FileSystemTree; import tk.amberide.ide.tool.ToolDefinition; import tk.amberide.ide.tool.ToolManifest; import java.awt.*; import java.io.File; import java.util.Arrays; import java.util.HashMap; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * * @author Tudor */ public class MainContentPanel extends javax.swing.JPanel { protected HashMap<Component, String> activeFiles = new HashMap<Component, String>(); protected CloseableTabbedPane activeFilesTabbedPane; protected FileMonitor monitor; protected JLabel openFileLabel = new JLabel("Double-click a file to open it.", JLabel.CENTER); protected JPanel statusBar = new JPanel(new BorderLayout()); @LazyState(scope = Scope.PROJECT, name = "ProjectTreeExpansion") protected String saveTreeExpansion() { return Trees.getExpansionState(treeView, 0); } /** * Creates new form MainIDEPanel */ public MainContentPanel(Workspace workspace) { initComponents(); Amber.getStateManager().unregisterStateOwner(this); treeView.addFileTreeAdapter(new FileTreeExplorer(treeView)); treeView.setRoot(workspace.getRootDirectory()); IState treeState = Amber.getStateManager().getState(Scope.PROJECT, "ProjectTreeExpansion"); if (treeState != null) { Trees.restoreExpanstionState(treeView, 0, (String) treeState.get()); } Amber.getStateManager().registerStateOwner(this); SmartExpander.installOn(treeView); treeView.setRootVisible(true); monitor = new FileMonitor(1500); monitor.addFile(workspace.getRootDirectory()); monitor.addListener(new FileListener(){ public void fileChanged(File file) { treeView.synchronize(); } }); projectDivider.setRightComponent(openFileLabel); } @Override public void removeNotify() { monitor.stop(); } public static boolean askToSaveFile(Component parent, Component... files) { CloseableTabbedPane tabs = Amber.getUI().getContentPanel().getFilesTabbedPane(); for (Component c : files) { if (!(c instanceof FileViewerPanel)) continue; FileViewerPanel file = (FileViewerPanel) c; if (!file.modified()) continue; if (tabs != null) tabs.setSelectedComponent(file); switch (JOptionPane.showConfirmDialog(parent, "Do you want to save the following file:\n" + file.getFile().getName(), "Confirm Close", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE)) { case JOptionPane.YES_OPTION: file.save(); break; case JOptionPane.NO_OPTION: break; case JOptionPane.CANCEL_OPTION: return false; } } return true; } public CloseableTabbedPane getFilesTabbedPane() { if (activeFilesTabbedPane == null) { activeFilesTabbedPane = new CloseableTabbedPane(); activeFilesTabbedPane.addTabCloseListener(new TabCloseListener() { public boolean tabClosed(String title, Component comp, CloseableTabbedPane pane) { if (comp instanceof FileViewerPanel && !askToSaveFile(MainContentPanel.this, comp)) return false; if (activeFiles.containsKey(comp)) { Amber.getWorkspace().getOpenedFiles().remove(activeFiles.remove(comp)); } if (activeFilesTabbedPane.getTabCount() == 1) { projectDivider.setRightComponent(openFileLabel); activeFilesTabbedPane = null; } return true; } }); activeFilesTabbedPane.addChangeListener(new ChangeListener() { int oldMenuCount = 0; @Override public void stateChanged(ChangeEvent e) { if (!(e.getSource() instanceof CloseableTabbedPane)) return; JMenuBar menuBar = Amber.getUI().getMenu(); for (int i = 0; i < oldMenuCount; ++i) { menuBar.remove(menuBar.getMenuCount() - 2); } statusBar.removeAll(); Component component = ((CloseableTabbedPane) e.getSource()).getSelectedComponent(); if (component instanceof FileViewerPanel) { JMenu[] menus = ((FileViewerPanel) component).getContextMenus(); for (JMenu menu : menus) { menuBar.add(menu, menuBar.getComponentCount() - 1); // Help menu should always be last } oldMenuCount = menus.length; JComponent status = ((FileViewerPanel) component).getStatusBar(); if (status != null) statusBar.add(status, BorderLayout.CENTER); } else { oldMenuCount = 0; } menuBar.revalidate(); } }); int location = projectDivider.getDividerLocation(); projectDivider.setRightComponent(activeFilesTabbedPane); projectDivider.setDividerLocation(location); } return activeFilesTabbedPane; } public void addTab(String id, Component tab) { activeFilesTabbedPane.add(id, tab); } public void addFileTab(FileViewerPanel file) { try { getFilesTabbedPane().add(file.getFile().getName(), file); } catch (RuntimeException ex) { getFilesTabbedPane().remove(file); throw ex; // Propagate to the error handler in FileTreeExplorer } activeFiles.put(file, file.getFile().getAbsolutePath()); int i = getFilesTabbedPane().getTabCount() - 1; getFilesTabbedPane().setSelectedIndex(i); ((CloseableTabComponent) getFilesTabbedPane().getTabComponentAt(i)).getTitleLabel().setIcon(file.getTabIcon()); } public void addToolTab(ToolDefinition tool) { ToolPanel toolPanel = new ToolPanel(tool); ToolManifest mf = tool.getManifest(); try { getFilesTabbedPane().add(mf.name(), toolPanel); } catch (RuntimeException ex) { getFilesTabbedPane().remove(toolPanel); throw ex; // Propagate to the error handler in FileTreeExplorer } getFilesTabbedPane().setToolTipTextAt(getFilesTabbedPane().getTabCount() - 1, String.format("<html>" + "<b>%s</b> v%s by %s" + "<br/>" + "   %s" + "</html>", mf.name(), mf.version(), Arrays.toString(mf.authors()), mf.description())); getFilesTabbedPane().setSelectedIndex(getFilesTabbedPane().getTabCount() - 1); } public FileSystemTree getFileTree() { return treeView; } public Component getStatusBar() { return statusBar; } /** * 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() { projectDivider = new tk.amberide.ide.swing.misc.ThinSplitPane(); jScrollPane1 = new javax.swing.JScrollPane(); treeView = new tk.amberide.ide.swing.tree.filesystem.FileSystemTree(); setLayout(new java.awt.BorderLayout()); projectDivider.setDividerLocation(150); projectDivider.setDividerSize(0); projectDivider.setMinimumSize(new java.awt.Dimension(0, 0)); jScrollPane1.setBorder(null); jScrollPane1.setMinimumSize(new java.awt.Dimension(0, 0)); jScrollPane1.setViewportView(treeView); projectDivider.setLeftComponent(jScrollPane1); add(projectDivider, java.awt.BorderLayout.CENTER); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JScrollPane jScrollPane1; private tk.amberide.ide.swing.misc.ThinSplitPane projectDivider; private tk.amberide.ide.swing.tree.filesystem.FileSystemTree treeView; // End of variables declaration//GEN-END:variables }