/*
GeoGebra - Dynamic Mathematics for Everyone
http://www.geogebra.org
This file is part of GeoGebra.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation.
*/
package org.geogebra.common.gui.view.properties;
import java.util.ArrayList;
import java.util.HashMap;
import org.geogebra.common.gui.dialog.options.OptionsObject;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.View;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.main.App;
import org.geogebra.common.main.Localization;
import org.geogebra.common.main.OptionType;
import org.geogebra.common.util.debug.Log;
/**
* Properties view
*
*/
public abstract class PropertiesView implements View {
protected Kernel kernel;
private boolean attached;
protected App app;
protected final Localization loc;
protected OptionType selectedOptionType = OptionType.EUCLIDIAN;
private OptionsObject objectPanel;
protected int selectedTab = 0;
final private static HashMap<Integer, OptionType> viewMap = new HashMap<Integer, OptionType>();
// map to match view ID with OptionType
static {
viewMap.put(App.VIEW_CAS, OptionType.CAS);
viewMap.put(App.VIEW_SPREADSHEET, OptionType.SPREADSHEET);
viewMap.put(App.VIEW_EUCLIDIAN, OptionType.EUCLIDIAN);
viewMap.put(App.VIEW_EUCLIDIAN2, OptionType.EUCLIDIAN2);
viewMap.put(App.VIEW_EUCLIDIAN3D, OptionType.EUCLIDIAN3D);
viewMap.put(App.VIEW_EUCLIDIAN_FOR_PLANE_START,
OptionType.EUCLIDIAN_FOR_PLANE);
}
public PropertiesView(App app2) {
app = app2;
kernel = app.getKernel();
loc = app.getLocalization();
}
/**
* Update selection
*/
public abstract void updateSelection();
/**
* update the properties view as if geos where selected
*
* @param geos
* geos
*/
public abstract void updateSelection(ArrayList<GeoElement> geos);
/**
* Sets and shows the option panel for the given option type
*
* @param type
* type
*/
final public void setOptionPanel(OptionType type) {
ArrayList<GeoElement> geos = removeAllConstants(
app.getSelectionManager().getSelectedGeos());
if (type == OptionType.OBJECTS) {// ensure that at least one geo is
// selected
if (geos.size() == 0) {
GeoElement geo = app.getSelectionManager()
.setFirstGeoSelectedForPropertiesView();
if (geo == null) {
// does nothing: stay in same panel
return;
}
// add this first geo
geos.add(geo);
}
}
setOptionPanel(type, geos);
}
protected void setOptionPanel(OptionType type, ArrayList<GeoElement> geos) {
// App.printStacktrace("\ntype="+type+"\nisIniting="+isIniting);
// App.printStacktrace("\ntype="+type+"\nisIniting="+isIniting+"\nsize="+app.getSelectedGeos().size());
// Log.debug("\ntype="+type+"\nisIniting="+isIniting+"\nsize="+app.getSelectedGeos().size()+"\ngeos="+geos);
if (type == null) {
return;
}
// update selection
if (type == OptionType.OBJECTS) {
if (geos != null) {
updateObjectPanelSelection(geos);
}
setObjectsToolTip();
}
setOptionPanelWithoutCheck(type);
}
abstract protected void setObjectsToolTip();
abstract protected void updateObjectPanelSelection(
ArrayList<GeoElement> geos);
protected ArrayList<GeoElement> removeAllConstants(
ArrayList<GeoElement> geosList) {
Construction.Constants firstConstant = Construction.Constants.NOT;
// check if there is constants, remove it and remember what type
ArrayList<GeoElement> geos = new ArrayList<GeoElement>();
for (GeoElement geo : geosList) {
Construction.Constants constant = kernel.getConstruction()
.isConstantElement(geo);
if (constant == Construction.Constants.NOT) {
// add if not constant
geos.add(geo);
} else {
// remember type
if (firstConstant == Construction.Constants.NOT) {
firstConstant = constant;
}
}
}
if (firstConstant != Construction.Constants.NOT) {
updateSelectedTab(firstConstant);
}
return geos;
}
public abstract void setOptionPanel(OptionType type, int subType);
public abstract void mousePressedForPropertiesView();
public abstract void updatePropertiesView();
public abstract void detachView();
public abstract void attachView();
public String getTypeString(OptionType type) {
switch (type) {
case DEFAULTS:
return loc.getPlain("PreferencesOfA", loc.getPlain("Defaults"));
case SPREADSHEET:
return loc.getPlain("PreferencesOfA", loc.getPlain("Spreadsheet"));
case EUCLIDIAN:
return loc.getPlain("PreferencesOfA", loc.getPlain("DrawingPad"));
case EUCLIDIAN2:
return loc.getPlain("PreferencesOfA", loc.getPlain("DrawingPad2"));
case EUCLIDIAN_FOR_PLANE:
return loc.getPlain("PreferencesOfA", loc.getPlain("ExtraViews"));
case EUCLIDIAN3D:
return loc.getPlain("PreferencesOfA",
loc.getPlain("GraphicsView3D"));
case CAS:
return loc.getPlain("PreferencesOfA", loc.getPlain("CAS"));
case ADVANCED:
return loc.getPlain("PreferencesOfA", loc.getMenu("Advanced"));
case ALGEBRA:
return loc.getPlain("PreferencesOfA", loc.getPlain("Algebra"));
case OBJECTS:
return objectPanel == null ? loc.getMenu("Objects") : objectPanel
.getSelectionDescription(loc);
case LAYOUT:
return loc.getPlain("PreferencesOfA", loc.getMenu("Layout"));
}
return null;
}
/**
* @param loc
* @param type
* @return short version of Option type string
*/
final public static String getTypeStringSimple(Localization loc,
OptionType type) {
switch (type) {
case DEFAULTS:
return loc.getPlain("Defaults");
case SPREADSHEET:
return loc.getPlain("Spreadsheet");
case EUCLIDIAN:
return loc.getPlain("DrawingPad");
case EUCLIDIAN2:
return loc.getPlain("DrawingPad2");
case CAS:
return loc.getPlain("CAS");
case ADVANCED:
return loc.getMenu("Advanced");
case OBJECTS:
return loc.getMenu("Objects");
// return objectPanel.getSelectionDescription();
case LAYOUT:
return loc.getMenu("Layout");
case EUCLIDIAN3D:
return loc.getPlain("GraphicsView3D");
case EUCLIDIAN_FOR_PLANE:
return loc.getPlain("ExtraViews");
case ALGEBRA:
return loc.getPlain("Algebra");
default:
Log.error("missing case in getTypeStringSimple():" + type);
return null;
}
}
/**
* Updates the Title Bar
*/
protected abstract void updateTitleBar();
/**
* @return type of option panel currently displayed
*/
public OptionType getSelectedOptionType() {
return selectedOptionType;
}
/**
* @param app
* @param type
* Option panel type
* @return true if given Option panel is showing (or is instantiated but
* hidden)
*/
public static boolean isOptionPanelAvailable(App app, OptionType type) {
boolean isAvailable = true;
switch (type) {
case EUCLIDIAN:
isAvailable = app.getGuiManager().showView(App.VIEW_EUCLIDIAN);
break;
case EUCLIDIAN2:
isAvailable = app.getGuiManager().showView(App.VIEW_EUCLIDIAN2);
break;
case EUCLIDIAN_FOR_PLANE:
isAvailable = app.hasEuclidianViewForPlaneVisible();
break;
case EUCLIDIAN3D:
isAvailable = app.getGuiManager().showView(App.VIEW_EUCLIDIAN3D);
break;
case SPREADSHEET:
isAvailable = app.getGuiManager().showView(App.VIEW_SPREADSHEET);
break;
case CAS:
isAvailable = app.getGuiManager().showView(App.VIEW_CAS);
break;
case OBJECTS:
// always available
break;
}
return isAvailable;
}
@Override
public void startBatchUpdate() {
// TODO Auto-generated method stub
}
@Override
public void endBatchUpdate() {
// TODO Auto-generated method stub
}
/**
* acts when mouse has been released in euclidian controller
*
* @param creatorMode
* says if euclidian view is in creator mode (ie not move mode)
*/
public void mouseReleasedForPropertiesView(boolean creatorMode) {
GeoElement geo;
if (objectPanel == null) {
geo = null;
} else {
geo = objectPanel.consumeGeoAdded();
}
if (app.getSelectionManager().selectedGeosSize() > 0) {
// selected geo is the most important
updatePropertiesViewCheckConstants(
app.getSelectionManager().getSelectedGeos());
} else if (geo != null) { // last created geo
if (creatorMode) { // if euclidian view is e.g. in move mode, then
// geo was created by a script, so just show
// object properties
ArrayList<GeoElement> geos = new ArrayList<GeoElement>();
geos.add(geo);
setOptionPanel(OptionType.OBJECTS, geos);
} else {
setOptionPanel(OptionType.OBJECTS, null);
}
} else { // focus
updateSelectedTab(Construction.Constants.NOT);
setOptionPanelRegardingFocus(true);
// updatePropertiesView();
}
}
/**
* Updates properties view panel. If geos are not empty then the Objects
* panel will be shown. If not, then an option pane for the current focused
* view is shown.
*
* @param geosList
* geos list
*/
protected void updatePropertiesViewCheckConstants(
ArrayList<GeoElement> geosList) {
// remove constant geos
ArrayList<GeoElement> geos = removeAllConstants(geosList);
updatePropertiesView(geos);
}
private void updatePropertiesView(ArrayList<GeoElement> geos) {
if (geos.size() > 0) {
if (!stayInCurrentPanel()) {
setOptionPanel(OptionType.OBJECTS, geos);
}
} else {
setOptionPanelRegardingFocus(true);
}
}
/**
*
* @return currently focused view type
*/
protected OptionType getFocusedViewType() {
int focusedViewId = app.getGuiManager().getLayout().getDockManager()
.getFocusedViewId();
return getTypeFromFocusedViewId(focusedViewId);
}
final protected void setOptionPanelRegardingFocus(
boolean updateEuclidianTab) {
if (stayInCurrentPanelWithObjects()) {
return;
}
OptionType type = getFocusedViewType();
if (type != null) {
if (type == OptionType.EUCLIDIAN || type == OptionType.EUCLIDIAN2) {
if (app.getActiveEuclidianView().getEuclidianController()
.checkBoxOrTextfieldOrButtonJustHitted()) {
// hit check box or text field : does nothing
return;
}
// ev clicked
setOptionPanelWithoutCheck(type);
if (updateEuclidianTab) {
setSelectedTab(type);
}
} else {
setOptionPanel(type);
}
// here necessary no object is selected
updateObjectPanelSelection(
app.getSelectionManager().getSelectedGeos());
}
}
abstract protected void setSelectedTab(OptionType type);
protected void updateSelectedTab(Construction.Constants constant) {
switch (constant) {
case X_AXIS:
selectedTab = 1;
break;
case Y_AXIS:
selectedTab = 2;
break;
default:
selectedTab = 0;
break;
}
}
/**
* @return selected tab index
*/
protected int getSelectedTab() {
return selectedTab;
}
abstract protected void setOptionPanelWithoutCheck(OptionType type);
protected OptionType getTypeFromFocusedViewId(int id) {
switch (id) {
case App.VIEW_CAS:
return OptionType.CAS;
case App.VIEW_SPREADSHEET:
return OptionType.SPREADSHEET;
case App.VIEW_EUCLIDIAN:
return OptionType.EUCLIDIAN;
case App.VIEW_EUCLIDIAN2:
return OptionType.EUCLIDIAN2;
case App.VIEW_EUCLIDIAN3D:
return OptionType.EUCLIDIAN3D;
}
if (id >= App.VIEW_EUCLIDIAN_FOR_PLANE_START
&& id <= App.VIEW_EUCLIDIAN_FOR_PLANE_END) {
return OptionType.EUCLIDIAN_FOR_PLANE;
}
return null;
}
protected boolean stayInCurrentPanelWithObjects() {
return stayInCurrentPanel() || (selectedOptionType == OptionType.OBJECTS
&& app.getSelectionManager().getSelectedGeos().size() > 0);
}
/**
* say if it has to stay in current panel. Should disable any try to change
* panel, unless from stylebar buttons.
*/
protected boolean stayInCurrentPanel() {
return selectedOptionType == OptionType.DEFAULTS
|| selectedOptionType == OptionType.ADVANCED
|| selectedOptionType == OptionType.LAYOUT;
}
/**
* update style bar
*/
abstract public void updateStyleBar();
@Override
public void updatePreviewFromInputBar(GeoElement[] geos) {
// TODO
}
protected OptionsObject getObjectPanel() {
return objectPanel;
}
protected void setObjectPanel(OptionsObject objectPanel) {
this.objectPanel = objectPanel;
}
protected boolean isAttached() {
return attached;
}
protected void setAttached(boolean attached) {
this.attached = attached;
}
}