/*
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.toolbar;
import java.awt.Component;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.JToolBar;
import org.geogebra.common.euclidian.EuclidianConstants;
import org.geogebra.common.gui.layout.DockPanel;
import org.geogebra.common.gui.toolbar.ToolBar;
import org.geogebra.common.gui.toolbar.ToolbarItem;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.Macro;
import org.geogebra.common.util.debug.Log;
import org.geogebra.desktop.main.AppD;
/**
* Base class for a single toolbar, either for a dock panel or as a general
* toolbar. Toolbars are always visible as part of a ToolbarContainer.
*/
public class ToolbarD extends JToolBar {
private static final long serialVersionUID = 1L;
/**
* Instance of the application.
*/
private AppD app;
/**
* Dock panel associated to this toolbar or null if this is the general
* toolbar. Just a single toolbar might have no dock panel, otherwise the
* ToolbarContainer logic will not work properly.
*/
private DockPanel dockPanel;
/**
* The mode selected at the moment.
*/
private int mode;
private ArrayList<ModeToggleMenuD> modeToggleMenus;
/**
* Creates general toolbar.
*
* @param app
* application
*/
public ToolbarD(AppD app) {
this(app, null);
}
/**
* Creates toolbar for a specific dock panel. Call buildGui() to actually
* create the GUI of this toolbar.
*
* @param app
* application
* @param dockPanel
* dock panel
*/
public ToolbarD(AppD app, DockPanel dockPanel) {
this.app = app;
this.dockPanel = dockPanel;
setFloatable(false);
setBackground(getBackground());
// setLayout(new GridLayout(0, 2));
}
/**
* Creates a toolbar using the current strToolBarDefinition.
*/
public void buildGui() {
mode = -1;
ModeToggleButtonGroup bg = new ModeToggleButtonGroup();
modeToggleMenus = new ArrayList<ModeToggleMenuD>();
// create toolbar
removeAll();
// use specific layout for 3D inputs requiring huge GUI
if (app.useHugeGuiForInput3D()) {
setLayout(new GridLayout(0, 2));
}
setAlignmentX(LEFT_ALIGNMENT);
// add menus with modes to toolbar
addCustomModesToToolbar(bg);
setMode(app.getMode());
}
/**
* Sets toolbar mode. This will change the selected toolbar icon.
*
* @param newMode
* see EuclidianConstants for mode numbers
*
*
* @return actual mode number selected (might be different if it's not
* available)
*/
public int setMode(int newMode) {
boolean success = false;
int tmpMode = newMode;
// there is no special icon/button for the selection listener mode, use
// the
// move mode button instead
if (tmpMode == EuclidianConstants.MODE_SELECTION_LISTENER) {
tmpMode = EuclidianConstants.MODE_MOVE;
}
if (modeToggleMenus != null) {
for (int i = 0; i < modeToggleMenus.size(); i++) {
ModeToggleMenuD mtm = modeToggleMenus.get(i);
if (mtm.selectMode(tmpMode)) {
success = true;
break;
}
}
if (!success) {
int firstMode = getFirstMode();
// in case there are no tools!
if (firstMode > -1) {
mode = setMode(getFirstMode());
}
}
this.mode = tmpMode;
}
return tmpMode;
}
/**
* @return currently selected mode
*/
public int getSelectedMode() {
return mode;
}
/**
* @return first mode in this toolbar
*/
public int getFirstMode() {
if (modeToggleMenus == null || modeToggleMenus.size() == 0) {
return -1;
}
ModeToggleMenuD mtm = modeToggleMenus.get(0);
return mtm.getFirstMode();
}
/**
* Adds the given modes to a two-dimensional toolbar. The toolbar definition
* string looks like "0 , 1 2 | 3 4 5 || 7 8 9" where the int values are
* mode numbers, "," adds a separator within a menu, "|" starts a new menu
* and "||" adds a separator before starting a new menu.
*
* @param modes
* @param tb
* @param bg
*/
private void addCustomModesToToolbar(ModeToggleButtonGroup bg) {
Vector<ToolbarItem> toolbarVec;
try {
if (dockPanel != null) {
toolbarVec = ToolBar
.parseToolbarString(dockPanel.getToolbarString());
} else {
toolbarVec = ToolBar.parseToolbarString(
app.getGuiManager().getToolbarDefinition());
}
} catch (Exception e) {
if (dockPanel != null) {
Log.debug("invalid toolbar string: "
+ dockPanel.getToolbarString());
} else {
Log.debug("invalid toolbar string: "
+ app.getGuiManager().getToolbarDefinition());
}
toolbarVec = ToolBar.parseToolbarString(getDefaultToolbarString());
}
// set toolbar
boolean firstButton = true;
// make the loop go backwards for eg Hebrew / Arabic
int first = app.getLocalization().isRightToLeftReadingOrder()
? toolbarVec.size() - 1 : 0;
int increment = app.getLocalization().isRightToLeftReadingOrder() ? -1
: 1;
beginAdd();
// for (int i = 0; i < toolbarVec.size(); i++) {
for (int i = first; i >= 0 && i < toolbarVec.size(); i += increment) {
ToolbarItem ob = toolbarVec.get(i);
// new menu
Vector<Integer> menu = ob.getMenu();
ModeToggleMenuD tm = new ModeToggleMenuD(app, this, bg);
modeToggleMenus.add(tm);
for (int k = 0; k < menu.size(); k++) {
// separator
int addMode = menu.get(k).intValue();
if (addMode < 0) {
// separator within menu:
tm.addSeparator();
} else { // standard case: add mode
// check mode
if (!"".equals(app.getToolName(addMode))) {
tm.addMode(addMode);
if (i == 0 && firstButton) {
tm.getJToggleButton().setSelected(true);
firstButton = false;
}
}
}
}
if (tm.getToolsCount() > 0) {
add(tm);
}
}
endAdd();
}
private ArrayList<Component> componentsToAdd;
private void beginAdd() {
if (app.useHugeGuiForInput3D()) {
if (componentsToAdd == null) {
componentsToAdd = new ArrayList<Component>();
}
}
}
@Override
public Component add(Component c) {
if (app.useHugeGuiForInput3D()) {
componentsToAdd.add(c);
return c;
}
return super.add(c);
}
private void endAdd() {
if (app.useHugeGuiForInput3D()) {
int size = componentsToAdd.size();
int halfSize = size / 2;
for (int i = 0; i < halfSize; i++) {
super.add(componentsToAdd.get(i));
if (halfSize + i < size) {
super.add(componentsToAdd.get(halfSize + i));
}
}
componentsToAdd.clear();
}
}
/**
* @return The dock panel associated with this toolbar or null if this is
* the general toolbar.
*/
public DockPanel getDockPanel() {
return dockPanel;
}
/**
* @return The default definition of this toolbar with macros.
*/
public String getDefaultToolbarString() {
if (dockPanel != null) {
return dockPanel.getDefaultToolbarString();
}
return ToolbarD.getAllTools(app);
}
/**
* @param app
* application
* @return All tools as a toolbar definition string
*/
public static String getAllTools(AppD app) {
StringBuilder sb = new StringBuilder();
sb.append(ToolBar.getAllToolsNoMacros(false, false, app));
// macros
Kernel kernel = app.getKernel();
int macroNumber = kernel.getMacroNumber();
// check if at least one macro is shown
// to avoid strange GUI
boolean at_least_one_shown = false;
for (int i = 0; i < macroNumber; i++) {
Macro macro = kernel.getMacro(i);
if (macro.isShowInToolBar()) {
at_least_one_shown = true;
break;
}
}
if (macroNumber > 0 && at_least_one_shown) {
sb.append(" || ");
for (int i = 0; i < macroNumber; i++) {
Macro macro = kernel.getMacro(i);
if (macro.isShowInToolBar()) {
sb.append(i + EuclidianConstants.MACRO_MODE_ID_OFFSET);
sb.append(" ");
}
}
}
return sb.toString();
}
/**
* @return true when tooltips are suppressed
*/
protected boolean preventToolTipDelay() {
return !app.showToolBarHelp();
}
}