/*
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.desktop.gui.view.properties;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Rectangle;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import org.geogebra.common.euclidian.EuclidianConstants;
import org.geogebra.common.gui.SetLabels;
import org.geogebra.common.gui.view.properties.PropertiesStyleBar;
import org.geogebra.common.gui.view.properties.PropertiesView;
import org.geogebra.common.kernel.ModeSetter;
import org.geogebra.common.kernel.geos.GProperty;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.main.App;
import org.geogebra.common.main.OptionType;
import org.geogebra.common.util.debug.Log;
import org.geogebra.desktop.gui.GuiManagerD;
import org.geogebra.desktop.gui.dialog.options.OptionPanelD;
import org.geogebra.desktop.gui.dialog.options.OptionsAdvancedD;
import org.geogebra.desktop.gui.dialog.options.OptionsAlgebraD;
import org.geogebra.desktop.gui.dialog.options.OptionsCASD;
import org.geogebra.desktop.gui.dialog.options.OptionsDefaultsD;
import org.geogebra.desktop.gui.dialog.options.OptionsEuclidianD;
import org.geogebra.desktop.gui.dialog.options.OptionsLayoutD;
import org.geogebra.desktop.gui.dialog.options.OptionsObjectD;
import org.geogebra.desktop.gui.dialog.options.OptionsSpreadsheetD;
import org.geogebra.desktop.gui.layout.DockManagerD;
import org.geogebra.desktop.gui.layout.DockPanelD;
import org.geogebra.desktop.gui.layout.LayoutD;
import org.geogebra.desktop.gui.layout.panels.PropertiesDockPanel;
import org.geogebra.desktop.gui.view.spreadsheet.SpreadsheetViewD;
import org.geogebra.desktop.main.AppD;
import org.geogebra.desktop.util.GuiResourcesD;
/**
* View for properties
*
* @author mathieu
*/
public class PropertiesViewD extends PropertiesView implements SetLabels {
// private GeoTree geoTree;
private PropertiesStyleBarD styleBar;
private JPanel wrappedPanel;
// option panels
private OptionsDefaultsD defaultsPanel;
private OptionsEuclidianD euclidianPanel, euclidianPanel2;
private OptionsSpreadsheetD spreadsheetPanel;
private OptionsCASD casPanel;
private OptionsAdvancedD advancedPanel;
private OptionsLayoutD layoutPanel;
private OptionsAlgebraD algebraPanel;
private Object selectedOptionPanel = null;
// GUI elements
private JPanel mainPanel;
// private JButton restoreDefaultsButton, saveButton;
protected boolean isIniting = true;
/**************************************************
* Constructor
*
* @param app
*/
public PropertiesViewD(AppD app) {
super(app);
isIniting = true;
this.wrappedPanel = new JPanel();
app.setPropertiesView(this);
// init object properties
Log.debug("init object properties");
app.setWaitCursor();
getOptionPanel(OptionType.OBJECTS);
Log.debug("end (init object properties)");
// this.geoTree=geoTree;
initGUI();
setOptionPanel(selectedOptionType);
isIniting = false;
styleBar.getBtnOption().requestFocus();
setLabels();
app.setDefaultCursor();// remove this if init object properties is
// faster
}
// ============================================
// GUI
// ============================================
/** */
public void initGUI() {
wrappedPanel.setLayout(new BorderLayout());
getStyleBar();
mainPanel = new JPanel(new BorderLayout());
wrappedPanel.add(mainPanel, BorderLayout.CENTER);
wrappedPanel.add(Box.createVerticalGlue(), BorderLayout.SOUTH);
// createButtonPanel();
// add(buttonPanel, BorderLayout.SOUTH);
}
/*
* Creates the button panel for all option panels except the Object Panel
*
* private void createButtonPanel() {
*
* // panel with buttons at the bottom buttonPanel = new JPanel(new
* BorderLayout());
*
* buttonPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory
* .createMatteBorder(1, 0, 0, 0, SystemColor.controlLtHighlight),
* BorderFactory.createEmptyBorder(5, 0, 5, 0)));
*
* // buttonPanel.setBackground(Color.white);
*
* // (restore defaults on the left side) JPanel panel = new JPanel(new
* FlowLayout(FlowLayout.LEFT)); // panel.setBackground(Color.white);
*
* if (!app.isApplet()) { restoreDefaultsButton = new JButton();
* restoreDefaultsButton.addActionListener(new ActionListener() { public
* void actionPerformed(ActionEvent e) {
* GeoGebraPreferences.getPref().clearPreferences();
*
* // reset defaults for GUI, views etc // this has to be called before load
* XML preferences, // in order to avoid overwrite
* app.getSettings().resetSettings();
*
* // for geoelement defaults, this will do nothing, so it is // OK here
* GeoGebraPreferences.getPref().loadXMLPreferences(app);
*
* // reset default line thickness etc
* app.getKernel().getConstruction().getConstructionDefaults()
* .resetDefaults();
*
* // reset defaults for geoelements; this will create brand // new objects
* // so the options defaults dialog should be reset later
* app.getKernel().getConstruction().getConstructionDefaults()
* .createDefaultGeoElementsFromScratch();
*
* // reset the stylebar defaultGeo if
* (app.getEuclidianView1().hasStyleBar())
* app.getEuclidianView1().getStyleBar() .restoreDefaultGeo(); if
* (app.hasEuclidianView2EitherShowingOrNot()) if
* (app.getEuclidianView2().hasStyleBar())
* app.getEuclidianView2().getStyleBar() .restoreDefaultGeo();
*
* // restore dialog panels to display these defaults restoreDefaults();
*
* } });
*
* panel.add(restoreDefaultsButton); }
*
* buttonPanel.add(panel, app.borderWest());
*
*
* // (save and close on the right side) panel = new JPanel(new
* FlowLayout(FlowLayout.RIGHT)); // panel.setBackground(Color.white);
*
*
* if (!app.isApplet()) { saveButton = new JButton();
* saveButton.addActionListener(new ActionListener() { public void
* actionPerformed(ActionEvent e) {
* GeoGebraPreferences.getPref().saveXMLPreferences(app); } });
* panel.add(saveButton); }
*
*
* buttonPanel.add(panel, app.borderEast());
*
*
* }
*/
/**
* Restores default settings in option dialogs
*/
public void restoreDefaults() {
((OptionsDefaultsD) getOptionPanel(OptionType.DEFAULTS))
.restoreDefaults();
((OptionsAdvancedD) getOptionPanel(OptionType.ADVANCED))
.updateAfterReset();
// TODO
// --- add calls to other panels here
updateGUI();
}
// ============================================
// Updates
// ============================================
/**
* Updates properties view panel. If any geos are selected then the Objects
* panel will be shown. If not, then an option pane for the current focused
* view is shown. Called when a view gets the focus.
*/
@Override
public void updatePropertiesView() {
if (!isShowing()) {
return;
}
setOptionPanelRegardingFocus(false);
}
/**
* acts when mouse has been pressed in euclidian controller
*/
@Override
public void mousePressedForPropertiesView() {
getObjectPanel().forgetGeoAdded();
}
/**
* apply current panel modifications
*/
public void applyModifications() {
if (selectedOptionPanel != null) {
((OptionPanelD) selectedOptionPanel).applyModifications();
}
}
/**
* set the current panel selected/unselected
*
* @param isVisible
* visible
*/
public void setSelectedOptionPanelVisible(boolean isVisible) {
if (selectedOptionPanel != null) {
((OptionPanelD) selectedOptionPanel).setSelected(isVisible);
}
}
@Override
protected void setObjectsToolTip() {
styleBar.setObjectsToolTip();
}
@Override
protected void setOptionPanelWithoutCheck(OptionType type) {
// App.printStacktrace("\ntype="+type);
if (selectedOptionType != type && selectedOptionPanel != null) {
((OptionPanelD) selectedOptionPanel).applyModifications();
((OptionPanelD) selectedOptionPanel).setSelected(false);
}
if (!isIniting && selectedOptionType == type
&& type != OptionType.EUCLIDIAN_FOR_PLANE) {
updateTitleBar();
return;
}
selectedOptionType = type;
// clear the center panel and replace with selected option panel
mainPanel.removeAll();
selectedOptionPanel = getOptionPanel(type);
mainPanel.add(getOptionPanel(type).getWrappedPanel(),
BorderLayout.CENTER);
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
((OptionPanelD) selectedOptionPanel).setSelected(true);
((OptionPanelD) selectedOptionPanel).updateGUI();
((OptionPanelD) selectedOptionPanel).revalidate();
updateStyleBar();
updateTitleBar();
wrappedPanel.revalidate();
wrappedPanel.repaint();
}
public void updateGUI() {
if (defaultsPanel != null) {
defaultsPanel.updateGUI();
}
updateEuclidianPanelsGUI();
if (spreadsheetPanel != null) {
spreadsheetPanel.updateGUI();
}
if (casPanel != null) {
casPanel.updateGUI();
}
if (advancedPanel != null) {
advancedPanel.updateGUI();
}
if (layoutPanel != null) {
layoutPanel.updateGUI();
}
if (getObjectPanel() != null) {
((OptionsObjectD) getObjectPanel())
.setVisible(selectedOptionType == OptionType.OBJECTS);
}
setLabels();
}
/**
* update euclidian panels GUI
*/
public void updateEuclidianPanelsGUI() {
if (euclidianPanel != null) {
euclidianPanel.updateGUI();
}
if (euclidianPanel2 != null) {
euclidianPanel2.updateGUI();
}
}
/**
* update panel GUI
*
* @param id
* view id
*/
public void updatePanelGUI(int id) {
switch (id) {
default:
// do nothing
break;
case App.VIEW_EUCLIDIAN:
if (euclidianPanel != null) {
euclidianPanel.updateGUI();
}
break;
case App.VIEW_EUCLIDIAN2:
if (euclidianPanel2 != null) {
euclidianPanel2.updateGUI();
}
break;
case App.VIEW_SPREADSHEET:
if (spreadsheetPanel != null) {
spreadsheetPanel.updateGUI();
}
break;
case App.VIEW_CAS:
if (casPanel != null) {
casPanel.updateGUI();
}
break;
}
}
/**
* Returns the option panel for the given type. If the panel does not exist,
* a new one is constructed
*
* @param type
* @return
*/
public OptionPanelD getOptionPanel(OptionType type) {
// AbstractApplication.printStacktrace("type :"+type);
switch (type) {
case DEFAULTS:
if (defaultsPanel == null) {
defaultsPanel = new OptionsDefaultsD((AppD) app);
}
return defaultsPanel;
case CAS:
if (casPanel == null) {
casPanel = new OptionsCASD((AppD) app);
}
return casPanel;
case EUCLIDIAN:
if (euclidianPanel == null) {
euclidianPanel = new OptionsEuclidianD((AppD) app,
((AppD) app).getEuclidianView1());
euclidianPanel.setLabels();
// euclidianPanel.setView(((AppD) app).getEuclidianView1());
}
return euclidianPanel;
case EUCLIDIAN2:
if (euclidianPanel2 == null) {
euclidianPanel2 = new OptionsEuclidianD((AppD) app,
((AppD) app).getEuclidianView2(1));
euclidianPanel2.setLabels();
// euclidianPanel2.setView(((AppD) app).getEuclidianView2());
}
return euclidianPanel2;
case SPREADSHEET:
if (spreadsheetPanel == null) {
spreadsheetPanel = new OptionsSpreadsheetD((AppD) app,
(SpreadsheetViewD) app.getGuiManager()
.getSpreadsheetView());
}
return spreadsheetPanel;
case ADVANCED:
if (advancedPanel == null) {
advancedPanel = new OptionsAdvancedD((AppD) app);
}
return advancedPanel;
case LAYOUT:
if (layoutPanel == null) {
layoutPanel = new OptionsLayoutD((AppD) app);
}
return layoutPanel;
case OBJECTS:
if (getObjectPanel() == null) {
setObjectPanel(new OptionsObjectD((AppD) app));
((OptionsObjectD) getObjectPanel()).setMinimumSize(
((OptionsObjectD) getObjectPanel()).getPreferredSize());
}
return (OptionPanelD) getObjectPanel();
case ALGEBRA:
if (algebraPanel == null) {
algebraPanel = new OptionsAlgebraD((AppD) app);
}
return algebraPanel;
}
return null;
}
/**
* @return the style bar for this view.
*/
public PropertiesStyleBar getStyleBar() {
if (styleBar == null) {
styleBar = newPropertiesStyleBar();
}
return styleBar;
}
/**
*
* @return new properties style bar
*/
protected PropertiesStyleBarD newPropertiesStyleBar() {
return new PropertiesStyleBarD(this, (AppD) app);
}
/**
* Update the labels of the components (e.g. if the language changed).
*/
@Override
public void setLabels() {
if (defaultsPanel != null) {
defaultsPanel.setLabels();
}
if (euclidianPanel != null) {
euclidianPanel.setLabels();
}
if (euclidianPanel2 != null) {
euclidianPanel2.setLabels();
}
if (spreadsheetPanel != null) {
spreadsheetPanel.setLabels();
}
if (casPanel != null) {
casPanel.setLabels();
}
if (advancedPanel != null) {
advancedPanel.setLabels();
}
if (getObjectPanel() != null) {
((SetLabels) getObjectPanel()).setLabels();
}
if (layoutPanel != null) {
layoutPanel.setLabels();
}
updateStyleBar();
styleBar.setLabels();
updateTitleBar();
}
@Override
public void updateStyleBar() {
if (styleBar != null) {
styleBar.updateGUI();
}
}
@Override
protected void updateTitleBar() {
((LayoutD) app.getGuiManager().getLayout()).getDockManager()
.getPanel(App.VIEW_PROPERTIES).updateTitleBar();
}
// //////////////////////////////////////////////////////
// VIEW INTERFACE
// //////////////////////////////////////////////////////
@Override
public void attachView() {
if (isAttached()) {
Log.debug("already attached");
return;
}
clearView();
kernel.notifyAddAll(this);
kernel.attach(this);
setAttached(true);
}
@Override
public void detachView() {
kernel.detach(this);
clearView();
setAttached(false);
}
@Override
public void add(GeoElement geo) {
getObjectPanel().add(geo);
((OptionsObjectD) getObjectPanel()).getTree().add(geo);
styleBar.setObjectButtonEnable(true);
}
@Override
public void remove(GeoElement geo) {
// ((OptionsObjectD) objectPanel).updateIfInSelection(geo);
((OptionsObjectD) getObjectPanel()).getTree().remove(geo);
if (app.getKernel().isEmpty()) {
styleBar.setObjectButtonEnable(false);
}
}
@Override
public void rename(GeoElement geo) {
if (!isShowing()) {
return;
}
((OptionsObjectD) getObjectPanel()).rename(geo);
((OptionsObjectD) getObjectPanel()).getTree().rename(geo);
updateTitleBar();
}
@Override
public void update(GeoElement geo) {
if (!isShowing() || (!geo.isLabelSet() && !geo.isGeoCasCell())) {
return;
}
// updateSelection();
// propPanel.updateSelection(new GeoElement[] {geo});
((OptionsObjectD) getObjectPanel()).updateIfInSelection(geo);
((OptionsObjectD) getObjectPanel()).getTree().update(geo);
}
@Override
public void updateVisualStyle(GeoElement geo, GProperty prop) {
if (!isShowing() || (!geo.isLabelSet() && !geo.isGeoCasCell())) {
return;
}
((OptionsObjectD) getObjectPanel()).updateVisualStyle(geo);
((OptionsObjectD) getObjectPanel()).getTree().updateVisualStyle(geo, prop);
}
@Override
public void updateAuxiliaryObject(GeoElement geo) {
if (!isShowing()) {
return;
}
((OptionsObjectD) getObjectPanel()).updateIfInSelection(geo);
((OptionsObjectD) getObjectPanel()).getTree().updateAuxiliaryObject(geo);
}
@Override
public void repaintView() {
if (!isShowing()) {
return;
}
if (getObjectPanel() != null) {
((OptionsObjectD) getObjectPanel()).getTree().repaint();
}
}
@Override
public void reset() {
((OptionsObjectD) getObjectPanel()).getTree().repaint();
}
@Override
public void clearView() {
((OptionsObjectD) getObjectPanel()).getTree().clearView();
}
private int mode = EuclidianConstants.MODE_MOVE;
@Override
public void setMode(int mode, ModeSetter m) {
// on init, mode=-1
if (mode < 0) {
return;
}
if (mode == this.mode) {
return;
}
// close undocked properties view when setting mode
// if propreties view covers a part of the main window
DockManagerD manager = ((LayoutD) app.getGuiManager().getLayout())
.getDockManager();
DockPanelD panel = manager.getPanel(getViewID());
if (panel.isInFrame()) {
Rectangle panelRectangle = panel.getFrameBounds();
Rectangle mainWindowRectangle = ((AppD) app).getMainComponent()
.getBounds();
boolean outside = (panelRectangle.x > mainWindowRectangle.x
+ mainWindowRectangle.width)
|| (panelRectangle.x
+ panelRectangle.width < mainWindowRectangle.x)
|| (panelRectangle.y > mainWindowRectangle.y
+ mainWindowRectangle.height)
|| (panelRectangle.y
+ panelRectangle.height < mainWindowRectangle.y);
if (!outside) {
manager.closePanel(panel, false);
}
}
this.mode = mode;
}
@Override
public int getViewID() {
return App.VIEW_PROPERTIES;
}
// //////////////////////////////////////////////////////
// SELECTION
// //////////////////////////////////////////////////////
@Override
public void updateSelection() {
if (!isShowing()) {
return;
}
ArrayList<GeoElement> geos = app.getSelectionManager()
.getSelectedGeos();
if (geos.size() > 0) {
updateSelection(removeAllConstants(geos));
}
}
@Override
public void updateSelection(ArrayList<GeoElement> geos) {
if (geos.size() > 0) {
if (!stayInCurrentPanel()) {
setObjectPanel(geos);
}
} else {
setOptionPanelRegardingFocus(true);
}
}
private void setObjectPanel(ArrayList<GeoElement> geos) {
if (geos.size() == 0) {
app.getSelectionManager().setFirstGeoSelectedForPropertiesView();
GeoElement geo = app.getSelectionManager()
.setFirstGeoSelectedForPropertiesView();
if (geo == null) {
// if no first geo, close properties view if object panel
// visible
if (selectedOptionType == OptionType.OBJECTS) {
((LayoutD) app.getGuiManager().getLayout()).getDockManager()
.closePanel(getViewID(), false);
}
} else if (selectedOptionType != OptionType.OBJECTS) {
setOptionPanel(OptionType.OBJECTS);
}
} else if (selectedOptionType != OptionType.OBJECTS) {
setOptionPanel(OptionType.OBJECTS);
}
// always update selection for object panel
updateObjectPanelSelection(geos);
}
@Override
protected void updateObjectPanelSelection(ArrayList<GeoElement> geos) {
((OptionsObjectD) getObjectPanel()).updateSelection(geos);
updateTitleBar();
styleBar.setObjectsToolTip();
}
@Override
protected void setSelectedTab(OptionType type) {
switch (type) {
default:
// do nothing
break;
case EUCLIDIAN:
euclidianPanel.setSelectedTab(getSelectedTab());
break;
case EUCLIDIAN2:
euclidianPanel2.setSelectedTab(getSelectedTab());
break;
}
}
// //////////////////////////////////////////////////////
// FOR DOCK/UNDOCK PANEL
// //////////////////////////////////////////////////////
public void windowPanel() {
applyModifications();
((OptionsObjectD) getObjectPanel()).setGeoTreeVisible();
// kernel.attach(geoTree);
// kernel.notifyAddAll(geoTree);
// app.setSelectionListenerMode(this);
}
public void unwindowPanel() {
applyModifications();
((OptionsObjectD) getObjectPanel()).setGeoTreeNotVisible();
// kernel.detach(geoTree);
// geoTree.clear();
// app.setSelectionListenerMode(null);
}
public void closeDialog() {
wrappedPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
app.storeUndoInfo();
wrappedPanel.setCursor(Cursor.getDefaultCursor());
app.getGuiManager().setShowView(false, getViewID());
}
public void showSliderTab() {
selectedOptionType = OptionType.EUCLIDIAN;
setOptionPanel(OptionType.OBJECTS);
((OptionsObjectD) getObjectPanel()).showSliderTab();
styleBar.updateGUI();
updateGUI();
}
@Override
public boolean hasFocus() {
return wrappedPanel.hasFocus();
}
public JPanel getWrappedPanel() {
// TODO Auto-generated method stub
return wrappedPanel;
}
/**
* @param app
* @param type
* @return
*/
public static ImageIcon getTypeIcon(AppD app, OptionType type) {
switch (type) {
case DEFAULTS:
return app.getScaledIcon(GuiResourcesD.PROPERTIES_DEFAULTS_3);
case SPREADSHEET:
return app.getScaledIcon(GuiResourcesD.MENU_VIEW_SPREADSHEET);
case ALGEBRA:
return app.getScaledIcon(GuiResourcesD.MENU_VIEW_ALGEBRA);
case EUCLIDIAN:
return app.getScaledIcon(GuiResourcesD.MENU_VIEW_GRAPHICS);
case EUCLIDIAN2:
return app.getScaledIcon(GuiResourcesD.MENU_VIEW_GRAPHICS2);
case CAS:
return app.getScaledIcon(GuiResourcesD.MENU_VIEW_CAS);
case ADVANCED:
return app.getScaledIcon(GuiResourcesD.OPTIONS_ADVANCED_24);
case OBJECTS:
return app.getScaledIcon(GuiResourcesD.OPTIONS_OBJECTS_24);
case LAYOUT:
return app.getScaledIcon(GuiResourcesD.OPTIONS_LAYOUT_24);
case EUCLIDIAN3D:
return app.getScaledIcon(GuiResourcesD.MENU_VIEW_GRAPHICS3D);
case EUCLIDIAN_FOR_PLANE:
return app.getScaledIcon(GuiResourcesD.MENU_VIEW_GRAPHICS_EXTRA);
}
return null;
}
/**
* update fonts
*/
public void updateFonts() {
if (isIniting) {
return;
}
Font font = ((AppD) app).getPlainFont();
mainPanel.setFont(font);
if (defaultsPanel != null)
{
defaultsPanel.updateFont(); // tree + button
}
if (euclidianPanel != null)
{
euclidianPanel.updateFont(); //
}
if (euclidianPanel2 != null)
{
euclidianPanel2.updateFont(); //
}
if (spreadsheetPanel != null)
{
spreadsheetPanel.updateFont(); //
}
if (casPanel != null)
{
casPanel.updateFont(); //
}
if (advancedPanel != null)
{
advancedPanel.updateFont(); //
}
if (getObjectPanel() != null)
{
((OptionsObjectD) getObjectPanel()).updateFont(); // tree
}
if (layoutPanel != null)
{
layoutPanel.updateFont(); //
}
if (styleBar != null) {
styleBar.reinit();
}
// SwingUtilities.updateComponentTreeUI(mainPanel);
}
public void repaint() {
Log.debug("unimplemented");
}
@Override
public boolean isShowing() {
PropertiesDockPanel dockPanel = ((GuiManagerD) app.getGuiManager())
.getPropertiesDockPanel();
if (dockPanel == null) {
return false;
}
return dockPanel.isVisible();
}
/**
* @param geo
* GeoText to be updated
*/
public void updateTextEditor(GeoElement geo) {
if (getObjectPanel() != null) {
((OptionsObjectD) getObjectPanel()).updateTextEditor(geo);
}
}
@Override
public void setOptionPanel(OptionType type, int subType) {
setOptionPanel(type);
}
@Override
public boolean suggestRepaint() {
return false;
// only for web
}
}