package org.basex.gui; import static org.basex.core.Text.ABOUT; import static org.basex.core.Text.BUTTONS; import static org.basex.core.Text.CHECK_FOR_UPDATES; import static org.basex.core.Text.CLOSE; import static org.basex.core.Text.COLORS; import static org.basex.core.Text.COMMUNITY; import static org.basex.core.Text.COMMUNITY_URL; import static org.basex.core.Text.COPY; import static org.basex.core.Text.COPY_PATH; import static org.basex.core.Text.CREATING_DB; import static org.basex.core.Text.DELETE; import static org.basex.core.Text.DELETE_NODES; import static org.basex.core.Text.DOC_URL; import static org.basex.core.Text.DOTS; import static org.basex.core.Text.EDIT; import static org.basex.core.Text.EDITOR; import static org.basex.core.Text.EXIT; import static org.basex.core.Text.EXPLORER; import static org.basex.core.Text.EXPORT_XML; import static org.basex.core.Text.FILES_REPLACE_X; import static org.basex.core.Text.FILE_EXISTS_X; import static org.basex.core.Text.FILTER_SELECTED; import static org.basex.core.Text.FOLDER; import static org.basex.core.Text.FONTS_D; import static org.basex.core.Text.FULLSCREEN; import static org.basex.core.Text.GO_BACK; import static org.basex.core.Text.GO_FORWARD; import static org.basex.core.Text.GO_HOME; import static org.basex.core.Text.GO_UP; import static org.basex.core.Text.HELP; import static org.basex.core.Text.H_ABOUT; import static org.basex.core.Text.H_BUTTONS; import static org.basex.core.Text.H_CLOSE; import static org.basex.core.Text.H_CLOSE_FILE; import static org.basex.core.Text.H_COLORS; import static org.basex.core.Text.H_COMMUNITY; import static org.basex.core.Text.H_COPY; import static org.basex.core.Text.H_CPPATH; import static org.basex.core.Text.H_DELETE; import static org.basex.core.Text.H_EDIT; import static org.basex.core.Text.H_EDITOR; import static org.basex.core.Text.H_EXIT; import static org.basex.core.Text.H_EXPLORER; import static org.basex.core.Text.H_EXPORT_XML; import static org.basex.core.Text.H_FILTER_SELECTED; import static org.basex.core.Text.H_FOLDER; import static org.basex.core.Text.H_FONTS; import static org.basex.core.Text.H_FULLSCREEN; import static org.basex.core.Text.H_GO_HOME; import static org.basex.core.Text.H_GO_UP; import static org.basex.core.Text.H_HELP; import static org.basex.core.Text.H_INPUT_BAR; import static org.basex.core.Text.H_MAP; import static org.basex.core.Text.H_MAP_LAYOUT; import static org.basex.core.Text.H_NEW; import static org.basex.core.Text.H_NEW_FILE; import static org.basex.core.Text.H_NEW_NODE; import static org.basex.core.Text.H_OPEN_FILE; import static org.basex.core.Text.H_OPEN_MANAGE; import static org.basex.core.Text.H_PASTE; import static org.basex.core.Text.H_PLOT; import static org.basex.core.Text.H_PREFERENCES; import static org.basex.core.Text.H_PROPERTIES; import static org.basex.core.Text.H_QUERY_INFO; import static org.basex.core.Text.H_RT_EXECUTION; import static org.basex.core.Text.H_RT_FILTERING; import static org.basex.core.Text.H_SAVE; import static org.basex.core.Text.H_STATUS_BAR; import static org.basex.core.Text.H_TABLE; import static org.basex.core.Text.H_TEXT; import static org.basex.core.Text.H_TREE; import static org.basex.core.Text.H_TREE_OPTIONS; import static org.basex.core.Text.H_UPDATES; import static org.basex.core.Text.INPUT_BAR; import static org.basex.core.Text.MAP; import static org.basex.core.Text.MAP_LAYOUT_D; import static org.basex.core.Text.NEW; import static org.basex.core.Text.NEW_DB_QUESTION; import static org.basex.core.Text.OPEN; import static org.basex.core.Text.OPEN_MANAGE; import static org.basex.core.Text.PASTE; import static org.basex.core.Text.PLOT; import static org.basex.core.Text.PREFERENCES; import static org.basex.core.Text.PROPERTIES; import static org.basex.core.Text.QUERY_INFO; import static org.basex.core.Text.RT_EXECUCTION; import static org.basex.core.Text.RT_FILTERING; import static org.basex.core.Text.SAVE; import static org.basex.core.Text.SAVE_AS; import static org.basex.core.Text.STATUS_BAR; import static org.basex.core.Text.S_H_SERVER_ADMIN; import static org.basex.core.Text.S_SERVER_ADMIN; import static org.basex.core.Text.TABLE; import static org.basex.core.Text.TEXT; import static org.basex.core.Text.TREE; import static org.basex.core.Text.TREE_OPTIONS_D; import static org.basex.core.Text.UPDATE_URL; import java.awt.BorderLayout; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import javax.swing.AbstractButton; import org.basex.core.Context; import org.basex.core.Prop; import org.basex.core.cmd.Close; import org.basex.core.cmd.CreateDB; import org.basex.core.cmd.Cs; import org.basex.core.cmd.Export; import org.basex.core.cmd.XQuery; import org.basex.data.Data; import org.basex.data.Nodes; import org.basex.gui.dialog.Dialog; import org.basex.gui.dialog.DialogAbout; import org.basex.gui.dialog.DialogColors; import org.basex.gui.dialog.DialogEdit; import org.basex.gui.dialog.DialogExport; import org.basex.gui.dialog.DialogFonts; import org.basex.gui.dialog.DialogInsert; import org.basex.gui.dialog.DialogManage; import org.basex.gui.dialog.DialogMapLayout; import org.basex.gui.dialog.DialogNew; import org.basex.gui.dialog.DialogPrefs; import org.basex.gui.dialog.DialogProgress; import org.basex.gui.dialog.DialogProps; import org.basex.gui.dialog.DialogServer; import org.basex.gui.dialog.DialogTreeOptions; import org.basex.gui.view.ViewData; import org.basex.io.IO; import org.basex.io.IOFile; import org.basex.query.func.Function; import org.basex.query.item.ANode; import org.basex.query.item.Int; import org.basex.query.item.NodeType; import org.basex.query.item.Str; import org.basex.util.Token; import org.basex.util.Util; import org.basex.util.list.IntList; import org.basex.util.list.StringList; /** * This enumeration encapsulates all commands that are triggered by * GUI operations. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public enum GUICommands implements GUICommand { /* DATABASE MENU */ /** Opens a dialog to create a new database. */ C_CREATE(NEW + DOTS, "% N", H_NEW, false, false) { @Override public void execute(final GUI gui) { // open file chooser for XML creation final DialogNew dialog = new DialogNew(gui); if(!dialog.ok()) return; final String in = gui.gprop.get(GUIProp.CREATEPATH); final String db = gui.gprop.get(GUIProp.CREATENAME); DialogProgress.execute(dialog, CREATING_DB, new CreateDB(db, in.isEmpty() ? null : in)); } }, /** Opens a dialog to manage databases. */ C_OPEN_MANAGE(OPEN_MANAGE + DOTS, "% O", H_OPEN_MANAGE, false, false) { @Override public void execute(final GUI gui) { if(new DialogManage(gui, true).nodb()) { if(Dialog.confirm(gui, NEW_DB_QUESTION)) C_CREATE.execute(gui); } } }, /** Shows database info. */ C_INFO(PROPERTIES + DOTS, "% D", H_PROPERTIES, true, false) { @Override public void execute(final GUI gui) { new DialogProps(gui); } }, /** Exports a database. */ C_EXPORT(EXPORT_XML + DOTS, null, H_EXPORT_XML, true, false) { @Override public void execute(final GUI gui) { final DialogExport dialog = new DialogExport(gui); if(!dialog.ok()) return; final IOFile root = new IOFile(dialog.path()); // check if existing files will be overwritten if(root.exists()) { IO file = null; boolean overwrite = false; final Data d = gui.context.data(); final IntList il = d.resources.docs(); for(int i = 0, is = il.size(); i < is; i++) { file = root.merge(Token.string(d.text(il.get(i), true))); if(file.exists()) { if(overwrite) { // more than one file will be overwritten; check remaining tests file = null; break; } overwrite = true; } } if(overwrite) { // show message for overwriting files or directories final String msg = file == null ? FILES_REPLACE_X : FILE_EXISTS_X; if(file == null) file = root; if(!Dialog.confirm(gui, Util.info(msg, file))) return; } } gui.execute(new Export(root.path())); } @Override public void refresh(final GUI gui, final AbstractButton b) { b.setEnabled(gui.context.data() != null && !gui.context.data().empty()); } }, /** Closes the database. */ C_CLOSE(CLOSE, "% W", H_CLOSE, true, false) { @Override public void execute(final GUI gui) { gui.execute(new Close()); } }, /** Server Dialog. */ C_SERVER(S_SERVER_ADMIN + DOTS, null, S_H_SERVER_ADMIN, false, false) { @Override public void execute(final GUI gui) { // open file chooser for XML creation new DialogServer(gui); } }, /** Opens a query file. */ C_EDITNEW(NEW + DOTS, "% shift N", H_NEW_FILE, false, false) { @Override public void execute(final GUI gui) { gui.editor.newFile(); } }, /** Opens a new editor file. */ C_EDITOPEN(OPEN + DOTS, "% R", H_OPEN_FILE, false, false) { @Override public void execute(final GUI gui) { gui.editor.open(); } }, /** Saves the current editor file. */ C_EDITSAVE(SAVE, "% S", H_SAVE, false, false) { @Override public void execute(final GUI gui) { gui.editor.save(); } @Override public void refresh(final GUI gui, final AbstractButton b) { b.setEnabled(gui.editor != null && gui.editor.saveable()); } }, /** Saves the current editor file under a new name. */ C_EDITSAVEAS(SAVE_AS + DOTS, "% shift S", H_SAVE, false, false) { @Override public void execute(final GUI gui) { gui.editor.saveAs(); } }, /** Closes the current editor file. */ C_EDITCLOSE(CLOSE, "% shift W", H_CLOSE_FILE, false, false) { @Override public void execute(final GUI gui) { gui.editor.close(null); } }, /** Exits the application. */ C_EXIT(EXIT, "% Q", H_EXIT, false, false) { @Override public void execute(final GUI gui) { gui.dispose(); } }, /* EDIT COMMANDS */ /** Copies the current path. */ C_COPYPATH(COPY_PATH, "% shift C", H_CPPATH, true, false) { @Override public void execute(final GUI gui) { final int pre = gui.context.marked.list[0]; final byte[] txt = ViewData.path(gui.context.data(), pre); // copy path to clipboard final Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); clip.setContents(new StringSelection(Token.string(txt)), null); } @Override public void refresh(final GUI gui, final AbstractButton b) { // disallow copy of empty node set or root node final Nodes marked = gui.context.marked; b.setEnabled(marked != null && marked.size() != 0); } }, /** Copies the currently marked nodes. */ C_COPY(COPY, "", H_COPY, true, false) { @Override public void execute(final GUI gui) { final Context ctx = gui.context; final Nodes n = ctx.marked; ctx.copied = new Nodes(n.list, n.data); } @Override public void refresh(final GUI gui, final AbstractButton b) { // disallow copy of empty node set or root node b.setEnabled(updatable(gui.context.marked)); } }, /** Pastes the copied nodes. */ C_PASTE(PASTE, "", H_PASTE, true, false) { @Override public void execute(final GUI gui) { final StringBuilder sb = new StringBuilder(); final Nodes n = gui.context.copied; for(int i = 0; i < n.size(); ++i) { if(i > 0) sb.append(','); sb.append(openPre(n, i)); } gui.context.copied = null; gui.execute(new XQuery("insert nodes (" + sb + ") into " + openPre(gui.context.marked, 0))); } @Override public void refresh(final GUI gui, final AbstractButton b) { final Context ctx = gui.context; // disallow copy of empty node set or root node b.setEnabled(updatable(ctx.marked, Data.DOC) && ctx.copied != null); } }, /** Deletes the currently marked nodes. */ C_DELETE(DELETE + DOTS, "", H_DELETE, true, false) { @Override public void execute(final GUI gui) { if(!Dialog.confirm(gui, DELETE_NODES)) return; final StringBuilder sb = new StringBuilder(); final Nodes n = gui.context.marked; for(int i = 0; i < n.size(); ++i) { if(i > 0) sb.append(','); sb.append(openPre(n, i)); } gui.context.marked = new Nodes(n.data); gui.context.copied = null; gui.context.focused = -1; gui.execute(new XQuery("delete nodes (" + sb + ')')); } @Override public void refresh(final GUI gui, final AbstractButton b) { // disallow deletion of empty node set or root node b.setEnabled(updatable(gui.context.marked)); } }, /** Inserts new nodes. */ C_INSERT(NEW + DOTS, "", H_NEW_NODE, true, false) { @Override public void execute(final GUI gui) { final Nodes n = gui.context.marked; final DialogInsert insert = new DialogInsert(gui); if(!insert.ok()) return; final StringList sl = insert.result; final NodeType type = ANode.type(insert.kind); String item = Token.string(type.string()) + " { " + quote(sl.get(0)) + " }"; if(type == NodeType.ATT || type == NodeType.PI) { item += " { " + quote(sl.get(1)) + " }"; } else if(type == NodeType.ELM) { item += " { () }"; } gui.context.copied = null; gui.execute(new XQuery("insert node " + item + " into " + openPre(n, 0))); } @Override public void refresh(final GUI gui, final AbstractButton b) { b.setEnabled(updatable(gui.context.marked, Data.ATTR, Data.PI, Data.COMM, Data.TEXT)); } }, /** Opens a dialog to edit the currently marked nodes. */ C_EDIT(EDIT + DOTS, "", H_EDIT, true, false) { @Override public void execute(final GUI gui) { final Nodes n = gui.context.marked; final DialogEdit edit = new DialogEdit(gui, n.list[0]); if(!edit.ok()) return; String rename = null; String replace = null; final int k = edit.kind; if(k == Data.ELEM || k == Data.PI || k == Data.ATTR) { rename = edit.result.get(0); if(k != Data.ELEM) replace = edit.result.get(1); } else { replace = edit.result.get(0); } if(rename != null) gui.execute(new XQuery("rename node " + openPre(n, 0) + " as " + quote(rename))); if(replace != null) gui.execute(new XQuery("replace value of node " + openPre(n, 0) + " with " + quote(replace))); } @Override public void refresh(final GUI gui, final AbstractButton b) { b.setEnabled(updatable(gui.context.marked, Data.DOC)); } }, /** Filters the currently marked nodes. */ C_FILTER(FILTER_SELECTED, "", H_FILTER_SELECTED, true, false) { @Override public void execute(final GUI gui) { final Context ctx = gui.context; Nodes marked = ctx.marked; if(marked.size() == 0) { final int pre = gui.context.focused; if(pre == -1) return; marked = new Nodes(pre, ctx.data()); } gui.notify.context(marked, false, null); } @Override public void refresh(final GUI gui, final AbstractButton b) { final Nodes marked = gui.context.marked; b.setEnabled(marked != null && marked.size() != 0); } }, /** Shows the XQuery view. */ C_SHOWEDITOR(EDITOR, "% E", H_EDITOR, false, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWEDITOR); gui.layoutViews(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWEDITOR)); } }, /** Shows info. */ C_SHOWINFO(QUERY_INFO, "% I", H_QUERY_INFO, false, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWINFO); gui.layoutViews(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWINFO)); } }, /* VIEW MENU */ /** Shows the buttons. */ C_SHOWBUTTONS(BUTTONS, null, H_BUTTONS, false, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWBUTTONS); gui.updateControl(gui.buttons, gui.gprop.is(GUIProp.SHOWBUTTONS), BorderLayout.CENTER); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWBUTTONS)); } }, /** Show Input Field. */ C_SHOWINPUT(INPUT_BAR, null, H_INPUT_BAR, false, true) { @Override public void execute(final GUI gui) { gui.updateControl(gui.nav, gui.gprop.invert(GUIProp.SHOWINPUT), BorderLayout.SOUTH); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWINPUT)); } }, /** Shows the status bar. */ C_SHOWSTATUS(STATUS_BAR, null, H_STATUS_BAR, false, true) { @Override public void execute(final GUI gui) { gui.updateControl(gui.status, gui.gprop.invert(GUIProp.SHOWSTATUS), BorderLayout.SOUTH); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWSTATUS)); } }, /** Shows the text view. */ C_SHOWTEXT(TEXT, "% 1", H_TEXT, false, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWTEXT); gui.layoutViews(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWTEXT)); } }, /** Shows the map. */ C_SHOWMAP(MAP, "% 2", H_MAP, true, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWMAP); gui.layoutViews(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWMAP)); } }, /** Shows the tree view. */ C_SHOWTREE(TREE, "% 3", H_TREE, true, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWTREE); gui.layoutViews(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWTREE)); } }, /** Shows the tree view. */ C_SHOWFOLDER(FOLDER, "% 4", H_FOLDER, true, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWFOLDER); gui.layoutViews(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWFOLDER)); } }, /** Shows the plot view. */ C_SHOWPLOT(PLOT, "% 5", H_PLOT, true, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWPLOT); gui.layoutViews(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWPLOT)); } }, /** Shows the table view. */ C_SHOWTABLE(TABLE, "% 6", H_TABLE, true, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWTABLE); gui.layoutViews(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWTABLE)); } }, /** Shows the explorer view. */ C_SHOWEXPLORE(EXPLORER, "% 7", H_EXPLORER, true, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.SHOWEXPLORE); gui.layoutViews(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.SHOWEXPLORE)); } }, /** Fullscreen mode. */ C_FULL(FULLSCREEN, Prop.MAC ? "% shift F" : "F11", H_FULLSCREEN, false, true) { @Override public void execute(final GUI gui) { gui.fullscreen(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.fullscreen); } }, /* OPTION MENU */ /** Realtime execution on/off. */ C_RTEXEC(RT_EXECUCTION, null, H_RT_EXECUTION, false, true) { @Override public void execute(final GUI gui) { gui.gprop.invert(GUIProp.EXECRT); gui.refreshControls(); gui.notify.layout(); } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.EXECRT)); } }, /** Realtime filtering on/off. */ C_RTFILTER(RT_FILTERING, null, H_RT_FILTERING, true, true) { @Override public void execute(final GUI gui) { final boolean rt = gui.gprop.invert(GUIProp.FILTERRT); gui.refreshControls(); gui.notify.layout(); final Context ctx = gui.context; final boolean root = ctx.root(); if(!rt) { if(!root) { gui.notify.context(new Nodes(0, ctx.data()), true, null); gui.notify.mark(ctx.current(), null); } } else { if(root) { gui.notify.mark(new Nodes(ctx.data()), null); } else { final Nodes mark = ctx.marked; ctx.marked = new Nodes(ctx.data()); gui.notify.context(mark, true, null); } } } @Override public void refresh(final GUI gui, final AbstractButton b) { super.refresh(gui, b); b.setSelected(gui.gprop.is(GUIProp.FILTERRT)); } }, /** Color schema. */ C_COLOR(COLORS + DOTS, null, H_COLORS, false, false) { @Override public void execute(final GUI gui) { new DialogColors(gui); } }, /** Changes the fonts. */ C_FONTS(FONTS_D, null, H_FONTS, false, false) { @Override public void execute(final GUI gui) { new DialogFonts(gui); } }, /** Map layout. */ C_MAPLAYOUT(MAP_LAYOUT_D, null, H_MAP_LAYOUT, true, false) { @Override public void execute(final GUI gui) { new DialogMapLayout(gui); } }, /** TreeView options. */ C_TREEOPTIONS(TREE_OPTIONS_D, null, H_TREE_OPTIONS, true, false) { @Override public void execute(final GUI gui) { new DialogTreeOptions(gui); } }, /** Shows a preference dialog. */ C_PREFS(PREFERENCES + DOTS, Prop.MAC ? "% COMMA" : "% P", H_PREFERENCES, false, false) { @Override public void execute(final GUI gui) { new DialogPrefs(gui); } }, /* HELP MENU */ /** Shows the documentation web page. */ C_HELP(HELP, "F1", H_HELP, false, false) { @Override public void execute(final GUI gui) { Dialog.browse(gui, DOC_URL); } }, /** Opens the community web page. */ C_COMMUNITY(COMMUNITY, null, H_COMMUNITY, false, false) { @Override public void execute(final GUI gui) { Dialog.browse(gui, COMMUNITY_URL); } }, /** Opens the update web page. */ C_UPDATES(CHECK_FOR_UPDATES, null, H_UPDATES, false, false) { @Override public void execute(final GUI gui) { Dialog.browse(gui, UPDATE_URL); } }, /** Shows the "about" information. */ C_ABOUT(ABOUT + DOTS, null, H_ABOUT, false, false) { @Override public void execute(final GUI gui) { new DialogAbout(gui); } }, /* BROWSE COMMANDS */ /** Goes one step back. */ C_GOBACK(GO_BACK, "alt LEFT", GO_BACK, true, false) { @Override public void execute(final GUI gui) { gui.notify.hist(false); } @Override public void refresh(final GUI gui, final AbstractButton b) { final String tt = gui.notify.tooltip(true); b.setEnabled(tt != null); b.setToolTipText(tt != null && tt.isEmpty() ? GO_BACK : tt); } }, /** Goes one step forward. */ C_GOFORWARD(GO_FORWARD, "alt RIGHT", GO_FORWARD, true, false) { @Override public void execute(final GUI gui) { gui.notify.hist(true); } @Override public void refresh(final GUI gui, final AbstractButton b) { final String tt = gui.notify.tooltip(false); b.setEnabled(tt != null); b.setToolTipText(tt != null && tt.isEmpty() ? GO_FORWARD : tt); } }, /** Goes one level up. */ C_GOUP(GO_UP, "alt UP", H_GO_UP, true, false) { @Override public void execute(final GUI gui) { // skip operation for root context final Context ctx = gui.context; if(ctx.root()) return; // check if all nodes are document nodes boolean doc = true; final Data data = ctx.data(); for(final int pre : ctx.current().list) doc &= data.kind(pre) == Data.DOC; if(doc) { // if yes, jump to database root ctx.update(); gui.notify.context(ctx.current(), false, null); } else { // otherwise, jump to parent nodes gui.execute(new Cs("..")); } } @Override public void refresh(final GUI gui, final AbstractButton b) { b.setEnabled(!gui.gprop.is(GUIProp.FILTERRT) && gui.context.data() != null && !gui.context.root()); } }, /** Goes to the root node. */ C_GOHOME(GO_HOME, "alt HOME", H_GO_HOME, true, false) { @Override public void execute(final GUI gui) { // skip operation for root context final Context ctx = gui.context; if(ctx.root()) return; // jump to database root ctx.update(); gui.notify.context(ctx.current(), false, null); } @Override public void refresh(final GUI gui, final AbstractButton b) { b.setEnabled(gui.context.data() != null && !gui.context.root()); } }, /** Displays the root node in the text view. */ C_HOME(GO_HOME, null, H_GO_HOME, true, false) { @Override public void execute(final GUI gui) { gui.execute(new XQuery("/")); } }; /** States if the command needs a data reference. */ private final boolean data; /** Menu entry. */ private final String entry; /** Key shortcut. */ private final String key; /** Help string. */ private final String help; /** Flag for commands that can be (un)checked. */ private final boolean checked; /** * Constructor. * @param e text of the menu item * @param k key shortcut * @param h help string * @param d data reference flag * @param c checked flag */ GUICommands(final String e, final String k, final String h, final boolean d, final boolean c) { entry = e; key = k; help = h; data = d; checked = c; } @Override public void refresh(final GUI gui, final AbstractButton b) { b.setEnabled(!data || gui.context.data() != null); } @Override public final boolean checked() { return checked; } @Override public String help() { return help; } @Override public String label() { return entry; } @Override public String key() { return key; } // STATIC METHODS =========================================================== /** * Checks if data can be updated. * @param n node instance * @param no disallowed node types * @return result of check */ static boolean updatable(final Nodes n, final int... no) { if(n == null || (no.length == 0 ? n.size() < 1 : n.size() != 1)) return false; final int k = n.data.kind(n.list[0]); for(final int i : no) if(k == i) return false; return true; } /** * Returns a quoted string. * @param s string to encode * @return quoted string */ static String quote(final String s) { return '"' + s.replaceAll("\"", """) + '"'; } /** * Returns a database function for the first node in a node set. * @param n node set * @param i offset * @return function string */ static String openPre(final Nodes n, final int i) { return Function._DB_OPEN_PRE.get(null, Str.get(n.data.meta.name), Int.get(n.list[i])).toString(); } }