package org.geogebra.common.euclidian.smallscreen; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.geogebra.common.euclidian.EuclidianView; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.geos.AbsoluteScreenLocateable; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoInputBox; import org.geogebra.common.kernel.geos.GeoNumeric; import org.geogebra.common.main.App; import org.geogebra.common.main.Feature; import org.geogebra.common.util.debug.Log; /** * Checks if the original screen was bigger when file was saved or not. If so, * some widgets needs to be adjusted to fit the smaller screen. * * @author laszlo * */ public class AdjustScreen { private static final int HSLIDER_OVERLAP_THRESOLD = 25; private static final int VSLIDER_OVERLAP_THRESOLD = 50; // private static final int BUTTON_Y_GAP = 10; private EuclidianView view; private App app; private Kernel kernel; private boolean enabled; private List<GeoNumeric> hSliders = new ArrayList<GeoNumeric>(); private List<GeoNumeric> vSliders = new ArrayList<GeoNumeric>(); private List<GeoInputBox> inputBoxes = new ArrayList<GeoInputBox>(); private LayoutAbsoluteGeos layoutAbsoluteGeos; private static class HSliderComparator implements Comparator<GeoNumeric> { protected HSliderComparator() { // avoid synthetic access warning } @Override public int compare(GeoNumeric o1, GeoNumeric o2) { double y1 = o1.getSliderY(); double y2 = o2.getSliderY(); if (y1 == y2) { return 0; } return Kernel.isGreater(y2, y1) ? -1 : 1; } } private static class VSliderComparator implements Comparator<GeoNumeric> { protected VSliderComparator() { // avoid synthetic access warning } @Override public int compare(GeoNumeric o1, GeoNumeric o2) { double x1 = o1.getSliderX(); double x2 = o2.getSliderX(); if (x1 == x2) { return 0; } return Kernel.isGreater(x2, x1) ? -1 : 1; } } // private static class ButtonComparator implements Comparator<GeoButton> { // public ButtonComparator() { // // TODO Auto-generated constructor stub // } // // @Override // public int compare(GeoButton o1, GeoButton o2) { // int y1 = o1.getAbsoluteScreenLocY(); // int y2 = o2.getAbsoluteScreenLocY(); // if (y1 == y2) { // return 0; // } // return Kernel.isGreater(y1, y2) ? 1 : -1; // } // } /** * @param view * view */ public AdjustScreen(EuclidianView view) { this.view = view; app = view.getApplication(); kernel = app.getKernel(); enabled = true;// needsAdjusting(); layoutAbsoluteGeos = new LayoutAbsoluteGeos(view); } /** * Remove old collection of buttons */ public void restartButtons() { layoutAbsoluteGeos.restart(); } /** * Collect widgets, ensures they are on the screen and does not overlap. * * @param reset * whether to reset buttons from original coords */ public void apply(boolean reset) { if (!enabled) { return; } if (reset) { reset(); } else { collectWidgets(); } checkOvelappingHSliders(); checkOvelappingVSliders(); layoutAbsoluteGeos.apply(); // checkOvelappingInputs(); view.repaintView(); } private void collectWidgets() { hSliders.clear(); vSliders.clear(); layoutAbsoluteGeos.clear(); inputBoxes.clear(); Log.debug("[AS] collectWidgets()"); for (GeoElement geo : kernel.getConstruction().getGeoTable().values()) { // boolean ensure = false; if (geo instanceof GeoNumeric) { GeoNumeric num = (GeoNumeric) geo; if (num.isSlider()) { if (num.isSliderHorizontal()) { hSliders.add(num); } else { vSliders.add(num); } // ensure = true; } } else if (layoutAbsoluteGeos.match(geo)) { // if (geo.isGeoInputBox()) { // Log.debug("[AS] collecting inputbox: " + geo); // GeoInputBox input = (GeoInputBox) geo; // inputBoxes.add(input); // // ensure = true; // } else { if (!layoutAbsoluteGeos.isCollected()) { AbsoluteScreenLocateable absGeo = (AbsoluteScreenLocateable) geo; layoutAbsoluteGeos.add(absGeo); } // } } // if (ensure) { // ensureGeoOnScreen(geo); // } } layoutAbsoluteGeos.setCollected(true); } /** * Reset buttons from original coords */ public void reset() { layoutAbsoluteGeos.reset(); } // private void ensureGeoOnScreen(GeoElement geo) { // if (!app.has(Feature.ADJUST_WIDGETS)) { // return; // } // Log.debug("[AS] ensureGeoOnScreen geo: " + geo); // // // AdjustWidget adjust = null; // // if (geo.isGeoNumeric()) { // // GeoNumeric number = (GeoNumeric) geo; // // if (number.isSlider()) { // // adjust = new AdjustSlider(number, view); // // } // // } else if (geo.isGeoButton()) { // // if (geo.isGeoInputBox()) { // // adjust = new AdjustInputBox((GeoInputBox) geo, view); // // } else { // // Log.debug("[AS] AdjustButton for " + geo); // // adjust = new AdjustButton((GeoButton) geo, view); // // } // // } // // // if (adjust != null) { // // adjust.apply(); // // view.update(geo); // // } // } private void checkOvelappingHSliders() { Collections.sort(hSliders, new HSliderComparator()); for (int idx = 0; idx < hSliders.size() - 1; idx++) { GeoNumeric slider1 = hSliders.get(idx); GeoNumeric slider2 = hSliders.get(idx + 1); Log.debug("[AS] :" + slider1 + " - " + slider2); double y1 = slider1.getSliderY(); double x2 = slider2.getSliderX(); double y2 = slider2.getSliderY(); if (y2 - y1 < HSLIDER_OVERLAP_THRESOLD) { Log.debug("[AS] HSLIDER adjusting " + slider2 + " to (" + x2 + ", " + (y1 + HSLIDER_OVERLAP_THRESOLD) + ")"); slider2.setSliderLocation(x2, y1 + HSLIDER_OVERLAP_THRESOLD, true); slider2.update(); } } if (hSliders.size() < 1) { return; } GeoNumeric lastSlider = hSliders.get(hSliders.size() - 1); int maxY = view.getViewHeight() - AdjustSlider.MARGIN_Y; if (lastSlider.getSliderY() > maxY) { double dY = lastSlider.getSliderY() - maxY; for (int idx = 0; idx < hSliders.size(); idx++) { GeoNumeric slider = hSliders.get(idx); slider.setSliderLocation(slider.getSliderX(), slider.getSliderY() - dY, true); } } } private void checkOvelappingVSliders() { Collections.sort(vSliders, new VSliderComparator()); for (int idx = 0; idx < vSliders.size() - 1; idx++) { GeoNumeric slider1 = vSliders.get(idx); GeoNumeric slider2 = vSliders.get(idx + 1); Log.debug("[AS] VSIDER:" + slider1 + " - " + slider2); double x1 = slider1.getSliderX(); double x2 = slider2.getSliderX(); double y2 = slider2.getSliderY(); if (x2 - x1 < VSLIDER_OVERLAP_THRESOLD) { slider2.setSliderLocation(x1 + VSLIDER_OVERLAP_THRESOLD, y2, true); slider2.update(); } } } // private static boolean isButtonsOverlap(GeoButton btn1, GeoButton btn2) { // GRectangle rect1 = // AwtFactory.getPrototype().newRectangle(btn1.getAbsoluteScreenLocX(), // btn1.getAbsoluteScreenLocY(), // btn1.getWidth(), btn1.getHeight()); // GRectangle rect2 = AwtFactory.getPrototype().newRectangle( // btn2.getAbsoluteScreenLocX(), btn2.getAbsoluteScreenLocY(), // btn2.getWidth(), btn2.getHeight()); // // return rect1.intersects(rect2) || rect2.intersects(rect1); // } // private void tileButtons(List<? extends GeoButton> buttonList) { // if (buttonList.size() < 1) { // return; // } // Collections.sort(buttonList, new ButtonComparator()); // // GeoButton last = buttonList.get(buttonList.size() - 1); // int lastBottom = last.getAbsoluteScreenLocY() + last.getHeight(); // // int maxBottom = view.getViewHeight() - AdjustButton.MARGIN_Y; // // Log.debug("[TILE] last: " + last.getLabelSimple() + " bottom: " // + lastBottom + " maxBottom: " + maxBottom); // if (lastBottom >= maxBottom) { // double dY = lastBottom - maxBottom; // for (int idx = 0; idx < buttonList.size(); idx++) { // GeoButton btn = buttonList.get(idx); // btn.setAbsoluteScreenLoc(btn.getAbsoluteScreenLocX(), // (int) (btn.getAbsoluteScreenLocY() - dY)); // btn.update(); // Log.debug("[TILE] " + btn.getLabelSimple() + " updatedt to (" // + btn.getAbsoluteScreenLocX() + ", " // + btn.getAbsoluteScreenLocY() + ")"); // // } // } // } // private void checkOverlappingInputs() { // Collections.sort(inputBoxes, new ButtonComparator()); // Log.debug("[AS] inputs:"); // for (int idx = 0; idx < inputBoxes.size() - 1; idx++) { // GeoInputBox input1 = inputBoxes.get(idx); // GeoInputBox input2 = inputBoxes.get(idx + 1); // DrawInputBox d1 = (DrawInputBox) view.getDrawableFor(input1); // DrawInputBox d2 = (DrawInputBox) view.getDrawableFor(input2); // if (d1 != null && d2 != null) { // GDimension t1 = d1.getTotalSize(); // GDimension t2 = d2.getTotalSize(); // // GRectangle rect1 = AwtFactory.getPrototype().newRectangle( // input1.getAbsoluteScreenLocX(), // input1.getAbsoluteScreenLocY(), t1.getWidth(), // t1.getHeight()); // GRectangle rect2 = AwtFactory.getPrototype().newRectangle( // input2.getAbsoluteScreenLocX(), // input2.getAbsoluteScreenLocY(), t2.getWidth(), // t2.getHeight()); // // boolean overlap = rect1.intersects(rect2) // || rect2.intersects(rect1); // // Log.debug("[AS] " + input1 + " - " + input2 + " overlaps: " // + overlap); // // if (overlap) { // input2.setAbsoluteScreenLoc(input2.getAbsoluteScreenLocX(), // input1.getAbsoluteScreenLocY() + t1.getHeight() // + BUTTON_Y_GAP); // input2.update(); // } // } // } // // tileButtons(inputBoxes); // // } /** * @return if the original screen was bigger so adjusting is needed. */ protected boolean needsAdjusting() { App viewApp = view.getApplication(); int fileWidth = viewApp.getSettings() .getEuclidian(view.getEuclidianViewNo()).getFileWidth(); int fileHeight = viewApp.getSettings() .getEuclidian(view.getEuclidianViewNo()).getFileHeight(); Log.debug("[AS] file: " + fileWidth + "x" + fileHeight); if (!viewApp.has(Feature.ADJUST_WIDGETS) || fileWidth == 0 || fileHeight == 0) { return false; } double w = viewApp.getWidth(); double h = viewApp.getHeight(); Log.debug("[AS] app: " + w + "x" + h); if ((w == fileWidth && h == fileHeight) || w == 0 || h == 0) { return false; } return true; } }