package org.geogebra.common.io.layout; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.geogebra.common.factories.AwtFactory; import org.geogebra.common.gui.Layout; import org.geogebra.common.kernel.StringTemplate; import org.geogebra.common.kernel.arithmetic.ExpressionNode; import org.geogebra.common.kernel.arithmetic.ExpressionValue; import org.geogebra.common.kernel.arithmetic.Variable; import org.geogebra.common.kernel.parser.ParseException; import org.geogebra.common.kernel.parser.Parser; import org.geogebra.common.main.App; import org.geogebra.common.main.App.InputPosition; import org.geogebra.common.plugin.Operation; import org.geogebra.common.util.debug.Log; /** * Helper class to convert strings like "CA/G" into perspectives * * @author Zbynek * */ public class PerspectiveDecoder { public static double landscapeRatio(double width) { if (width < 300) { return 2.0 / 3.0; } if (width < 600) { return 200 / width; } return 100 / width + 1 / 6.0; } private static Map<String, DockPanelData> viewCodes = new HashMap<String, DockPanelData>(); static { viewCodes .put("G", new DockPanelData(App.VIEW_EUCLIDIAN, null, true, false, false, AwtFactory.getPrototype() .newRectangle(100, 100, 600, 400), "1", 500)); viewCodes .put("A", new DockPanelData(App.VIEW_ALGEBRA, null, false, false, false, AwtFactory.getPrototype() .newRectangle(100, 100, 250, 400), "3,3", 200)); viewCodes .put("S", new DockPanelData(App.VIEW_SPREADSHEET, null, true, false, false, AwtFactory.getPrototype() .newRectangle(100, 100, 600, 400), "3", 300)); viewCodes .put("C", new DockPanelData(App.VIEW_CAS, null, false, false, false, AwtFactory.getPrototype() .newRectangle(100, 100, 600, 400), "3,1", 300)); viewCodes .put("P", new DockPanelData(App.VIEW_PROPERTIES, null, false, false, true, AwtFactory.getPrototype() .newRectangle(100, 100, 700, 550), "1,1", 400)); viewCodes .put("L", new DockPanelData(App.VIEW_CONSTRUCTION_PROTOCOL, null, false, false, true, AwtFactory.getPrototype() .newRectangle(100, 100, 700, 550), "1,1", 400)); viewCodes .put("D", new DockPanelData(App.VIEW_EUCLIDIAN2, null, false, false, true, AwtFactory.getPrototype() .newRectangle(100, 100, 700, 550), "1,1", 400)); viewCodes .put("T", new DockPanelData(App.VIEW_EUCLIDIAN3D, null, false, false, true, AwtFactory.getPrototype() .newRectangle(100, 100, 700, 550), "1,1", 400)); viewCodes .put("B", new DockPanelData(App.VIEW_PROBABILITY_CALCULATOR, null, false, false, true, AwtFactory.getPrototype() .newRectangle(100, 100, 700, 550), "1,1", 400)); viewCodes .put("R", new DockPanelData(App.VIEW_DATA_ANALYSIS, null, false, false, true, AwtFactory.getPrototype() .newRectangle(100, 100, 700, 550), "1,1", 400)); viewCodes .put("F", new DockPanelData(App.VIEW_FUNCTION_INSPECTOR, null, false, false, true, AwtFactory.getPrototype() .newRectangle(100, 100, 700, 550), "1,1", 400)); viewCodes .put("M", new DockPanelData(App.VIEW_DATA_COLLECTION, null, true, false, false, AwtFactory.getPrototype() .newRectangle(100, 100, 600, 400), "3", 300)); } /** * * @param code * views encoded as G,A,S,C,P,L,D,T * @param parser * parser * @param defToolbar * toolbar definition string * @return decoded perspective */ public static Perspective decode(String code, Parser parser, String defToolbar) { if (code.length() == 0 || code.startsWith("search:")) { return null; } for (int i = 1; i <= Layout.getDefaultPerspectivesLength(); i++) { if (code.equals(i + "")) { return Layout.getDefaultPerspectives(i - 1); } } StringBuilder longCode = new StringBuilder(); for (int i = 0; i < code.length(); i++) { longCode.append(code.charAt(i)); longCode.append(" "); } ExpressionValue expr; try { expr = parser.parseGeoGebraExpression(longCode.toString()).wrap(); } catch (ParseException e) { e.printStackTrace(); return null; } ArrayList<DockPanelData> panelList = new ArrayList<DockPanelData>(); ArrayList<DockSplitPaneData> splitList = new ArrayList<DockSplitPaneData>(); buildPerspective(expr.unwrap(), "", "", panelList, splitList, 1, 0.8); if (splitList.isEmpty()) { splitList.add(new DockSplitPaneData("", 1.0, 1)); } DockSplitPaneData[] spData = new DockSplitPaneData[splitList.size()]; splitList.toArray(spData); DockPanelData[] dpData = new DockPanelData[panelList.size()]; panelList.toArray(dpData); return new Perspective(0, spData, dpData, defToolbar, true, false, true, true, true, InputPosition.algebraView); } private static void buildPerspective(ExpressionValue expr, String panelPath, String splitPath, ArrayList<DockPanelData> panelList, ArrayList<DockSplitPaneData> splitList, double totalWidth, double totalHeight) { if (expr instanceof Variable) { String code = ((Variable) expr) .getName(StringTemplate.defaultTemplate); if (viewCodes.get(code) != null) { viewCodes.get(code).setVisible(true); viewCodes.get(code).setLocation( panelPath.length() > 0 ? panelPath.substring(1) : ""); panelList.add(viewCodes.get(code)); } } else if (expr instanceof ExpressionNode) { ExpressionNode en = (ExpressionNode) expr; boolean horizontal = ((ExpressionNode) expr) .getOperation() == Operation.MULTIPLY; double ratio = size(en.getLeft(), horizontal) / size(en, horizontal); double height1 = totalHeight; double width1 = totalWidth; double height2 = totalHeight; double width2 = totalWidth; if (horizontal) { width1 = width1 * ratio; width2 = width2 * (1 - ratio); } else { height1 = height1 * ratio; height2 = height2 * (1 - ratio); } splitList.add(new DockSplitPaneData( splitPath.length() > 0 ? splitPath.substring(1) : "", horizontal ? width1 : height1, horizontal ? 1 : 0)); buildPerspective(en.getRight().unwrap(), panelPath + (horizontal ? ",1" : ",2"), splitPath + ",1", panelList, splitList, width2, height2); buildPerspective(en.getLeft().unwrap(), panelPath + (horizontal ? ",3" : ",0"), splitPath + ",0", panelList, splitList, width1, height1); } else { Log.error("Wrong type" + expr.getValueType()); } } private static double size(ExpressionValue expr, boolean horizontal) { if (expr instanceof Variable && horizontal) { String name = ((Variable) expr) .getName(StringTemplate.defaultTemplate); if ("A".equals(name) || "C".equals(name)) { return 0.5; } } if (!(expr instanceof ExpressionNode)) { return 1; } ExpressionNode en = (ExpressionNode) expr; if (en.getOperation() != Operation.NO_OPERATION && en.getRight() != null) { return size(en.getLeft(), horizontal) + size(en.getRight(), horizontal); } return size(en.getLeft(), horizontal); } }