package org.geogebra.desktop.gui; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.Font; import java.awt.Point; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DropTarget; import java.awt.event.ActionEvent; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import java.util.StringTokenizer; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.ImageIcon; import javax.swing.JApplet; import javax.swing.JColorChooser; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JMenuBar; import javax.swing.JOptionPane; import javax.swing.ListCellRenderer; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileFilter; import javax.swing.text.JTextComponent; import org.geogebra.common.GeoGebraConstants; import org.geogebra.common.awt.GColor; import org.geogebra.common.awt.GPoint; import org.geogebra.common.euclidian.EuclidianConstants; import org.geogebra.common.euclidian.EuclidianView; import org.geogebra.common.euclidian.EuclidianViewInterfaceCommon; import org.geogebra.common.euclidian.event.AbstractEvent; import org.geogebra.common.euclidian3D.EuclidianView3DInterface; import org.geogebra.common.export.pstricks.GeoGebraToPstricks; import org.geogebra.common.gui.GuiManager; import org.geogebra.common.gui.Layout; import org.geogebra.common.gui.SetLabels; import org.geogebra.common.gui.VirtualKeyboardListener; import org.geogebra.common.gui.toolbar.ToolBar; import org.geogebra.common.gui.view.consprotocol.ConstructionProtocolNavigation; import org.geogebra.common.gui.view.consprotocol.ConstructionProtocolView; import org.geogebra.common.jre.util.Base64; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.ModeSetter; import org.geogebra.common.kernel.View; import org.geogebra.common.kernel.commands.AlgebraProcessor; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoImage; import org.geogebra.common.kernel.geos.GeoPoint; import org.geogebra.common.main.App; import org.geogebra.common.main.DialogManager; import org.geogebra.common.main.Localization; import org.geogebra.common.main.MyError; import org.geogebra.common.main.settings.KeyboardSettings; import org.geogebra.common.plugin.Event; import org.geogebra.common.plugin.EventType; import org.geogebra.common.util.AsyncOperation; import org.geogebra.common.util.FileExtensions; import org.geogebra.common.util.StringUtil; import org.geogebra.common.util.Util; import org.geogebra.common.util.debug.Log; import org.geogebra.common.util.lang.Unicode; import org.geogebra.desktop.CommandLineArguments; import org.geogebra.desktop.awt.GColorD; import org.geogebra.desktop.cas.view.CASViewD; import org.geogebra.desktop.euclidian.EuclidianControllerD; import org.geogebra.desktop.euclidian.EuclidianViewD; import org.geogebra.desktop.euclidian.event.MouseEventND; import org.geogebra.desktop.euclidianND.EuclidianViewInterfaceD; import org.geogebra.desktop.export.GraphicExportDialog; import org.geogebra.desktop.export.WorksheetExportDialog; import org.geogebra.desktop.export.pstricks.GeoGebraToPstricksD; import org.geogebra.desktop.export.pstricks.PstricksFrame; import org.geogebra.desktop.gui.app.GeoGebraFrame; import org.geogebra.desktop.gui.app.MyFileFilter; import org.geogebra.desktop.gui.color.GeoGebraColorChooser; import org.geogebra.desktop.gui.dialog.DialogManagerD; import org.geogebra.desktop.gui.dialog.InputDialogD; import org.geogebra.desktop.gui.dialog.InputDialogOpenURL; import org.geogebra.desktop.gui.dialog.ToolCreationDialogD; import org.geogebra.desktop.gui.inputbar.AlgebraInputD; import org.geogebra.desktop.gui.inputbar.InputBarHelpPanelD; import org.geogebra.desktop.gui.layout.DockPanelD; import org.geogebra.desktop.gui.layout.LayoutD; import org.geogebra.desktop.gui.layout.panels.AlgebraDockPanel; import org.geogebra.desktop.gui.layout.panels.CasDockPanel; import org.geogebra.desktop.gui.layout.panels.ConstructionProtocolDockPanel; import org.geogebra.desktop.gui.layout.panels.DataAnalysisViewDockPanel; import org.geogebra.desktop.gui.layout.panels.Euclidian2DockPanel; import org.geogebra.desktop.gui.layout.panels.EuclidianDockPanel; import org.geogebra.desktop.gui.layout.panels.EuclidianDockPanelAbstract; import org.geogebra.desktop.gui.layout.panels.ProbabilityCalculatorDockPanel; import org.geogebra.desktop.gui.layout.panels.PropertiesDockPanel; import org.geogebra.desktop.gui.layout.panels.SpreadsheetDockPanel; import org.geogebra.desktop.gui.menubar.GeoGebraMenuBar; import org.geogebra.desktop.gui.nssavepanel.NSSavePanel; import org.geogebra.desktop.gui.toolbar.ToolbarContainer; import org.geogebra.desktop.gui.toolbar.ToolbarD; import org.geogebra.desktop.gui.util.BrowserLauncher; import org.geogebra.desktop.gui.util.GeoGebraFileChooser; import org.geogebra.desktop.gui.view.CompressedAlgebraView; import org.geogebra.desktop.gui.view.algebra.AlgebraControllerD; import org.geogebra.desktop.gui.view.algebra.AlgebraViewD; import org.geogebra.desktop.gui.view.consprotocol.ConstructionProtocolNavigationD; import org.geogebra.desktop.gui.view.consprotocol.ConstructionProtocolViewD; import org.geogebra.desktop.gui.view.consprotocol.ConstructionProtocolViewD.ConstructionTableDataD; import org.geogebra.desktop.gui.view.data.DataAnalysisViewD; import org.geogebra.desktop.gui.view.probcalculator.ProbabilityCalculatorViewD; import org.geogebra.desktop.gui.view.properties.PropertiesViewD; import org.geogebra.desktop.gui.view.spreadsheet.SpreadsheetViewD; import org.geogebra.desktop.gui.virtualkeyboard.VirtualKeyboardD; import org.geogebra.desktop.gui.virtualkeyboard.WindowsUnicodeKeyboard; import org.geogebra.desktop.main.AppD; import org.geogebra.desktop.main.DialogManagerMinimal; import org.geogebra.desktop.main.GeoGebraPreferencesD; import org.geogebra.desktop.main.GuiManagerInterfaceD; import org.geogebra.desktop.main.LocalizationD; import org.geogebra.desktop.util.GuiResourcesD; import org.geogebra.desktop.util.UtilD; /** * Handles all geogebra.gui package related objects and methods for Application. * This is done to be able to put class files of geogebra.gui.* packages into a * separate gui jar file. */ @SuppressWarnings("javadoc") public class GuiManagerD extends GuiManager implements GuiManagerInterfaceD { private final static boolean USE_COMPRESSED_VIEW = true; private final static int CV_UPDATES_PER_SECOND = 3; protected DialogManagerD dialogManager; protected DialogManagerD.Factory dialogManagerFactory; private AlgebraInputD algebraInput; private AlgebraControllerD algebraController; private AlgebraViewD algebraView; private CASViewD casView; private SpreadsheetViewD spreadsheetView; private ArrayList<EuclidianViewD> euclidianView2 = new ArrayList<EuclidianViewD>(); private ConstructionProtocolViewD constructionProtocolView; private GeoGebraMenuBar menuBar; private String strCustomToolbarDefinition; private ToolbarContainer toolbarPanel; private LayoutD layout; private DataAnalysisViewD dataView; private String lastFilenameOfSaveDialog; /** * Returns last filename that was used in save dialog (may be for .png, * .ggb, ...) See #665 * * @return last filename including extension */ public String getLastFileNameOfSaveDialog() { return lastFilenameOfSaveDialog; } private static DataFlavor getFlavor(String desc) { try { return new DataFlavor(desc); } catch (ClassNotFoundException cnfe) { cnfe.printStackTrace(); } return null; } public static final DataFlavor urlFlavor = getFlavor( "application/x-java-url; class=java.net.URL"); public static final DataFlavor uriListFlavor = getFlavor( "text/uri-list; class=java.lang.String"); // Actions private AbstractAction showAxesAction, showGridAction, undoAction, redoAction; private LocalizationD loc; public GuiManagerD(AppD app) { super(app); this.loc = app.getLocalization(); lastFilenameOfSaveDialog = null; dialogManagerFactory = new DialogManagerD.Factory(); } /** * Initialize the GUI manager. */ @Override public void initialize() { initAlgebraController(); // needed for keyboard input in EuclidianView // init layout related stuff layout.initialize((AppD) app); initLayoutPanels(); // init dialog manager dialogManager = dialogManagerFactory.create((AppD) app); } /** * Performs a couple of actions required if the user is switching between * frame and applet: - Make the title bar visible if the user is using an * applet. - Active the glass pane if the application is changing from * applet to frame mode. */ public void updateLayout() { // update the glass pane (add it for frame, remove it for applet) layout.getDockManager().updateGlassPane(); // we now need to make sure that the relative dimensions of views // are kept, therefore we update the dividers Dimension oldCenterSize = ((AppD) app).getCenterPanel().getSize(); Dimension newCenterSize; // frame -> applet if (app.isApplet()) { newCenterSize = ((AppD) app).getApplet().getJApplet().getSize(); } // applet -> frame else { // TODO redo this, guessing dimensions is bad if (((AppD) app).getFrame().getPreferredSize().width <= 0) { newCenterSize = new Dimension(700, 500); } else { newCenterSize = ((AppD) app).getFrame().getPreferredSize(); newCenterSize.width -= 10; newCenterSize.height -= 100; } } layout.getDockManager().scale( newCenterSize.width / (float) oldCenterSize.width, newCenterSize.height / (float) oldCenterSize.height); } /** * Register panels for the layout manager. */ protected void initLayoutPanels() { // register euclidian view layout.registerPanel(newEuclidianDockPanel()); // register spreadsheet view layout.registerPanel(new SpreadsheetDockPanel((AppD) app)); // register algebra view layout.registerPanel(new AlgebraDockPanel((AppD) app)); // register CAS view if (app.supportsView(App.VIEW_CAS)) { layout.registerPanel(new CasDockPanel((AppD) app)); } // register EuclidianView2 layout.registerPanel(newEuclidian2DockPanel(1)); // register ConstructionProtocol view layout.registerPanel(new ConstructionProtocolDockPanel((AppD) app)); // register ProbabilityCalculator view layout.registerPanel(new ProbabilityCalculatorDockPanel((AppD) app)); // register Properties view propertiesDockPanel = new PropertiesDockPanel((AppD) app); layout.registerPanel(propertiesDockPanel); // register data analysis view layout.registerPanel(new DataAnalysisViewDockPanel((AppD) app)); /* * if (!app.isWebstart() || app.is3D()) { // register Assignment view * layout.registerPanel(new AssignmentDockPanel(app)); } */ } private PropertiesDockPanel propertiesDockPanel = null; /** * * @return the properties dock panel */ public PropertiesDockPanel getPropertiesDockPanel() { return propertiesDockPanel; } /** * @return new euclidian view */ protected EuclidianDockPanel newEuclidianDockPanel() { return new EuclidianDockPanel((AppD) app, null); } protected Euclidian2DockPanel newEuclidian2DockPanel(int idx) { return new Euclidian2DockPanel((AppD) app, null, idx); } @Override public boolean isInputFieldSelectionListener() { return app.getCurrentSelectionListener() == algebraInput.getTextField(); } public void clearPreferences() { if ((app).isSaved() || ((AppD) app).saveCurrentFile()) { app.setWaitCursor(); GeoGebraPreferencesD.getPref().clearPreferences(app); // clear custom toolbar definition strCustomToolbarDefinition = null; GeoGebraPreferencesD.getPref().loadXMLPreferences((AppD) app); // this // will // load the // default // settings ((AppD) app) .setLanguage(((AppD) app).getMainComponent().getLocale()); ((AppD) app).updateContentPaneAndSize(); app.setDefaultCursor(); app.setUndoActive(true); } } @Override public synchronized CASViewD getCasView() { if (casView == null) { casView = new CASViewD((AppD) app); } return casView; } @Override public boolean hasCasView() { return casView != null; } @Override public AlgebraViewD getAlgebraView() { if (algebraView == null) { initAlgebraController(); algebraView = newAlgebraView(algebraController); if (!app.isApplet()) { // allow drag & drop of files on algebraView algebraView.setDropTarget(new DropTarget(algebraView, new FileDropTargetListener((AppD) app))); } } return algebraView; } @Override public void applyAlgebraViewSettings() { if (algebraView != null) { algebraView.applySettings(); } } private PropertiesViewD propertiesView; @Override public View getPropertiesView() { if (propertiesView == null) { // initPropertiesDialog(); propertiesView = newPropertiesViewD((AppD) app); } return propertiesView; } /** * @param appD * Application * @return new PropertiesViewD */ protected PropertiesViewD newPropertiesViewD(AppD appD) { return new PropertiesViewD(appD); } @Override public boolean hasPropertiesView() { return propertiesView != null; } /** * * @param algc * @return new algebra view */ protected AlgebraViewD newAlgebraView(AlgebraControllerD algc) { if (USE_COMPRESSED_VIEW) { return new CompressedAlgebraView(algc, CV_UPDATES_PER_SECOND); } return new AlgebraViewD(algc); } @Override public ConstructionProtocolView getConstructionProtocolView() { if (constructionProtocolView == null) { constructionProtocolView = new ConstructionProtocolViewD( (AppD) app); } return constructionProtocolView; } @Override public void startEditing(GeoElement geo) { getAlgebraView().startEditItem(geo); } @Override public void setScrollToShow(boolean scrollToShow) { if (spreadsheetView != null) { spreadsheetView.setScrollToShow(scrollToShow); } } @Override public void resetSpreadsheet() { if (spreadsheetView != null) { spreadsheetView.restart(); } } @Override public boolean hasSpreadsheetView() { if (spreadsheetView == null) { return false; } if (!spreadsheetView.isShowing()) { return false; } return true; } @Override public boolean hasAlgebraViewShowing() { if (algebraView == null) { return false; } if (!algebraView.isShowing()) { return false; } return true; } @Override public boolean hasAlgebraView() { if (algebraView == null) { return false; } return true; } @Override public boolean hasProbabilityCalculator() { if (probCalculator == null) { return false; } if (!probCalculator.isShowing()) { return false; } return true; } @Override public ProbabilityCalculatorViewD getProbabilityCalculator() { if (probCalculator == null) { setProbCalculator(new ProbabilityCalculatorViewD((AppD) app)); } return (ProbabilityCalculatorViewD) probCalculator; } @Override public boolean hasDataAnalysisView() { if (dataView == null) { return false; } if (!dataView.isShowing()) { return false; } return true; } @Override public DataAnalysisViewD getDataAnalysisView() { if (dataView == null) { dataView = new DataAnalysisViewD((AppD) app, app.getSettings().getDataAnalysis().getMode()); } return dataView; } @Override public SpreadsheetViewD getSpreadsheetView() { // init spreadsheet view if (spreadsheetView == null) { spreadsheetView = new SpreadsheetViewD((AppD) app); } return spreadsheetView; } @Override public void updateSpreadsheetColumnWidths() { if (spreadsheetView != null) { spreadsheetView.updateColumnWidths(); } } // XML // ===================================================== @Override public void getSpreadsheetViewXML(StringBuilder sb, boolean asPreference) { app.getSettings().getSpreadsheet().getXML(sb, asPreference); } @Override public void getAlgebraViewXML(StringBuilder sb, boolean asPreference) { if (algebraView != null) { algebraView.getXML(sb, asPreference); } } // public void getAlgebraViewXML(StringBuilder sb) { // if (algebraView != null) // algebraView.getXML(sb); // } // ================================== // End XML @Override public EuclidianViewD getEuclidianView2(int idx) { for (int i = euclidianView2.size(); i <= idx; i++) { euclidianView2.add(null); } if (euclidianView2.get(idx) == null) { boolean[] showAxis = { true, true }; boolean showGrid = false; Log.debug("Creating 2nd Euclidian View"); EuclidianViewD ev = newEuclidianView(showAxis, showGrid, 2); // euclidianView2.setEuclidianViewNo(2); ev.updateFonts(); euclidianView2.set(idx, ev); } return euclidianView2.get(idx); } protected EuclidianViewD newEuclidianView(boolean[] showAxis, boolean showGrid, int id) { return new EuclidianViewD(new EuclidianControllerD(kernel), showAxis, showGrid, id, app.getSettings().getEuclidian(id)); } @Override public boolean hasEuclidianView2(int idx) { if (euclidianView2.size() <= idx || euclidianView2.get(idx) == null) { return false; } if (!euclidianView2.get(idx).isShowing()) { return false; } return true; } @Override public boolean hasEuclidianView2EitherShowingOrNot(int idx) { if (euclidianView2.size() <= idx || euclidianView2.get(idx) == null) { return false; } return true; } /** * @todo Do not just use the default euclidian view if no EV has focus, but * determine if maybe just one EV is visible etc. * * @return The euclidian view to which new geo elements should be added by * default (if the user uses this mode). This is the focused * euclidian view or the first euclidian view at the moment. */ @Override public EuclidianView getActiveEuclidianView() { if (layout != null && layout.getDockManager() != null) { EuclidianDockPanelAbstract focusedEuclidianPanel = layout .getDockManager().getFocusedEuclidianPanel(); if (focusedEuclidianPanel != null) { return focusedEuclidianPanel.getEuclidianView(); } } return app.getEuclidianView1(); } @Override public void attachSpreadsheetView() { getSpreadsheetView(); spreadsheetView.attachView(); } @Override public void detachSpreadsheetView() { if (spreadsheetView != null) { spreadsheetView.detachView(); } } @Override public void attachAlgebraView() { getAlgebraView(); algebraView.attachView(); } @Override public void detachAlgebraView() { if (algebraView != null) { algebraView.detachView(); } } @Override public void attachCasView() { getCasView(); casView.attachView(); } @Override public void detachCasView() { if (casView != null) { casView.detachView(); } } @Override public void attachConstructionProtocolView() { getConstructionProtocolView(); constructionProtocolView.getData().attachView(); } @Override public void detachConstructionProtocolView() { if (constructionProtocolView != null) { ((ConstructionTableDataD) (constructionProtocolView.getData())) .detachView(); } } @Override public void attachProbabilityCalculatorView() { getProbabilityCalculator(); probCalculator.attachView(); } @Override public void detachProbabilityCalculatorView() { getProbabilityCalculator(); probCalculator.detachView(); } @Override public void attachDataAnalysisView() { getDataAnalysisView().attachView(); } @Override public void detachDataAnalysisView() { getDataAnalysisView().detachView(); } @Override public void attachPropertiesView() { getPropertiesView(); propertiesView.attachView(); } @Override public void detachPropertiesView() { if (propertiesView != null) { propertiesView.detachView(); } } @Override public void setShowAuxiliaryObjects(boolean flag) { if (!hasAlgebraViewShowing()) { return; } getAlgebraView(); algebraView.setShowAuxiliaryObjects(flag); app.getSettings().getAlgebra().setShowAuxiliaryObjects(flag); } private void initAlgebraController() { if (algebraController == null) { algebraController = new AlgebraControllerD(app.getKernel()); } } public JComponent getAlgebraInput() { if (algebraInput == null) { algebraInput = new AlgebraInputD((AppD) app); } return algebraInput; } /** * use Application.getDialogManager() instead */ @Override @Deprecated public DialogManager getDialogManager() { return dialogManager; } @Override public void setLayout(Layout layout) { this.layout = (LayoutD) layout; } @Override public LayoutD getLayout() { return layout; } public Container getToolbarPanelContainer() { return getToolbarPanel(); } public ToolbarContainer getToolbarPanel() { if (toolbarPanel == null) { toolbarPanel = new ToolbarContainer((AppD) app, true); } return toolbarPanel; } @Override public void updateToolbar() { if (toolbarPanel != null) { toolbarPanel.buildGui(); // toolbarPanel.updateToolbarPanel(); toolbarPanel.updateHelpText(); } if (layout != null) { layout.getDockManager().updateToolbars(); } } @Override public void setShowView(boolean flag, int viewId) { setShowView(flag, viewId, true); } @Override public void setShowView(boolean flag, int viewId, boolean isPermanent) { if (flag) { if (!showView(viewId)) { layout.getDockManager().show(viewId); } if (viewId == App.VIEW_SPREADSHEET) { getSpreadsheetView().requestFocus(); } } else { if (showView(viewId)) { layout.getDockManager().hide(viewId, isPermanent); } if (viewId == App.VIEW_SPREADSHEET) { (app).getActiveEuclidianView().requestFocus(); } } toolbarPanel.validate(); toolbarPanel.updateHelpText(); app.dispatchEvent(new Event(EventType.PERSPECTIVE_CHANGE, null)); } @Override public boolean showView(int viewId) { try { if (layout.getDockManager().getPanel(viewId) == null) { return false; } return layout.getDockManager().getPanel(viewId).isVisible(); } catch (RuntimeException e) { e.printStackTrace(); return false; } } @Override public void setShowToolBarHelp(boolean flag) { ToolbarContainer.setShowHelp(flag); } public boolean isConsProtNavigationPlayButtonVisible() { return getConstructionProtocolNavigation().isPlayButtonVisible(); } public boolean isConsProtNavigationProtButtonVisible() { return getConstructionProtocolNavigation().isConsProtButtonVisible(); } /** * Displays the construction protocol dialog */ public void showConstructionProtocol() { app.getActiveEuclidianView().resetMode(); getConstructionProtocolView(); constructionProtocolView.setVisible(true); } /** * Displays the construction protocol dialog */ /* * public void hideConstructionProtocol() { if (constructionProtocolView == * null) return; app.getEuclidianView().resetMode(); * constructionProtocolView.setVisible(false); } */ /** * returns whether the construction protocol is visible */ /* * public boolean isConstructionProtocolVisible() { if * (constructionProtocolView == null) return false; return * constructionProtocolView.isVisible(); } */ /* * public JPanel getConstructionProtocol() { if (constProtocol == null) { * constProtocol = new ConstructionProtocolView(app); } return * constProtocol; } */ public void setConstructionStep(int step) { if (constructionProtocolView != null) { constructionProtocolView.setConstructionStep(step); } } @Override public void updateConstructionProtocol() { if (constructionProtocolView != null) { constructionProtocolView.update(); } } @Override public boolean isUsingConstructionProtocol() { return constructionProtocolView != null; } public int getToolBarHeight() { if ((app).showToolBar() && toolbarPanel != null) { return toolbarPanel.getHeight(); } return 0; } public String getDefaultToolbarString() { if (toolbarPanel == null) { return ""; } return getGeneralToolbar().getDefaultToolbarString(); } @Override public void updateFonts() { if (algebraView != null) { algebraView.updateFonts(); } if (spreadsheetView != null) { spreadsheetView.updateFonts(); } if (algebraInput != null) { algebraInput.updateFonts(); } if (toolbarPanel != null) { toolbarPanel.buildGui(); } if (menuBar != null) { menuBar.updateFonts(); } if (constructionProtocolView != null) { constructionProtocolView.initGUI(); } if (getConstructionProtocolNavigationIfExists() != null) { ((ConstructionProtocolNavigationD) getConstructionProtocolNavigation()) .initGUI(); } if (casView != null) { casView.updateFonts(); } if (layout.getDockManager() != null) { layout.getDockManager().updateFonts(); } if (probCalculator != null) { ((ProbabilityCalculatorViewD) probCalculator).updateFonts(); } if (dataView != null) { dataView.updateFonts(); } if (propertiesView != null) { propertiesView.updateFonts(); } dialogManager.updateFonts(); SwingUtilities.updateComponentTreeUI(((AppD) app).getMainComponent()); } @Override public void setLabels() { // reinit actions to update labels showAxesAction = null; initActions(); if ((app).showMenuBar()) { initMenubar(); // updateMenubar(); Component comp = ((AppD) app).getMainComponent(); if (comp instanceof JApplet) { ((JApplet) comp).setJMenuBar(menuBar); } else if (comp instanceof JFrame) { ((JFrame) comp).setJMenuBar(menuBar); } } if (inputHelpPanel != null) { inputHelpPanel.setLabels(); } // update views if (algebraView != null) { algebraView.setLabels(); } if (algebraInput != null) { algebraInput.setLabels(); } if (toolbarPanel != null) { toolbarPanel.buildGui(); toolbarPanel.updateHelpText(); } if (constructionProtocolView != null) { constructionProtocolView.initGUI(); } getConstructionProtocolNavigation().setLabels(); if (virtualKeyboard != null) { virtualKeyboard.setLabels(); } layout.getDockManager().setLabels(); dialogManager.setLabels(); if (((AppD) app).getDockBar() != null) { ((AppD) app).getDockBar().setLabels(); } } @Override public void initMenubar() { if (menuBar == null) { menuBar = new GeoGebraMenuBar((AppD) app, layout); } // ((GeoGebraMenuBar) menuBar).setFont(app.getPlainFont()); menuBar.initMenubar(); } @Override public void updateMenubar() { if (menuBar != null) { menuBar.updateMenubar(); } } @Override public void updateMenubarSelection() { if (menuBar != null) { menuBar.updateSelection(); } } @Override public void updateMenuWindow() { if (menuBar != null) { menuBar.updateMenuWindow(); } } @Override public void updateMenuFile() { if (menuBar != null) { menuBar.updateMenuFile(); } } @Override public JMenuBar getMenuBar() { return menuBar; } @Override public void updateMenuBarLayout() { if ((app).showMenuBar()) { Component comp = ((AppD) app).getMainComponent(); if (comp instanceof JApplet) { ((JApplet) comp).setJMenuBar(menuBar); } else if (comp instanceof JFrame) { ((JFrame) comp).setJMenuBar(menuBar); ((JFrame) comp).validate(); } } else { Component comp = ((AppD) app).getMainComponent(); if (comp instanceof JApplet) { ((JApplet) comp).setJMenuBar(null); } else if (comp instanceof JFrame) { ((JFrame) comp).setJMenuBar(null); ((JFrame) comp).validate(); } } } public void showAboutDialog() { GeoGebraMenuBar.showAboutDialog((AppD) app); } public void showPrintPreview() { GeoGebraMenuBar.showPrintPreview((AppD) app); } ContextMenuGraphicsWindowD drawingPadpopupMenu; /** * Displays the Graphics View menu at the position p in the coordinate space * of euclidianView */ public void showDrawingPadPopup(Component invoker, GPoint p) { // clear highlighting and selections in views app.getActiveEuclidianView().resetMode(); // menu for drawing pane context menu drawingPadpopupMenu = new ContextMenuGraphicsWindowD((AppD) app, p.x, p.y); drawingPadpopupMenu.getWrappedPopup().show(invoker, p.x, p.y); } /** * Toggles the Graphics View menu at the position p in the coordinate space * of euclidianView */ public void toggleDrawingPadPopup(Component invoker, Point p) { GPoint loc1 = new GPoint(p.x, p.y); if (drawingPadpopupMenu == null || !drawingPadpopupMenu.getWrappedPopup().isVisible()) { showDrawingPadPopup(invoker, loc1); return; } drawingPadpopupMenu.getWrappedPopup().setVisible(false); } ContextMenuGeoElementD popupMenu; /** * Displays the popup menu for geo at the position p in the coordinate space * of the component invoker */ public void showPopupMenu(ArrayList<GeoElement> geos, Component invoker, GPoint p) { if (geos == null || geos.size() == 0 || !app.letShowPopupMenu()) { return; } if (app.getKernel().isAxis(geos.get(0))) { showDrawingPadPopup(invoker, p); } else { // clear highlighting and selections in views app.getActiveEuclidianView().resetMode(); Point screenPos = (invoker == null) ? new Point(0, 0) : invoker.getLocationOnScreen(); screenPos.translate(p.x, p.y); popupMenu = new ContextMenuGeoElementD((AppD) app, geos, screenPos); popupMenu.getWrappedPopup().show(invoker, p.x, p.y); } } /** * Displays the popup menu for geo at the position p in the coordinate space * of the component invoker */ public void showPopupChooseGeo(ArrayList<GeoElement> selectedGeos, ArrayList<GeoElement> geos, EuclidianView view, GPoint p) { if (geos == null || !app.letShowPopupMenu()) { return; } Component invoker = ((EuclidianViewInterfaceD) view).getJPanel(); if (!geos.isEmpty() && app.getKernel().isAxis(geos.get(0))) { showDrawingPadPopup(invoker, p); } else { // clear highlighting and selections in views app.getActiveEuclidianView().resetMode(); Point screenPos = (invoker == null) ? new Point(0, 0) : invoker.getLocationOnScreen(); screenPos.translate(p.x, p.y); popupMenu = new ContextMenuChooseGeoD((AppD) app, view, selectedGeos, geos, screenPos, p); // popupMenu = new ContextMenuGeoElement(app, geos, screenPos); popupMenu.getWrappedPopup().show(invoker, p.x, p.y); } } /** * Toggles the popup menu for geo at the position p in the coordinate space * of the component invoker */ public void togglePopupMenu(ArrayList<GeoElement> geos, Component invoker, Point p) { GPoint loc1 = new GPoint(p.x, p.y); if (popupMenu == null || !popupMenu.getWrappedPopup().isVisible()) { showPopupMenu(geos, invoker, loc1); return; } popupMenu.getWrappedPopup().setVisible(false); } /** * Creates a new GeoImage, using an image provided by either a Transferable * object or the clipboard contents, then places it at the given location * (real world coords). If the transfer content is a list of images, then * multiple GeoImages will be created. * * @return whether a new image was created or not */ public boolean loadImage(Transferable transfer, boolean fromClipboard) { app.setWaitCursor(); String[] fileName = null; if (fromClipboard) { fileName = getImageFromTransferable(null); } else if (transfer != null) { fileName = getImageFromTransferable(transfer); } else { fileName = new String[1]; fileName[0] = getImageFromFile(); // opens file chooser dialog } boolean ret; if (fileName.length == 0 || fileName[0] == null) { ret = false; } else { EuclidianView ev = ((AppD) app).getActiveEuclidianView(); Construction cons = ev.getApplication().getKernel() .getConstruction(); // Point mousePos = ((EuclidianViewInterfaceDesktop) ev) // .getMousePosition(); // create GeoImage object(s) for this fileName GeoImage geoImage = null; GeoPoint loc1 = new GeoPoint(cons); GeoPoint loc2 = new GeoPoint(cons); for (int i = 0; i < fileName.length; i++) { // create corner points (bottom right/left) loc1 = new GeoPoint(cons); loc2 = new GeoPoint(cons); loc1.setCoords(ev.getXmin() + (ev.getXmax() - ev.getXmin()) / 4, ev.getYmin() + (ev.getYmax() - ev.getYmin()) / 4, 1.0); loc1.setLabel(null); loc1.setLabelVisible(false); loc1.update(); loc2.setCoords(ev.getXmax() - (ev.getXmax() - ev.getXmin()) / 4, ev.getYmin() + (ev.getYmax() - ev.getYmin()) / 4, 1.0); loc2.setLabel(null); loc2.setLabelVisible(false); loc2.update(); geoImage = new GeoImage(app.getKernel().getConstruction()); geoImage.setImageFileName(fileName[i]); geoImage.setCorner(loc1, 0); geoImage.setCorner(loc2, 1); geoImage.setLabel(null); GeoImage.updateInstances(app); } // make sure only the last image will be selected GeoElement[] geos = { geoImage, loc1, loc2 }; app.getActiveEuclidianView().getEuclidianController() .clearSelections(); app.getActiveEuclidianView().getEuclidianController() .memorizeJustCreatedGeos(geos); ret = true; } app.setDefaultCursor(); return ret; } public Color showColorChooser(GColor currentColor) { try { GeoGebraColorChooser chooser = new GeoGebraColorChooser((AppD) app); chooser.setColor(GColorD.getAwtColor(currentColor)); JDialog dialog = JColorChooser.createDialog( ((AppD) app).getMainComponent(), app.getLocalization().getMenu("ChooseColor"), true, chooser, null, null); dialog.setVisible(true); return chooser.getColor(); } catch (RuntimeException e) { return null; } } /** * gets String from clipboard */ public String getStringFromClipboard() { String selection = null; Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); Transferable transfer = clip.getContents(null); try { StringBuilder sbuf = new StringBuilder(); char readBuf[] = new char[1024 * 64]; int numChars; DataFlavor[] df = transfer.getTransferDataFlavors(); DataFlavor html = null; for (int i = 0; i < df.length; i++) { if (df[i].getMimeType().startsWith("text/html")) { html = df[i]; break; } } InputStreamReader reader; Object data = transfer.getTransferData(html); reader = data instanceof InputStreamReader ? (InputStreamReader) data : new InputStreamReader((InputStream) data, "UNICODE"); while (true) { numChars = reader.read(readBuf); if (numChars == -1) { break; } sbuf.append(readBuf, 0, numChars); } selection = new String(sbuf); reader.close(); } catch (RuntimeException e) { // e.printStackTrace(); } catch (Exception e) { // e.printStackTrace(); } return selection; } /** * /** Tries to gets an image from a transferable object or the clipboard * (if transfer is null). If an image is found, then it is loaded and stored * in this application's imageManager. * * @param transfer * @return fileName of image stored in imageManager */ @SuppressWarnings("unchecked") public String[] getImageFromTransferable(Transferable transfer0) { Transferable transfer = transfer0; BufferedImage img = null; String fileName = null; ArrayList<String> nameList = new ArrayList<String>(); boolean imageFound = false; app.setWaitCursor(); // if transfer is null then get it from the clipboard if (transfer == null) { try { Clipboard clip = Toolkit.getDefaultToolkit() .getSystemClipboard(); transfer = clip.getContents(null); fileName = "clipboard.png"; // extension determines what format // it will be in ggb file } catch (Exception e) { app.setDefaultCursor(); e.printStackTrace(); app.showError("PasteImageFailed"); return null; } } // load image from transfer try { transfer.getTransferDataFlavors(); DataFlavor htmlFlavor = new DataFlavor( "text/html; document=all; class=java.lang.String; charset=Unicode"); // PNG image copied in html format // eg http://jsfiddle.net/bvFNL/8/ if (transfer.isDataFlavorSupported(htmlFlavor)) { String html = (String) transfer.getTransferData(htmlFlavor); String pngMarker = "data:image/png;base64,"; int pngBase64index = html.indexOf(pngMarker); if (pngBase64index > -1) { int pngBase64end = html.indexOf("\"", pngBase64index); String base64 = html.substring( pngBase64index + pngMarker.length(), pngBase64end); byte[] bytes = Base64.decode(base64); InputStream in = new ByteArrayInputStream(bytes); img = ImageIO.read(in); fileName = "transferHTMLImage.png"; nameList.add(((AppD) app).createImage(new MyImageD(img), fileName)); imageFound = true; } } if (!imageFound && transfer.isDataFlavorSupported(DataFlavor.imageFlavor)) { img = (BufferedImage) transfer .getTransferData(DataFlavor.imageFlavor); if (img != null) { fileName = "transferImage.png"; nameList.add(((AppD) app).createImage(new MyImageD(img), fileName)); imageFound = true; } // System.out.println(nameList.toString()); } if (!imageFound && transfer .isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { // java.util.List list = null; // list = (java.util.List) // transfer.getTransferData(DataFlavor.javaFileListFlavor); List<File> list = (List<File>) transfer .getTransferData(DataFlavor.javaFileListFlavor); ListIterator<File> it = list.listIterator(); while (it.hasNext()) { File f = it.next(); fileName = f.getName(); img = ImageIO.read(f); if (img != null) { nameList.add(((AppD) app).createImage(new MyImageD(img), fileName)); imageFound = true; } } // System.out.println(nameList.toString()); } if (!imageFound && transfer.isDataFlavorSupported(uriListFlavor)) { String uris = (String) transfer.getTransferData(uriListFlavor); StringTokenizer st = new StringTokenizer(uris, "\r\n"); while (st.hasMoreTokens()) { URI uri = new URI(st.nextToken()); File f = new File(uri.toString()); fileName = f.getName(); img = ImageIO.read(uri.toURL()); if (img != null) { nameList.add(((AppD) app).createImage(new MyImageD(img), fileName)); imageFound = true; } } // System.out.println(nameList.toString()); } if (!imageFound && transfer.isDataFlavorSupported(urlFlavor)) { URL url = (URL) transfer.getTransferData(urlFlavor); ImageIcon ic = new ImageIcon(url); if (ic.getIconHeight() > -1 && ic.getIconWidth() > -1) { File f = new File(url.toString()); fileName = f.getName(); img = (BufferedImage) ic.getImage(); if (img != null) { nameList.add(((AppD) app).createImage(new MyImageD(img), fileName)); imageFound = true; } } // System.out.println(nameList.toString()); } } catch (UnsupportedFlavorException ufe) { app.setDefaultCursor(); ufe.printStackTrace(); return null; } catch (IOException ioe) { app.setDefaultCursor(); ioe.printStackTrace(); return null; } catch (Exception e) { app.setDefaultCursor(); e.printStackTrace(); return null; } app.setDefaultCursor(); String[] f = new String[nameList.size()]; return nameList.toArray(f); } /** * Shows a file open dialog to choose an image file, Then the image file is * loaded and stored in this application's imageManager. * * @return fileName of image stored in imageManager */ public String getImageFromFile() { return getImageFromFile(null); } public Localization getLocalization() { return app.getLocalization(); } /** * Loads and stores an image file is in this application's imageManager. If * a null image file is passed, then a file dialog is opened to choose a * file. * * @return fileName of image stored in imageManager */ public String getImageFromFile(File imageFile0) { File imageFile = imageFile0; MyImageD img = new MyImageD(); String fileName = null; try { app.setWaitCursor(); // else { if (imageFile == null) { /************************************************************** * Mac OS X related code to work around JFileChooser problem * on sandboxing. See * http://intransitione.com/blog/take-java-to-app-store/ **************************************************************/ if (((AppD) app).macsandbox) { FileDialog fd = new FileDialog(((AppD) app).getFrame()); fd.setModal(true); File currentPath = ((AppD) app).getCurrentPath(); fd.setMode(FileDialog.LOAD); if (currentPath != null) { fd.setDirectory(currentPath.toString()); } fd.setFilenameFilter(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return (name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png") || name.endsWith(".bmp") || name.endsWith(".gif")); } }); fd.setTitle(loc.getMenu("Load")); fd.toFront(); fd.setVisible(true); // FIXME: find a better place for this, we need to // change the // cursor back before NPE when file loading was // unsuccessful: app.setDefaultCursor(); if (fd.getFile() != null) { imageFile = new File( fd.getDirectory() + "/" + fd.getFile()); } ((AppD) app) .setCurrentPath(new File(fd.getDirectory())); } else { /************************************************************** * End of Mac OS X related code. **************************************************************/ ((DialogManagerD) getDialogManager()).initFileChooser(); GeoGebraFileChooser fileChooser = ((DialogManagerD) getDialogManager()) .getFileChooser(); fileChooser.setMode(GeoGebraFileChooser.MODE_IMAGES); fileChooser.setCurrentDirectory( ((AppD) app).getCurrentImagePath()); MyFileFilter fileFilter = new MyFileFilter(); fileFilter.addExtension(FileExtensions.JPG); fileFilter.addExtension(FileExtensions.JPEG); fileFilter.addExtension(FileExtensions.PNG); fileFilter.addExtension(FileExtensions.GIF); fileFilter.addExtension(FileExtensions.BMP); fileFilter.addExtension(FileExtensions.SVG); fileFilter.setDescription( getLocalization().getMenu("Image")); fileChooser.resetChoosableFileFilters(); fileChooser.setFileFilter(fileFilter); int returnVal = fileChooser.showOpenDialog( ((AppD) app).getMainComponent()); if (returnVal == JFileChooser.APPROVE_OPTION) { imageFile = fileChooser.getSelectedFile(); if (imageFile != null) { ((AppD) app).setCurrentImagePath( imageFile.getParentFile()); if (!app.isApplet()) { GeoGebraPreferencesD.getPref() .saveDefaultImagePath(((AppD) app) .getCurrentImagePath()); } } } } } if (imageFile == null) { app.setDefaultCursor(); return null; } // get file name fileName = imageFile.getCanonicalPath(); // load image img.load(imageFile); } return ((AppD) app).createImage(img, fileName); } catch (Exception e) { app.setDefaultCursor(); e.printStackTrace(); app.showError("LoadFileFailed"); return null; } } /** * Opens file chooser and returns a data file for the spreadsheet G.Sturr * 2010-2-5 */ @Override public File getDataFile() { // TODO -- create MODE_DATA that shows preview of text file (or no // preview?) File dataFile = null; try { app.setWaitCursor(); /************************************************************** * Mac OS X related code to work around JFileChooser problem on * sandboxing. See * http://intransitione.com/blog/take-java-to-app-store/ **************************************************************/ if (((AppD) app).macsandbox) { FileDialog fd = new FileDialog(((AppD) app).getFrame()); fd.setModal(true); File currentPath = ((AppD) app).getCurrentPath(); fd.setMode(FileDialog.LOAD); if (currentPath != null) { fd.setDirectory(currentPath.toString()); } fd.setFilenameFilter(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return (name.endsWith(".txt") || name.endsWith(".csv") || name.endsWith(".dat")); } }); fd.setTitle(loc.getMenu("Load")); fd.toFront(); fd.setVisible(true); // FIXME: find a better place for this, we need to change the // cursor back before NPE when file loading was unsuccessful: app.setDefaultCursor(); if (fd.getFile() != null) { dataFile = new File(fd.getDirectory() + "/" + fd.getFile()); } ((AppD) app).setCurrentPath(new File(fd.getDirectory())); return dataFile; } /************************************************************** * End of Mac OS X related code. **************************************************************/ ((DialogManagerD) getDialogManager()).initFileChooser(); GeoGebraFileChooser fileChooser = ((DialogManagerD) getDialogManager()) .getFileChooser(); fileChooser.setMode(GeoGebraFileChooser.MODE_DATA); fileChooser.setCurrentDirectory(((AppD) app).getCurrentImagePath()); MyFileFilter fileFilter = new MyFileFilter(); fileFilter.addExtension(FileExtensions.TXT); fileFilter.addExtension(FileExtensions.CSV); fileFilter.addExtension(FileExtensions.DAT); // fileFilter.setDescription(app.getPlain("Image")); fileChooser.resetChoosableFileFilters(); fileChooser.setFileFilter(fileFilter); int returnVal = fileChooser .showOpenDialog(((AppD) app).getMainComponent()); if (returnVal == JFileChooser.APPROVE_OPTION) { dataFile = fileChooser.getSelectedFile(); if (dataFile != null) { ((AppD) app).setCurrentImagePath(dataFile.getParentFile()); if (!app.isApplet()) { GeoGebraPreferencesD.getPref().saveDefaultImagePath( ((AppD) app).getCurrentImagePath()); } } } } catch (Exception e) { app.setDefaultCursor(); e.printStackTrace(); app.showError("LoadFileFailed"); return null; } app.setDefaultCursor(); return dataFile; } // returns true for YES or NO and false for CANCEL @Override public boolean saveCurrentFile() { app.getEuclidianView1().reset(); if (app.hasEuclidianView2(1)) { app.getEuclidianView2(1).reset(); } // use null component for iconified frame Component comp = ((AppD) app).getMainComponent(); if (((AppD) app).getFrame() instanceof GeoGebraFrame) { GeoGebraFrame frame = (GeoGebraFrame) ((AppD) app).getFrame(); comp = frame != null && !frame.isIconified() ? frame : null; } Object[] options = { loc.getMenu("Save"), loc.getMenu("DontSave"), loc.getMenu("Cancel") }; int returnVal = JOptionPane.showOptionDialog(comp, loc.getMenu("DoYouWantToSaveYourChanges"), loc.getMenu("CloseFile"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]); /* * int returnVal = JOptionPane.showConfirmDialog( comp, * getMenu("SaveCurrentFileQuestion"), * GeoGebraConstants.APPLICATION_NAME + " - " + * app.getPlain("Question"), JOptionPane.YES_NO_CANCEL_OPTION, * JOptionPane.QUESTION_MESSAGE); */ switch (returnVal) { case 0: return save(); case 1: return true; default: return false; } } @Override public boolean save() { // app.getFrame().getJMenuBar() app.setWaitCursor(); // close properties dialog if open getDialogManager().closeAll(); boolean success = false; if (((AppD) app).getCurrentFile() != null) { // Mathieu Blossier - 2008-01-04 // if the file is read-only, open save as if (!((AppD) app).getCurrentFile().canWrite()) { success = saveAs(); } else { success = ((AppD) app) .saveGeoGebraFile(((AppD) app).getCurrentFile()); } } else { success = saveAs(); } app.setDefaultCursor(); return success; } @Override public boolean saveAs() { // Mathieu Blossier - 2008-01-04 // if the file is hidden, set current file to null if (((AppD) app).getCurrentFile() != null) { if (!((AppD) app).getCurrentFile().canWrite() && ((AppD) app).getCurrentFile().isHidden()) { app.setCurrentFile(null); ((AppD) app).setCurrentPath(null); } } FileExtensions[] fileExtensions; String[] fileDescriptions; fileExtensions = new FileExtensions[] { FileExtensions.GEOGEBRA }; fileDescriptions = new String[] { GeoGebraConstants.APPLICATION_NAME + " " + loc.getMenu("Files") }; ((AppD) app).needThumbnailFor3D(); File file = showSaveDialog(fileExtensions, ((AppD) app).getCurrentFile(), fileDescriptions, true, false); if (file == null) { return false; } boolean success = ((AppD) app).saveGeoGebraFile(file); if (success) { app.setCurrentFile(file); } return success; } @Override public File showSaveDialog(FileExtensions fileExtension, File selectedFile0, String fileDescription, boolean promptOverwrite, boolean dirsOnly) { File selectedFile = selectedFile0; if (selectedFile == null) { selectedFile = removeExtension(((AppD) app).getCurrentFile()); } FileExtensions[] fileExtensions = { fileExtension }; String[] fileDescriptions = { fileDescription }; return showSaveDialog(fileExtensions, selectedFile, fileDescriptions, promptOverwrite, dirsOnly); } public File showSaveDialog(final FileExtensions[] fileExtensions, File selectedFile0, String[] fileDescriptions, boolean promptOverwrite, boolean dirsOnly) { boolean done = false; File selectedFile = selectedFile0; File file = null; if (fileExtensions == null || fileExtensions.length == 0 || fileDescriptions == null) { return null; } FileExtensions fileExtension = fileExtensions[0]; /************************************************************** * Mac OS X related code to work around JFileChooser problem on * sandboxing. See http://intransitione.com/blog/take-java-to-app-store/ **************************************************************/ if (((AppD) app).macsandbox) { while (!done) { NSSavePanel panel = new NSSavePanel(); String result = panel.saveDialog(loc.getMenu("Save"), fileExtension.toString()); file = new File(result); done = true; /* * FileDialog fd = new FileDialog(((AppD) app).getFrame()); * fd.setModal(true); File currentPath = ((AppD) * app).getCurrentPath(); fd.setMode(FileDialog.SAVE); if * (currentPath != null) { * fd.setDirectory(currentPath.toString()); } * fd.setFilenameFilter(new FilenameFilter() { public boolean * accept(File dir, String name) { for (String s : * fileExtensions) { if (name.endsWith("." + s)) { return true; * } } return false; } }); fd.setTitle(loc.getMenu("Save")); if * (selectedFile == null) { String str = * app.getPlain("UntitledConstruction"); int length = * str.length(); // Sandbox (when running the application * directly from Finder) // may return with a filename which is * incompatible, // thus we try to ensure that the filename does * not contain // accented letters: str = * Normalizer.normalize(str, Normalizer.Form.NFKD); str = * str.replaceAll( "[^\\x20-\\x7E]", ""); if (str.length() * 2 < * length) { // This normalization can filter out all or almost * all // non-Latin characters. If this happens: str = * "Untitled Construction"; // using the English version } * fd.setFile(str + "." + fileExtension); } else { * fd.setFile(selectedFile.getName()); } * * fd.toFront(); fd.setVisible(true); * * if (fd.getFile() == null) { // cancel pressed return null; } * * file = new File(fd.getDirectory() + "/" + fd.getFile()); * ((AppD) app).setCurrentPath(new File(fd.getDirectory())); * * // Don't add file extension since it will be disallowed on * Mac in sandbox: // file = addExtension(file, fileExtension); * lastFilenameOfSaveDialog = file.getName(); * * // Don't ask overwrite question again. Mac will do it * already. done = true; */ } return file; } /************************************************************** * End of Mac OS X related code. **************************************************************/ ((DialogManagerD) getDialogManager()).initFileChooser(); GeoGebraFileChooser fileChooser = ((DialogManagerD) getDialogManager()) .getFileChooser(); fileChooser.setMode(GeoGebraFileChooser.MODE_GEOGEBRA_SAVE); fileChooser.setCurrentDirectory(((AppD) app).getCurrentPath()); if (dirsOnly) { fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); } // set selected file if (selectedFile != null) { fileExtension = StringUtil.getFileExtension(selectedFile.getName()); int i = 0; while (i < fileExtensions.length && !fileExtension.equals(fileExtensions[i])) { i++; } if (i >= fileExtensions.length) { fileExtension = fileExtensions[0]; } selectedFile = addExtension(selectedFile, fileExtension); fileChooser.setSelectedFile(selectedFile); } else { fileChooser.setSelectedFile(null); } fileChooser.resetChoosableFileFilters(); MyFileFilter fileFilter; MyFileFilter mainFilter = null; for (int i = 0; i < fileExtensions.length; i++) { fileFilter = new MyFileFilter(fileExtensions[i]); if (fileDescriptions.length >= i && fileDescriptions[i] != null) { fileFilter.setDescription(fileDescriptions[i]); } fileChooser.addChoosableFileFilter(fileFilter); if (fileExtension.equals(fileExtensions[i])) { mainFilter = fileFilter; } } fileChooser.setFileFilter(mainFilter); while (!done) { // show save dialog int returnVal = fileChooser .showSaveDialog(((AppD) app).getMainComponent()); if (returnVal == JFileChooser.APPROVE_OPTION) { file = fileChooser.getSelectedFile(); if (fileChooser.getFileFilter() instanceof MyFileFilter) { fileFilter = (MyFileFilter) fileChooser.getFileFilter(); fileExtension = fileFilter.getExtension(); } else { fileExtension = fileExtensions[0]; } // remove all special characters from HTML filename if (fileExtension.equals(FileExtensions.HTML)) { file = removeExtension(file); file = new File(file.getParent(), UtilD.keepOnlyLettersAndDigits(file.getName())); } // remove "*<>/\?|: file = new File(file.getParent(), Util.processFilename(file.getName())); // add file extension file = addExtension(file, fileExtension); fileChooser.setSelectedFile(file); lastFilenameOfSaveDialog = file.getName(); if (promptOverwrite && file.exists()) { // ask overwrite question Object[] options = { getLocalization().getMenu("Overwrite"), loc.getMenu("DontOverwrite") }; int n = JOptionPane.showOptionDialog( ((AppD) app).getMainComponent(), getLocalization().getPlain("OverwriteFile") + "\n" + file.getName(), getLocalization().getPlain("Question"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[1]); done = (n == 0); /* * int n = JOptionPane.showConfirmDialog( * app.getMainComponent(), app.getPlain("OverwriteFile") + * "\n" + file.getAbsolutePath(), app.getPlain("Question"), * JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); * done = (n == JOptionPane.YES_OPTION); */ } else { done = true; } } else { // } else // return null; file = null; break; } } return file; } public static File addExtension(File file, FileExtensions fileExtension) { return addExtension(file, fileExtension.toString()); } public static File addExtension(File file, String fileExtension) { if (file == null) { return null; } if (StringUtil.getFileExtensionStr(file.getName()) .equals(fileExtension)) { return file; } return new File(file.getParentFile(), // path file.getName() + '.' + fileExtension); // filename } public static File removeExtension(File file) { if (file == null) { return null; } String fileName = file.getName(); int dotPos = fileName.lastIndexOf('.'); if (dotPos <= 0) { return file; } return new File(file.getParentFile(), // path fileName.substring(0, dotPos)); } @Override public void openURL() { InputDialogD id = new InputDialogOpenURL((AppD) app); id.setVisible(true); } @Override public void openFromGGT() { if ((app).isSaved() || saveCurrentFile()) { ((DialogManagerD) app.getDialogManager()).showOpenFromGGTDialog(); } } @Override public void openFile() { openFile(null); } /** * Points to the given file in the file dialog popup window and offers to * choose that file --- or a different one. * * @param file */ public void openFile(File file) { if ((app).isSaved() || saveCurrentFile()) { app.setWaitCursor(); /************************************************************** * Mac OS X related code to work around JFileChooser problem on * sandboxing. See * http://intransitione.com/blog/take-java-to-app-store/ **************************************************************/ if (((AppD) app).macsandbox) { FileDialog fd = new FileDialog(((AppD) app).getFrame()); fd.setModal(true); File currentPath = null; if (file == null) { currentPath = ((AppD) app).getCurrentPath(); } else { currentPath = file.getParentFile(); fd.setFile(file.getName()); } fd.setMode(FileDialog.LOAD); if (currentPath != null) { fd.setDirectory(currentPath.toString()); } fd.setFilenameFilter(new FilenameFilter() { @Override public boolean accept(File dir, String name) { FileExtensions ext = StringUtil.getFileExtension(name); return ext.equals(FileExtensions.GEOGEBRA) || ext.equals(FileExtensions.GEOGEBRA_TOOL) || ext.equals(FileExtensions.HTML) || ext.equals(FileExtensions.HTM) || ext.equals(FileExtensions.OFF); } }); fd.setTitle(loc.getMenu("Load")); fd.toFront(); fd.setVisible(true); // FIXME: find a better place for this, we need to change the // cursor back before NPE when file loading was unsuccessful: app.setDefaultCursor(); File[] files = new File[1]; if (fd.getFile() != null) { files[0] = new File(fd.getDirectory() + "/" + fd.getFile()); } ((AppD) app).setCurrentPath(new File(fd.getDirectory())); app.setDefaultCursor(); doOpenFiles(files, true); return; } /************************************************************** * End of Mac OS X related code. **************************************************************/ File oldCurrentFile = ((AppD) app).getCurrentFile(); ((DialogManagerD) getDialogManager()).initFileChooser(); GeoGebraFileChooser fileChooser = ((DialogManagerD) getDialogManager()) .getFileChooser(); fileChooser.setMode(GeoGebraFileChooser.MODE_GEOGEBRA); fileChooser.setCurrentDirectory(((AppD) app).getCurrentPath()); fileChooser.setMultiSelectionEnabled(true); fileChooser.setSelectedFile(oldCurrentFile); // GeoGebra File Filter MyFileFilter fileFilter = new MyFileFilter(); fileFilter.addExtension(FileExtensions.GEOGEBRA); fileFilter.addExtension(FileExtensions.GEOGEBRA_TOOL); fileFilter.addExtension(FileExtensions.HTML); fileFilter.addExtension(FileExtensions.HTM); fileFilter.setDescription( GeoGebraConstants.APPLICATION_NAME + loc.getMenu("Files")); fileChooser.resetChoosableFileFilters(); fileChooser.addChoosableFileFilter(fileFilter); MyFileFilter insertFilter = new MyFileFilter(); insertFilter.addExtension(FileExtensions.GEOGEBRA); insertFilter.setDescription(loc.getMenu("InsertFile")); fileChooser.addChoosableFileFilter(insertFilter); MyFileFilter templateFilter = new MyFileFilter(); templateFilter.addExtension(FileExtensions.GEOGEBRA); templateFilter.setDescription(loc.getMenu("ApplyTemplate")); fileChooser.addChoosableFileFilter(templateFilter); MyFileFilter offFilter = new MyFileFilter(FileExtensions.OFF); // TODO: Localization offFilter.setDescription("OFF file"); fileChooser.addChoosableFileFilter(offFilter); if (oldCurrentFile == null || StringUtil.getFileExtension(oldCurrentFile.getName()) .equals(FileExtensions.GEOGEBRA) || StringUtil.getFileExtension(oldCurrentFile.getName()) .equals(FileExtensions.GEOGEBRA_TOOL)) { fileChooser.setFileFilter(fileFilter); } app.setDefaultCursor(); int returnVal = fileChooser .showOpenDialog(((AppD) app).getMainComponent()); File[] files = null; if (returnVal == JFileChooser.APPROVE_OPTION) { files = fileChooser.getSelectedFiles(); } FileFilter filter = fileChooser.getFileFilter(); if (filter == fileFilter) { fileFilter = (MyFileFilter) fileChooser.getFileFilter(); doOpenFiles(files, true, fileFilter.getExtension()); } else if (filter == templateFilter) { // #4403 app.setWaitCursor(); app.setMoveMode(); for (int i = 0; i < files.length; i++) { File file0 = files[i]; if (!file0.exists()) { file0 = addExtension(file0, FileExtensions.GEOGEBRA); } ((AppD) app).applyTemplate(file0); } app.setDefaultCursor(); } else if (filter == insertFilter) { app.setWaitCursor(); app.setMoveMode(); for (int i = 0; i < files.length; i++) { File file0 = files[i]; if (!file0.exists()) { file0 = addExtension(file0, FileExtensions.GEOGEBRA); } ((AppD) app).insertFile(file0); } app.setDefaultCursor(); } else if (filter == offFilter) { app.setWaitCursor(); app.setMoveMode(); for (int i = 0; i < files.length; i++) { File file0 = files[i]; if (!file0.exists()) { file0 = addExtension(file0, FileExtensions.OFF); } } doOpenFiles(files, true); app.setDefaultCursor(); } else { doOpenFiles(files, true); } fileChooser.setMultiSelectionEnabled(false); } } public synchronized void doOpenFiles(File[] files, boolean allowOpeningInThisInstance) { doOpenFiles(files, allowOpeningInThisInstance, FileExtensions.GEOGEBRA); } public synchronized void doOpenFiles(File[] files, boolean allowOpeningInThisInstance, FileExtensions extension) { // there are selected files if (files != null) { File file; int counter = 0; for (int i = 0; i < files.length; i++) { file = files[i]; if (!file.exists()) { file = addExtension(file, extension); if (extension.equals(FileExtensions.GEOGEBRA) && !file.exists()) { file = addExtension(removeExtension(file), FileExtensions.GEOGEBRA_TOOL); } if (extension.equals(FileExtensions.GEOGEBRA) && !file.exists()) { file = addExtension(removeExtension(file), FileExtensions.HTML); } if (extension.equals(FileExtensions.GEOGEBRA) && !file.exists()) { file = addExtension(removeExtension(file), FileExtensions.HTM); } if (extension.equals(FileExtensions.GEOGEBRA) && !file.exists()) { file = addExtension(removeExtension(file), FileExtensions.OFF); } if (!file.exists()) { // Put the correct extension back on for the error // message file = addExtension(removeExtension(file), extension); JOptionPane.showConfirmDialog( ((AppD) app).getMainComponent(), getLocalization().getError("FileNotFound") + ":\n" + file.getAbsolutePath(), app.getLocalization().getError("Error"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE); } } FileExtensions ext = StringUtil .getFileExtension(file.getName()); if (file.exists()) { if (FileExtensions.GEOGEBRA_TOOL.equals(ext)) { // load macro file loadFile(file, true); } else if (FileExtensions.HTML.equals(ext) || FileExtensions.HTM.equals(ext)) { // load HTML file with applet param ggbBase64 // if we loaded from GGB, we don't want to overwrite old // file loadBase64File(file); } else if (FileExtensions.OFF.equals(ext)) { loadOffFile(file); } else { // standard GeoGebra file GeoGebraFrame inst = GeoGebraFrame .getInstanceWithFile(file); if (inst == null) { counter++; if (counter == 1 && allowOpeningInThisInstance) { // open first file in current window loadFile(file, false); } else { // create new window for file try { String[] args = { file.getCanonicalPath() }; GeoGebraFrame wnd = GeoGebraFrame .createNewWindow( new CommandLineArguments( args)); wnd.toFront(); wnd.requestFocus(); } catch (Exception e) { e.printStackTrace(); } } } else if (counter == 0) { // there is an instance with this file opened inst.toFront(); inst.requestFocus(); } } } } } } @Override public void allowGUIToRefresh() { if (!SwingUtilities.isEventDispatchThread()) { return; } } /** * Passes a transferable object to the application's dropTargetListener. * Returns true if a ggb file was dropped succesfully. This is a utility * method for component transfer handlers that need to pass potential ggb * file drops on to the top level drop handler. * * @param t * @return */ public boolean handleGGBFileDrop(Transferable t) { FileDropTargetListener dtl = ((GeoGebraFrame) ((AppD) app).getFrame()) .getDropTargetListener(); boolean isGGBFileDrop = dtl.handleFileDrop(t); return (isGGBFileDrop); } @Override public boolean loadFile(final File file, final boolean isMacroFile) { boolean success = ((AppD) app).loadFile(file, isMacroFile); updateGUIafterLoadFile(success, isMacroFile); app.setDefaultCursor(); return success; } // See http://stackoverflow.com/questions/6198894/java-encode-url for an // explanation public static URL getEscapedUrl(String url0) throws Exception { String url; if (url0.startsWith("www")) { url = "http://" + url0; } else { url = url0; } URL u = new URL(url); return new URI(u.getProtocol(), u.getAuthority(), u.getPath(), u.getQuery(), u.getRef()).toURL(); } /* * loads an html file with <param name="ggbBase64" value="UEsDBBQACAAI... */ public boolean loadBase64File(final File file) { boolean success = ((AppD) app).loadBase64File(file); updateGUIafterLoadFile(success, false); return success; } /** * Load off files to current view * * @param file * off file * @return status */ public boolean loadOffFile(final File file) { boolean success = ((AppD) app).loadOffFile(file); updateGUIafterLoadFile(success, false); return success; } @Override public void updateGUIafterLoadFile(boolean success, boolean isMacroFile) { if (success && !isMacroFile && !app.getSettings().getLayout().isIgnoringDocumentLayout()) { getLayout().setPerspectives(app.getTmpPerspectives(), null); SwingUtilities .updateComponentTreeUI(getLayout().getRootComponent()); if (!app.isIniting()) { updateFrameSize(); // checks internally if frame is available if (app.needsSpreadsheetTableModel()) { (app).getSpreadsheetTableModel(); // ensure create one if // not already done } } } else if (isMacroFile && success) { refreshCustomToolsInToolBar(); ((AppD) app).updateToolBar(); ((AppD) app).updateContentPane(); } if (kernel.wantAnimationStarted()) { kernel.getAnimatonManager().startAnimation(); kernel.setWantAnimationStarted(false); } if (app.isEuclidianView3Dinited()) { EuclidianView ev = (EuclidianView) app.getEuclidianView3D(); ev.updateFonts(); ((EuclidianView3DInterface) ev).updateAllDrawables(); } // force JavaScript ggbOnInit(); to be called if (!app.isApplet()) { app.getScriptManager().ggbOnInit(); ((AppD) app).centerFrame(); } } protected boolean initActions() { if (showAxesAction != null) { return false; } showAxesAction = new AbstractAction(loc.getMenu("Axes"), ((AppD) app).getScaledIcon(GuiResourcesD.AXES)) { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { showAxesCmd(); } }; showGridAction = new AbstractAction(loc.getMenu("Grid"), ((AppD) app).getScaledIcon(GuiResourcesD.GRID)) { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { showGridCmd(); } }; undoAction = new AbstractAction(loc.getMenu("Undo"), ((AppD) app).getScaledIcon(GuiResourcesD.MENU_EDIT_UNDO)) { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { undo(); } }; redoAction = new AbstractAction(loc.getMenu("Redo"), ((AppD) app).getScaledIcon(GuiResourcesD.MENU_EDIT_REDO)) { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { redo(); } }; updateActions(); return true; } @Override public void updateCheckBoxesForShowConstructinProtocolNavigation(int id) { if (propertiesView != null) { propertiesView.updatePanelGUI(id); } } @Override public void updateActions() { if (undoAction != null) { if (app.isUndoActive()) { undoAction.setEnabled(kernel.undoPossible()); } else { // eg --enableUndo=false undoAction.setEnabled(false); } } if (redoAction != null) { if (app.isUndoActive()) { redoAction.setEnabled(kernel.redoPossible()); } else { // eg --enableUndo=false redoAction.setEnabled(false); } } } public int getMenuBarHeight() { if (menuBar == null) { return 0; } return ((JMenuBar) menuBar).getHeight(); } public int getAlgebraInputHeight() { if (app.showAlgebraInput() && algebraInput != null) { return algebraInput.getHeight(); } return 0; } public AbstractAction getShowAxesAction() { initActions(); return showAxesAction; } public AbstractAction getShowGridAction() { initActions(); return showGridAction; } public ToolbarD getGeneralToolbar() { return toolbarPanel.getFirstToolbar(); } @Override public String getToolbarDefinition() { // "null" may appear in files created using some buggy versions of Touch if (("null".equals(strCustomToolbarDefinition) || strCustomToolbarDefinition == null) && toolbarPanel != null) { return getGeneralToolbar().getDefaultToolbarString(); } return strCustomToolbarDefinition; } @Override public void removeFromToolbarDefinition(int mode) { if (strCustomToolbarDefinition != null) { // Application.debug("before: " + strCustomToolbarDefinition + // ", delete " + mode); strCustomToolbarDefinition = strCustomToolbarDefinition .replaceAll(Integer.toString(mode), ""); } } @Override public void addToToolbarDefinition(int mode) { if (this.getActiveEuclidianView().getDimension() > 2) { DockPanelD panel = this.getLayout().getDockManager() .getPanel(this.getActiveEuclidianView().getViewID()); panel.addToToolbar(mode); panel.updateToolbar(); return; } strCustomToolbarDefinition = ToolBar.addMode(strCustomToolbarDefinition, mode); } public void showURLinBrowser(URL url) { if (AppD.getJApplet() != null) { Log.debug("opening URL (applet):" + url); AppD.getJApplet().getAppletContext().showDocument(url, "_blank"); } else { Log.debug("opening URL:" + url.toExternalForm()); BrowserLauncher.openURL(url.toExternalForm()); } } @Override public void openHelp(String page, Help type) { try { URL helpURL = getEscapedUrl(getHelpURL(type, page)); showURLinBrowser(helpURL); } catch (MyError e) { app.showError(e); } catch (Exception e) { Log.debug("openHelp error: " + e.toString() + " " + e.getMessage() + " " + page + " " + type); app.showError(e.getMessage()); e.printStackTrace(); } } @Override public void showURLinBrowser(String strURL) { try { URL url = getEscapedUrl(strURL); showURLinBrowser(url); } catch (Exception e) { e.printStackTrace(); } } /** * Returns text "Created with <ApplicationName>" and link to application * homepage in html. */ public String getCreatedWithHTML() { String plain; plain = StringUtil .toHTMLString(getLocalization().getMenu("CreatedWithGeoGebra")); if (StringUtil.toLowerCase(plain).indexOf("geogebr") == -1) { plain = "Created with GeoGebra"; } String[] words = plain.split(" "); StringBuilder ret = new StringBuilder(); for (int i = 0; i < words.length; i++) { // deliberate 'a' missing if (StringUtil.toLowerCase(words[i]).startsWith("geogebr")) { // wrap translation of GeoGebra to make a link words[i] = wrapLink(words[i]); } ret.append(words[i] + ((i == words.length - 1) ? "" : " ")); } return ret.toString(); } private static String wrapLink(String string) { return "<a href=\"" + GeoGebraConstants.GEOGEBRA_WEBSITE + "\" target=\"_blank\" >" + string + "</a>"; } @Override public int setToolbarMode(int mode, ModeSetter m) { if (toolbarPanel == null) { if (layout != null && layout.getDockManager() != null) { layout.getDockManager().setToolbarMode(mode); } return mode; } int ret = toolbarPanel.setMode(mode); layout.getDockManager().setToolbarMode(mode); return ret; } /** * Exports construction protocol as html */ /* * final public void exportConstructionProtocolHTML() { * constructionProtocolView.initProtocol(); * constructionProtocolView.showHTMLExportDialog(); } */ public final String getCustomToolbarDefinition() { return strCustomToolbarDefinition; } public AbstractAction getRedoAction() { initActions(); return redoAction; } public AbstractAction getUndoAction() { initActions(); return undoAction; } @Override public void updateFrameSize() { JFrame fr = ((AppD) app).getFrame(); if (fr instanceof GeoGebraFrame) { ((GeoGebraFrame) fr).updateSize(); ((AppD) app).validateComponent(); } } @Override public void updateFrameTitle() { if (!(((AppD) app).getFrame() instanceof GeoGebraFrame)) { return; } GeoGebraFrame frame = (GeoGebraFrame) ((AppD) app).getFrame(); StringBuilder sb = new StringBuilder(); if (((AppD) app).getCurrentFile() != null) { sb.append(((AppD) app).getCurrentFile().getName()); } else { sb.append(GeoGebraConstants.APPLICATION_NAME); if (GeoGebraFrame.getInstanceCount() > 1) { int nr = frame.getInstanceNumber(); sb.append(" ("); sb.append(nr + 1); sb.append(')'); } } frame.setTitle(sb.toString()); } @Override public Object createFrame() { GeoGebraFrame wnd = new GeoGebraFrame(); wnd.setGlassPane(layout.getDockManager().getGlassPane()); wnd.setApplication((AppD) app); return wnd; } public static synchronized void exitAll() { ArrayList<GeoGebraFrame> insts = GeoGebraFrame.getInstances(); GeoGebraFrame[] instsCopy = new GeoGebraFrame[insts.size()]; for (int i = 0; i < instsCopy.length; i++) { instsCopy[i] = insts.get(i); } for (int i = 0; i < instsCopy.length; i++) { instsCopy[i].getApplication().exit(); } } @Override public void exitAllCurrent() { if (layout != null) { layout.getDockManager().exitAllCurrent(); } } VirtualKeyboardListener currentKeyboardListener = null; public VirtualKeyboardListener getCurrentKeyboardListener() { return currentKeyboardListener; } public void setCurrentTextfield(VirtualKeyboardListener keyboardListener, boolean autoClose) { currentKeyboardListener = keyboardListener; if (virtualKeyboard != null) { if (currentKeyboardListener == null) { // close virtual keyboard when focus lost // ... unless we've lost focus because we've just opened it! if (autoClose) { toggleKeyboard(false); } } else { // open virtual keyboard when focus gained if (AppD.isVirtualKeyboardActive()) { toggleKeyboard(true); } } } } WindowsUnicodeKeyboard kb = null; public void insertStringIntoTextfield(String text, boolean altPressed, boolean ctrlPressed, boolean shiftPressed) { if (currentKeyboardListener != null && !"\n".equals(text) && (!text.startsWith("<") || !text.endsWith(">")) && !altPressed && !ctrlPressed) { currentKeyboardListener.insertString(text); } else { // use Robot if no TextField currently active // or for special keys eg Enter if (kb == null) { try { kb = new WindowsUnicodeKeyboard(); } catch (Exception e) { return; } } kb.doType(altPressed, ctrlPressed, shiftPressed, text); } } VirtualKeyboardD virtualKeyboard = null; public void toggleKeyboard(boolean show) { getVirtualKeyboard().setVisible(show); } /** * @return The virtual keyboard (initializes it if necessary) */ public VirtualKeyboardD getVirtualKeyboard() { if (virtualKeyboard == null) { KeyboardSettings settings = app.getSettings().getKeyboard(); virtualKeyboard = new VirtualKeyboardD(((AppD) app), settings.getKeyboardWidth(), settings.getKeyboardHeight(), (float) settings.getKeyboardOpacity()); settings.addListener(virtualKeyboard); } return virtualKeyboard; } public boolean hasVirtualKeyboard() { return virtualKeyboard != null; } /* * HandwritingRecognitionTool handwritingRecognition = null; * * public Component getHandwriting() { * * if (handwritingRecognition == null) { handwritingRecognition = new * HandwritingRecognitionTool(app); } return handwritingRecognition; * * } * * public void toggleHandwriting(boolean show) { * * if (handwritingRecognition == null) { handwritingRecognition = new * HandwritingRecognitionTool(app); } * handwritingRecognition.setVisible(show); * handwritingRecognition.repaint(); * * } * * public boolean showHandwritingRecognition() { if (handwritingRecognition * == null) return false; * * return handwritingRecognition.isVisible(); } */ public boolean showVirtualKeyboard() { if (virtualKeyboard == null) { return false; } return virtualKeyboard.isVisible(); } @Override public boolean noMenusOpen() { if (popupMenu != null && popupMenu.getWrappedPopup().isVisible()) { // Application.debug("menus open"); return false; } if (drawingPadpopupMenu != null && drawingPadpopupMenu.getWrappedPopup().isVisible()) { // Application.debug("menus open"); return false; } // Application.debug("no menus open"); return true; } // TextInputDialog recent symbol list private ArrayList<String> recentSymbolList; public ArrayList<String> getRecentSymbolList() { if (recentSymbolList == null) { recentSymbolList = new ArrayList<String>(); recentSymbolList.add(Unicode.PI_STRING); for (int i = 0; i < 9; i++) { recentSymbolList.add(""); } } return recentSymbolList; } public static void setFontRecursive(Container c, Font font) { Component[] components = c.getComponents(); for (Component com : components) { com.setFont(font); if (com instanceof Container) { setFontRecursive((Container) com, font); } } } public static void setLabelsRecursive(Container c) { Component[] components = c.getComponents(); for (Component com : components) { // com.setl(font); // ((Panel)com).setLabels(); if (com instanceof Container) { // Application.debug("container"+com.getClass()); setLabelsRecursive((Container) com); } if (com instanceof SetLabels) { // Application.debug("container"+com.getClass()); ((SetLabels) com).setLabels(); } /* * for debugging, to show classes that might benefit from * implementing SetLabels if (com instanceof JPanel && !(com * instanceof SetLabels) &&!(com.getClass().toString().startsWith( * "class java"))) { //((JPanel)com).setla * System.err.println(com.getClass().toString()+" panel "+com); }// */ } } private InputBarHelpPanelD inputHelpPanel; public boolean hasInputHelpPanel() { if (inputHelpPanel == null) { return false; } return true; } public void reInitHelpPanel(boolean forCAS) { if (inputHelpPanel != null) { if (forCAS) { app.getCommandDictionaryCAS(); } inputHelpPanel.setLabels(); } } @Override public Component getInputHelpPanel() { if (inputHelpPanel == null) { if (app.showView(App.VIEW_CAS)) { app.getCommandDictionaryCAS(); } inputHelpPanel = new InputBarHelpPanelD((AppD) app); } return inputHelpPanel; } public void setFocusedPanel(MouseEventND event, boolean updatePropertiesView) { // determine parent panel to change focus EuclidianDockPanelAbstract panel = (EuclidianDockPanelAbstract) SwingUtilities .getAncestorOfClass(EuclidianDockPanelAbstract.class, event.getComponent()); setFocusedPanel(panel, updatePropertiesView); } @Override public void setFocusedPanel(int viewId, boolean updatePropertiesView) { setFocusedPanel(getLayout().getDockManager().getPanel(viewId), updatePropertiesView); } public void setFocusedPanel(DockPanelD panel, boolean updatePropertiesView) { if (panel != null) { getLayout().getDockManager().setFocusedPanel(panel, updatePropertiesView); // notify the properties view if (updatePropertiesView) { updatePropertiesView(); } } } @Override public void updateAlgebraInput() { if (algebraInput != null) { algebraInput.initGUI(); } } @Override public void updatePropertiesView() { if (propertiesView != null) { propertiesView.updatePropertiesView(); } } /** * close properties view * */ @Override public void updatePropertiesViewStylebar() { if (propertiesView != null) { propertiesView.updateStyleBar(); } } @Override public void mouseReleasedForPropertiesView(boolean creatorMode) { if (propertiesView != null) { propertiesView.mouseReleasedForPropertiesView(creatorMode); } } @Override public void mousePressedForPropertiesView() { if (propertiesView != null) { propertiesView.mousePressedForPropertiesView(); } } @Override public void showPopupMenu(ArrayList<GeoElement> selectedGeos, EuclidianViewInterfaceCommon view, GPoint mouseLoc) { showPopupMenu(selectedGeos, ((EuclidianViewInterfaceD) view).getJPanel(), mouseLoc); } @Override public void showPopupChooseGeo(ArrayList<GeoElement> selectedGeos, ArrayList<GeoElement> geos, EuclidianViewInterfaceCommon view, GPoint p) { showPopupChooseGeo(selectedGeos, geos, (EuclidianView) view, p); } @Override public void setFocusedPanel(AbstractEvent event, boolean updatePropertiesView) { setFocusedPanel((MouseEventND) event, updatePropertiesView); } @Override public void loadImage(GeoPoint corner, Object transfer, boolean fromClipboard, EuclidianView ev) { loadImage(corner, fromClipboard, (Transferable) transfer, ev); } /** * Creates a new GeoImage, using an image provided by either a Transferable * object or the clipboard contents, then places it at the given location * (real world coords). If the transfer content is a list of images, then * multiple GeoImages will be created. * * @return whether a new image was created or not */ public boolean loadImage(GeoPoint corner, boolean fromClipboard, Transferable transfer, EuclidianView ev) { app.setWaitCursor(); String[] fileName = null; if (fromClipboard) { fileName = getImageFromTransferable(null); } else if (transfer != null) { fileName = getImageFromTransferable(transfer); } else { fileName = new String[1]; fileName[0] = getImageFromFile(); // opens file chooser dialog } boolean ret; if (fileName.length == 0 || fileName[0] == null) { ret = false; app.setMoveMode(); } else { // create GeoImage object(s) for this fileName GeoImage geoImage = null; if (fileName.length == 1) { geoImage = new GeoImage(app.getKernel().getConstruction()); geoImage.setImageFileName(fileName[0]); setImageCornersFromSelection(geoImage); app.setDefaultCursor(); return true; } if (!corner.isLabelSet()) { corner.setLabel(null); } for (int i = 0; i < fileName.length; i++) { GeoPoint point1; if (i == 0) { point1 = corner; } else { point1 = new GeoPoint(app.getKernel().getConstruction()); point1.setCoordsFromPoint(corner); point1.setLabel(null); } geoImage = new GeoImage(app.getKernel().getConstruction()); geoImage.setImageFileName(fileName[i]); // Log.debug("filename = " + fileName[i]); geoImage.setCorner(point1, 0); GeoPoint point2 = new GeoPoint( app.getKernel().getConstruction()); geoImage.calculateCornerPoint(point2, 2); geoImage.setCorner(point2, 1); point2.setLabel(null); // make sure 2nd corner is on screen double x1 = point1.inhomX; double x2 = point2.inhomX; double xmax = ev .toRealWorldCoordX((double) (ev.getWidth()) + 1); if (x2 > xmax) { point2.setCoords((x1 + 9 * xmax) / 10, point2.inhomY, 1); point2.update(); } geoImage.setLabel(null); GeoImage.updateInstances(app); } // make sure only the last image will be selected GeoElement[] geos = { geoImage }; app.getActiveEuclidianView().getEuclidianController() .clearSelections(); app.getActiveEuclidianView().getEuclidianController() .memorizeJustCreatedGeos(geos); ret = true; } app.setDefaultCursor(); return ret; } @Override public void showDrawingPadPopup(EuclidianViewInterfaceCommon view, GPoint mouseLoc) { showDrawingPadPopup(((EuclidianViewD) view).getJPanel(), mouseLoc); } @Override public void showDrawingPadPopup3D(EuclidianViewInterfaceCommon view, GPoint mouseLoc) { // 3D stuff } @Override public void showPropertiesViewSliderTab() { propertiesView.showSliderTab(); } @Override public void showGraphicExport() { app.getSelectionManager().clearSelectedGeos(true, false); app.updateSelection(false); JDialog d = new GraphicExportDialog((AppD) app); d.setVisible(true); } @Override public void showPSTricksExport() { GeoGebraToPstricks export = new GeoGebraToPstricksD(app); new PstricksFrame(export).setVisible(true); } @Override public void showWebpageExport() { app.getSelectionManager().clearSelectedGeos(true, false); app.updateSelection(false); WorksheetExportDialog d = new WorksheetExportDialog((AppD) app); d.setVisible(true); } @Override public void clearInputbar() { ((AlgebraInputD) getAlgebraInput()).clear(); } public int getInputHelpPanelMinimumWidth() { return getInputHelpPanel().getMinimumSize().width; } @Override public int getActiveToolbarId() { if (toolbarPanel == null) { return -1; } return toolbarPanel.getActiveToolbar(); } /** * Tells if the 3D View is shown in the current window * * @return whether 3D View is switched on */ public boolean is3DViewShown() { return menuBar.is3DViewShown(); } @Override public AppD getApp() { return (AppD) app; } @Override public void setToolBarDefinition(String toolBarDefinition) { strCustomToolbarDefinition = toolBarDefinition; } @Override public void clearAbsolutePanels() { // TODO Auto-generated method stub } @Override public boolean checkAutoCreateSliders(String s, AsyncOperation<String[]> callback) { Component comp = ((AppD) app).getMainComponent(); if (((AppD) app).getFrame() instanceof GeoGebraFrame) { GeoGebraFrame frame = (GeoGebraFrame) ((AppD) app).getFrame(); comp = frame != null && !frame.isIconified() ? frame : null; } Object[] options = { loc.getMenu("CreateSliders"), loc.getMenu("Cancel") }; int returnVal = JOptionPane.showOptionDialog(comp, loc.getPlain("CreateSlidersForA", s), loc.getMenu("CreateSliders"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, ((AppD) app).getModeIcon(EuclidianConstants.MODE_SLIDER), options, options[0]); if (callback != null) { Log.debug("callback" + returnVal); callback.callback(new String[] { returnVal == 0 ? AlgebraProcessor.CREATE_SLIDER : "0" }); } return false; } @Override public boolean belongsToToolCreator(ListCellRenderer renderer) { return ToolCreationDialogD.isMyCellRenderer(renderer); } @Override protected ConstructionProtocolNavigation newConstructionProtocolNavigation( int viewID) { ConstructionProtocolNavigationD cpn = new ConstructionProtocolNavigationD( this.getApp(), viewID); if (constructionProtocolView != null) { cpn.register(constructionProtocolView); } return cpn; } @Override public void login() { ((DialogManagerMinimal) app.getDialogManager()).showLogInDialog(); } @Override public void logout() { ((DialogManagerMinimal) app.getDialogManager()).showLogOutDialog(); } @Override public int getEuclidianViewCount() { return euclidianView2.size(); } @Override public void resetCasView() { if (casView != null) { casView.resetCursor(); } } @Override public boolean hasDataCollectionView() { // not available in desktop return false; } @Override public void getDataCollectionViewXML(StringBuilder sb, boolean asPreference) { // not available in desktop } @Override public String getToolImageURL(int mode, GeoImage gi) { String modeStr = StringUtil .toLowerCase(EuclidianConstants.getModeTextSimple(mode)); return ((AppD) app).getImageManager().createImage(((AppD) app) .getImageManager().getToolImageResource(modeStr), app); } @Override public EuclidianViewInterfaceCommon getPlotPanelEuclidanView() { return null; } @Override public void replaceInputSelection(String string) { JTextComponent textComponent = ((AlgebraInputD) getAlgebraInput()) .getTextField(); textComponent.replaceSelection(string); textComponent.requestFocusInWindow(); } @Override public void setInputText(String string) { JTextComponent textComponent = ((AlgebraInputD) getAlgebraInput()) .getTextField(); textComponent.setText(string); ((AlgebraInputD) getAlgebraInput()).setAutoInput(string); textComponent.requestFocusInWindow(); } }