package com.revolsys.swing.map; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.Window; import java.awt.event.ContainerAdapter; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JRootPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.KeyStroke; import javax.swing.tree.TreePath; import com.revolsys.collection.set.Sets; import com.revolsys.datatype.DataTypes; import com.revolsys.geometry.model.BoundingBox; import com.revolsys.geometry.util.BoundingBoxUtil; import com.revolsys.io.FileUtil; import com.revolsys.io.file.FileConnectionManager; import com.revolsys.io.file.FileNameExtensionFilter; import com.revolsys.io.file.FolderConnectionRegistry; import com.revolsys.io.file.Paths; import com.revolsys.logging.Logs; import com.revolsys.process.JavaProcess; import com.revolsys.record.io.RecordStoreConnection; import com.revolsys.record.io.RecordStoreConnectionManager; import com.revolsys.record.io.RecordStoreConnectionRegistry; import com.revolsys.spring.resource.PathResource; import com.revolsys.swing.EventQueue; import com.revolsys.swing.Icons; import com.revolsys.swing.SwingUtil; import com.revolsys.swing.TabbedPane; import com.revolsys.swing.action.RunnableAction; import com.revolsys.swing.action.enablecheck.ObjectPropertyEnableCheck; import com.revolsys.swing.component.BaseFrame; import com.revolsys.swing.component.DnDTabbedPane; import com.revolsys.swing.component.TabClosableTitle; import com.revolsys.swing.logging.Log4jTableModel; import com.revolsys.swing.map.form.RecordStoreConnectionForm; import com.revolsys.swing.map.layer.Layer; import com.revolsys.swing.map.layer.LayerGroup; import com.revolsys.swing.map.layer.Project; import com.revolsys.swing.map.overlay.MeasureOverlay; import com.revolsys.swing.map.print.SinglePage; import com.revolsys.swing.menu.MenuFactory; import com.revolsys.swing.parallel.Invoke; import com.revolsys.swing.parallel.SwingWorkerProgressBar; import com.revolsys.swing.pdf.SaveAsPdf; import com.revolsys.swing.preferences.PreferencesDialog; import com.revolsys.swing.scripting.ScriptRunner; import com.revolsys.swing.table.worker.SwingWorkerTableModel; import com.revolsys.swing.tree.BaseTree; import com.revolsys.swing.tree.BaseTreeNode; import com.revolsys.swing.tree.node.ListTreeNode; import com.revolsys.swing.tree.node.WebServiceConnectionTrees; import com.revolsys.swing.tree.node.file.FolderConnectionsTrees; import com.revolsys.swing.tree.node.file.PathTreeNode; import com.revolsys.swing.tree.node.layer.ProjectTreeNode; import com.revolsys.swing.tree.node.record.RecordStoreConnectionTrees; import com.revolsys.util.OS; import com.revolsys.util.PreferencesUtil; import com.revolsys.util.Property; import com.revolsys.webservice.WebServiceConnectionManager; import com.revolsys.webservice.WebServiceConnectionRegistry; public class ProjectFrame extends BaseFrame { private static final String BOTTOM_TAB = "INTERNAL_bottomTab"; private static final String BOTTOM_TAB_LISTENER = "INTERNAL_bottomTabListener"; public static final String PROJECT_FRAME = "INTERNAL_projectFrame"; public static final String SAVE_CHANGES_KEY = "Save Changes"; public static final String SAVE_PROJECT_KEY = "Save Project"; private static final long serialVersionUID = 1L; static { RecordStoreConnectionManager.setInvalidRecordStoreFunction((connection, exception) -> { return Invoke.andWait(() -> { final RecordStoreConnectionRegistry registry = connection.getRegistry(); final RecordStoreConnectionForm form = new RecordStoreConnectionForm(registry, connection, exception); return form.showDialog(); }); }); RecordStoreConnectionManager.setMissingRecordStoreFunction((name) -> { final RecordStoreConnectionRegistry registry = RecordStoreConnectionManager.get() .getUserConnectionRegistry(); Invoke.andWait(() -> { final RecordStoreConnectionForm form = new RecordStoreConnectionForm(registry, name); form.showDialog(); }); final RecordStoreConnection connection = registry.getConnection(name); if (connection == null) { return null; } else { return connection.getRecordStore(); } }); } public static void addSaveActions(final JComponent component, final Project project) { final InputMap inputMap = component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK), SAVE_PROJECT_KEY); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.META_DOWN_MASK), SAVE_PROJECT_KEY); inputMap.put( KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK), SAVE_CHANGES_KEY); inputMap.put( KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.META_DOWN_MASK | InputEvent.ALT_DOWN_MASK), SAVE_CHANGES_KEY); final ActionMap actionMap = component.getActionMap(); actionMap.put(SAVE_PROJECT_KEY, new RunnableAction(SAVE_PROJECT_KEY, project::saveAllSettings)); actionMap.put(SAVE_CHANGES_KEY, new RunnableAction(SAVE_CHANGES_KEY, project::saveChanges)); } public static ProjectFrame get(final Layer layer) { if (layer == null) { return null; } else { final LayerGroup project = layer.getProject(); if (project == null) { return null; } else { return project.getProperty(PROJECT_FRAME); } } } public static void init() { } private Set<String> bottomTabLayerPaths = new LinkedHashSet<>(); private DnDTabbedPane bottomTabs = new DnDTabbedPane(); private BaseTree catalogTree; private boolean exitOnClose = true; private final String frameTitle; private JSplitPane leftRightSplit; private TabbedPane leftTabs = new TabbedPane(); private MapPanel mapPanel; private final MenuFactory openRecentMenu = new MenuFactory("Open Recent Project"); private Project project = new Project(); private BaseTree tocTree; private JSplitPane topBottomSplit; private Path projectPath; public ProjectFrame(final String title, final Path projectPath) { this(title, projectPath, true); } public ProjectFrame(final String title, final Path projectPath, final boolean initialize) { super(title, false); this.frameTitle = title; this.projectPath = projectPath; if (initialize) { initUi(); loadProject(); } } private void actionNewProject() { if (this.project != null && this.project.saveWithPrompt()) { this.project.reset(); super.setTitle("NEW - " + this.frameTitle); } } private void actionOpenProject() { if (this.project != null && this.project.saveWithPrompt()) { final JFileChooser fileChooser = SwingUtil.newFileChooser("Open Project", "com.revolsys.swing.map.project", "directory"); final FileNameExtensionFilter filter = new FileNameExtensionFilter("Project (*.rgmap)", "rgmap"); fileChooser.setAcceptAllFileFilterUsed(true); fileChooser.addChoosableFileFilter(filter); fileChooser.setFileFilter(filter); if (!OS.isMac()) { fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); } final int returnVal = fileChooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { final File projectDirectory = fileChooser.getSelectedFile(); openProject(projectDirectory.toPath()); } } } private void actionRunScript() { final File logDirectory = getLogDirectory(); final JavaProcess javaProcess = newJavaProcess(); ScriptRunner.runScriptProcess(this, logDirectory, javaProcess); } public void actionSaveProjectAs() { final Path path = this.project.saveAllSettingsAs(); if (path != null) { addToRecentProjects(path); Invoke.later(() -> { final Project project = getProject(); setTitle(project.getName() + " - " + getFrameTitle()); }); } } public void addBottomTab(final ProjectFramePanel panel, final Map<String, Object> config) { Invoke.later(() -> { final TabbedPane tabs = getBottomTabs(); final Object tableView = panel.getProperty(BOTTOM_TAB); Component component = null; if (tableView instanceof Component) { component = (Component)tableView; if (component.getParent() != tabs) { component = null; } } if (component == null) { component = panel.newPanelComponent(config); if (component != null) { final Component panelComponent = component; panel.activatePanelComponent(panelComponent, config); final int tabIndex = tabs.getTabCount(); final String name = panel.getName(); final Icon icon = panel.getIcon(); panel.setPropertyWeak(BOTTOM_TAB, panelComponent); final PropertyChangeListener listener = EventQueue.addPropertyChange(panel, "name", () -> { final int index = tabs.indexOfComponent(panelComponent); if (index != -1) { final String newName = panel.getName(); tabs.setTitleAt(index, newName); } }); panel.setPropertyWeak(BOTTOM_TAB_LISTENER, listener); final String layerPath = panel.getPath(); final Runnable closeAction = () -> { removeBottomTab(panel); synchronized (this.bottomTabLayerPaths) { this.bottomTabLayerPaths.remove(layerPath); } }; synchronized (this.bottomTabLayerPaths) { this.bottomTabLayerPaths.add(layerPath); } final TabClosableTitle tab = tabs.addClosableTab(name, icon, panelComponent, closeAction); tab.setMenu(panel); tabs.setSelectedIndex(tabIndex); } } else { panel.activatePanelComponent(component, config); tabs.setSelectedComponent(component); } }); } protected void addMenu(final JMenuBar menuBar, final MenuFactory menuFactory) { if (menuFactory != null) { final JMenu menu = menuFactory.newComponent(); menuBar.add(menu, menuBar.getMenuCount() - 1); } } private void addToRecentProjects(final Path projectPath) { final List<String> recentProjects = getRecentProjectPaths(); final String filePath = projectPath.toAbsolutePath().toString(); recentProjects.remove(filePath); recentProjects.add(0, filePath); while (recentProjects.size() > 10) { recentProjects.remove(recentProjects.size() - 1); } OS.setPreference("com.revolsys.gis", "/com/revolsys/gis/project", "recentProjects", recentProjects); OS.setPreference("com.revolsys.gis", "/com/revolsys/gis/project", "recentProject", filePath); updateRecentMenu(); } @Override protected void close() { Property.removeAllListeners(this); setVisible(false); super.close(); setRootPane(new JRootPane()); removeAll(); setMenuBar(null); if (this.project != null) { this.project.setProperty(PROJECT_FRAME, null); Project.clearProject(this.project); } if (this.bottomTabs != null) { for (final ContainerListener listener : this.bottomTabs.getContainerListeners()) { this.bottomTabs.removeContainerListener(listener); } } if (this.catalogTree != null) { this.catalogTree.setRoot(null); } if (this.mapPanel != null) { this.mapPanel.destroy(); } if (this.project != null) { final RecordStoreConnectionRegistry recordStores = this.project.getRecordStores(); RecordStoreConnectionManager.get().removeConnectionRegistry(recordStores); if (Project.get() == this.project) { Project.set(null); } this.project.delete(); } if (this.tocTree != null) { this.tocTree.setRoot(null); } this.bottomTabs = null; this.catalogTree = null; this.leftRightSplit = null; this.leftTabs = null; this.mapPanel = null; this.project = null; this.tocTree = null; this.topBottomSplit = null; final ActionMap actionMap = getRootPane().getActionMap(); actionMap.put(SAVE_PROJECT_KEY, null); actionMap.put(SAVE_CHANGES_KEY, null); } public void exit() { final Project project = getProject(); if (project != null && project.saveWithPrompt()) { final Window[] windows = Window.getOwnerlessWindows(); for (final Window window : windows) { SwingUtil.dispose(window); } System.exit(0); } } public void expandLayers(final Layer layer) { if (layer != null) { Invoke.later(() -> { final LayerGroup group; if (layer instanceof LayerGroup) { group = (LayerGroup)layer; } else { group = layer.getLayerGroup(); } if (group != null) { final List<Layer> layerPath = group.getPathList(); this.tocTree.expandPath(layerPath); } }); } } public TabbedPane getBottomTabs() { return this.bottomTabs; } public double getControlWidth() { return 0.20; } protected BoundingBox getDefaultBoundingBox() { return BoundingBox.empty(); } public String getFrameTitle() { return this.frameTitle; } public TabbedPane getLeftTabs() { return this.leftTabs; } public File getLogDirectory() { return FileUtil.getDirectory("log"); } public MapPanel getMapPanel() { return this.mapPanel; } public Project getProject() { return this.project; } public Path getProjectPath() { return this.projectPath; } private List<String> getRecentProjectPaths() { final List<String> recentProjects = OS.getPreference("com.revolsys.gis", "/com/revolsys/gis/project", "recentProjects", new ArrayList<String>()); for (int i = 0; i < recentProjects.size();) { final String filePath = recentProjects.get(i); final File file = FileUtil.getFile(filePath); if (file.exists()) { i++; } else { recentProjects.remove(i); } } OS.setPreference("com.revolsys.gis", "/com/revolsys/gis/project", "recentProjects", recentProjects); return recentProjects; } public BaseTreeNode getTreeNode(final Layer layer) { final List<Layer> layerPath = layer.getPathList(); final TreePath treePath = this.tocTree.getTreePath(layerPath); if (treePath == null) { return null; } else { return (BaseTreeNode)treePath.getLastPathComponent(); } } // public void expandConnectionManagers(final PropertyChangeEvent event) { // final Object newValue = event.getNewValue(); // if (newValue instanceof ConnectionRegistry) { // final ConnectionRegistry<?> registry = (ConnectionRegistry<?>)newValue; // final ConnectionRegistryManager<?> connectionManager = // registry.getConnectionManager(); // if (connectionManager != null) { // final List<?> connectionRegistries = // connectionManager.getConnectionRegistries(); // if (connectionRegistries != null) { // final ObjectTree tree = catalogPanel.getTree(); // tree.expandPath(connectionRegistries, connectionManager, registry); // } // } // } // } @Override protected void initUi() { setMinimumSize(new Dimension(600, 500)); final JRootPane rootPane = getRootPane(); addSaveActions(rootPane, this.project); final BoundingBox defaultBoundingBox = getDefaultBoundingBox(); this.project.setViewBoundingBoxAndGeometryFactory(defaultBoundingBox); Project.set(this.project); this.project.setPropertyWeak(PROJECT_FRAME, this); newMapPanel(); this.leftTabs.setMinimumSize(new Dimension(100, 300)); this.leftTabs.setPreferredSize(new Dimension(300, 700)); this.mapPanel.setMinimumSize(new Dimension(300, 300)); this.mapPanel.setPreferredSize(new Dimension(700, 700)); this.leftRightSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, this.leftTabs, this.mapPanel); this.leftRightSplit.setBorder(BorderFactory.createEmptyBorder()); this.bottomTabs.setBorder(BorderFactory.createEmptyBorder()); this.bottomTabs.setPreferredSize(new Dimension(700, 200)); final ContainerListener listener = new ContainerAdapter() { @Override public void componentRemoved(final ContainerEvent e) { final Component eventComponent = e.getChild(); if (eventComponent instanceof ProjectFramePanel) { final ProjectFramePanel panel = (ProjectFramePanel)eventComponent; panel.setProperty(BOTTOM_TAB, null); } } }; this.bottomTabs.addContainerListener(listener); this.topBottomSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, this.leftRightSplit, this.bottomTabs); this.bottomTabs.setMinimumSize(new Dimension(600, 100)); this.topBottomSplit.setResizeWeight(1); add(this.topBottomSplit, BorderLayout.CENTER); newTabLeftTableOfContents(); newTabLeftCatalogPanel(); newTabBottomTasksPanel(); Log4jTableModel.addNewTabPane(this.bottomTabs); setBounds((Object)null, false); super.initUi(); } protected final void loadProject() { final Path projectPath = getProjectPath(); if (projectPath == null) { getMapPanel().setInitializing(false); } else { Invoke.background("Load Project: " + projectPath, () -> { loadProject(projectPath); getMapPanel().setInitializing(false); loadProjectAfter(); }); } } protected void loadProject(final Path projectPath) { final PathResource resource = new PathResource(projectPath); this.project.readProject(resource); Invoke.later(() -> setTitle(this.project.getName() + " - " + this.frameTitle)); final Object frameBoundsObject = this.project.getProperty("frameBounds"); setBounds(frameBoundsObject, true); setVisible(true); final RecordStoreConnectionManager recordStoreConnectionManager = RecordStoreConnectionManager .get(); recordStoreConnectionManager.removeConnectionRegistry("Project"); final RecordStoreConnectionRegistry recordStores = this.project.getRecordStores(); recordStoreConnectionManager.addConnectionRegistry(recordStores); final FileConnectionManager fileConnectionManager = FileConnectionManager.get(); fileConnectionManager.removeConnectionRegistry("Project"); final FolderConnectionRegistry folderConnections = this.project.getFolderConnections(); fileConnectionManager.addConnectionRegistry(folderConnections); final WebServiceConnectionManager webServiceConnectionManager = WebServiceConnectionManager .get(); webServiceConnectionManager.removeConnectionRegistry("Project"); final WebServiceConnectionRegistry webServices = this.project.getWebServices(); webServiceConnectionManager.addConnectionRegistry(webServices); final MapPanel mapPanel = getMapPanel(); final BoundingBox initialBoundingBox = this.project.getInitialBoundingBox(); final Viewport2D viewport = mapPanel.getViewport(); if (!BoundingBoxUtil.isEmpty(initialBoundingBox)) { this.project.setViewBoundingBoxAndGeometryFactory(initialBoundingBox); viewport.setBoundingBoxAndGeometryFactory(initialBoundingBox); } viewport.setInitialized(true); } protected void loadProjectAfter() { this.bottomTabLayerPaths = Sets .newLinkedHash(this.project.<Collection<String>> getProperty("bottomTabLayerPaths")); this.project.setProperty("bottomTabLayerPaths", this.bottomTabLayerPaths); for (final String layerPath : this.bottomTabLayerPaths) { final Layer layer = this.project.getLayerByPath(layerPath); if (layer != null) { Invoke.later(layer::showTableView); } } } public JavaProcess newJavaProcess() { return new JavaProcess(); } protected MapPanel newMapPanel() { this.mapPanel = new MapPanel(this.project); if (OS.isMac()) { // Make border on right/bottom to match the JTabbedPane UI on a mac this.mapPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 9, 9)); } return this.mapPanel; } @Override protected JMenuBar newMenuBar() { final JMenuBar menuBar = super.newMenuBar(); addMenu(menuBar, newMenuFile()); final MenuFactory tools = newMenuTools(); if (OS.isWindows()) { tools.addMenuItem("options", "Options...", "Options...", (String)null, PreferencesDialog.get()::showPanel); } addMenu(menuBar, tools); return menuBar; } protected MenuFactory newMenuFile() { final MenuFactory file = new MenuFactory("File"); file.addMenuItemTitleIcon("projectOpen", "New Project", "layout_add", this::actionNewProject) .setAcceleratorControlKey(KeyEvent.VK_N); file .addMenuItemTitleIcon("projectOpen", "Open Project...", "layout_add", this::actionOpenProject) .setAcceleratorControlKey(KeyEvent.VK_O); file.addComponentFactory("projectOpen", this.openRecentMenu); updateRecentMenu(); file.addMenuItemTitleIcon("projectSave", "Save Project", "layout_save", this.project::saveAllSettings).setAcceleratorControlKey(KeyEvent.VK_S); file.addMenuItemTitleIcon("projectSave", "Save Project As...", "layout_save", this::actionSaveProjectAs).setAcceleratorShiftControlKey(KeyEvent.VK_S); file.addMenuItemTitleIcon("save", "Save as PDF", "save_pdf", SaveAsPdf::save); file.addMenuItemTitleIcon("print", "Print", "printer", SinglePage::print) .setAcceleratorControlKey(KeyEvent.VK_P); if (OS.isWindows()) { file.addMenuItemTitleIcon("exit", "Exit", null, this::exit) .setAcceleratorKey(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_MASK)); } else if (OS.isUnix()) { file.addMenuItemTitleIcon("exit", "Exit", null, this::exit) .setAcceleratorKey(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK)); } return file; } protected MenuFactory newMenuTools() { final MenuFactory tools = new MenuFactory("Tools"); final MapPanel map = getMapPanel(); final MeasureOverlay measureOverlay = map.getMapOverlay(MeasureOverlay.class); tools.addCheckboxMenuItem("map", new RunnableAction("Measure Length", Icons.getIcon("ruler_line"), () -> measureOverlay.toggleMeasureMode(DataTypes.LINE_STRING)), new ObjectPropertyEnableCheck(measureOverlay, "measureDataType", DataTypes.LINE_STRING)); tools.addCheckboxMenuItem("map", new RunnableAction("Measure Area", Icons.getIcon("ruler_polygon"), () -> measureOverlay.toggleMeasureMode(DataTypes.POLYGON)), new ObjectPropertyEnableCheck(measureOverlay, "measureDataType", DataTypes.POLYGON)); tools.addMenuItem("script", "Run Script...", "script_go", this::actionRunScript); return tools; } protected void newTabBottomTasksPanel() { final int tabIndex = SwingWorkerTableModel.addNewTabPanel(this.bottomTabs); final SwingWorkerProgressBar progressBar = this.mapPanel.getProgressBar(); final JButton viewTasksAction = RunnableAction.newButton(null, "View Running Tasks", Icons.getIcon("time_go"), () -> this.bottomTabs.setSelectedIndex(tabIndex)); viewTasksAction.setBorderPainted(false); viewTasksAction.setBorder(null); progressBar.add(viewTasksAction, BorderLayout.EAST); } protected void newTabLeftCatalogPanel() { final BaseTreeNode recordStores = RecordStoreConnectionTrees .newRecordStoreConnectionsTreeNode(); final BaseTreeNode fileSystems = PathTreeNode.newFileSystemsTreeNode(); final BaseTreeNode folderConnections = FolderConnectionsTrees.newFolderConnectionsTreeNode(); final BaseTreeNode webServices = WebServiceConnectionTrees.newWebServiceConnectionsTreeNode(); final ListTreeNode root = new ListTreeNode("/", recordStores, fileSystems, folderConnections, webServices); final BaseTree tree = new BaseTree(root); tree.setRootVisible(false); recordStores.expandChildren(); fileSystems.expand(); folderConnections.expandChildren(); webServices.expandChildren(); this.catalogTree = tree; final Icon icon = Icons.getIconWithBadge("folder", "tree"); final TabbedPane tabs = this.leftTabs; final Component component = this.catalogTree; tabs.addTab(icon, "Catalog", component, true); } protected void newTabLeftTableOfContents() { final Project project = getProject(); this.tocTree = ProjectTreeNode.newTree(project); this.leftTabs.addTabIcon("tree_layers", "TOC", this.tocTree, true); } public void openProject(final Path projectPath) { if (Files.exists(projectPath)) { this.projectPath = projectPath; try { addToRecentProjects(projectPath); PreferencesUtil.setUserString("com.revolsys.swing.map.project", "directory", projectPath.getParent().toString()); this.project.reset(); final Runnable task = this::loadProject; Invoke.background("Load project", task); } catch (final Throwable e) { Logs.error(this, "Unable to open project:" + projectPath, e); } } } public void removeBottomTab(final ProjectFramePanel panel) { final JTabbedPane tabs = getBottomTabs(); final PropertyChangeListener listener = panel.getProperty(BOTTOM_TAB_LISTENER); if (listener != null) { Property.removeListener(panel, listener); } final Component component = panel.getProperty(BOTTOM_TAB); if (component != null) { if (tabs != null) { tabs.remove(component); } panel.deletePanelComponent(component); } panel.setProperty(BOTTOM_TAB, null); panel.setProperty(BOTTOM_TAB_LISTENER, null); } public void setBounds(final Object frameBoundsObject, final boolean visible) { Invoke.later(() -> { boolean sizeSet = false; if (frameBoundsObject instanceof List) { try { @SuppressWarnings("unchecked") final List<Number> frameBoundsList = (List<Number>)frameBoundsObject; if (frameBoundsList.size() == 4) { int x = frameBoundsList.get(0).intValue(); int y = frameBoundsList.get(1).intValue(); int width = frameBoundsList.get(2).intValue(); int height = frameBoundsList.get(3).intValue(); final Rectangle screenBounds = SwingUtil.getScreenBounds(x, y); width = Math.min(width, screenBounds.width); height = Math.min(height, screenBounds.height); setSize(width, height); if (x < screenBounds.x || x > screenBounds.x + screenBounds.width) { x = 0; } else { x = Math.min(x, screenBounds.x + screenBounds.width - width); } if (y < screenBounds.y || x > screenBounds.y + screenBounds.height) { y = 0; } else { y = Math.min(y, screenBounds.y + screenBounds.height - height); } setLocation(x, y); sizeSet = true; } } catch (final Throwable t) { } } if (!sizeSet) { final Rectangle screenBounds = SwingUtil.getScreenBounds(); setLocation(screenBounds.x + 10, screenBounds.y + 10); setSize(screenBounds.width - 20, screenBounds.height - 20); } final int leftRightDividerLocation = (int)(getWidth() * 0.2); this.leftRightSplit.setDividerLocation(leftRightDividerLocation); final int topBottomDividerLocation = (int)(getHeight() * 0.75); this.topBottomSplit.setDividerLocation(topBottomDividerLocation); if (visible) { setVisible(true); } }); } public void setExitOnClose(final boolean exitOnClose) { this.exitOnClose = exitOnClose; } protected void setProjectPath(final Path projectPath) { this.projectPath = projectPath; } public void updateRecentMenu() { final List<String> recentProjects = getRecentProjectPaths(); this.openRecentMenu.clear(); for (final String filePath : recentProjects) { final Path file = Paths.getPath(filePath); final String fileName = Paths.getFileName(file); final String path = file.getParent().toString(); this.openRecentMenu.addMenuItem("default", fileName + " - " + path, "layout_add", () -> openProject(file)); } } @Override public void windowClosing(final WindowEvent e) { if (this.exitOnClose) { exit(); } else { dispose(); } } }