/* This file is part of leafdigital leafChat. leafChat 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, either version 3 of the License, or (at your option) any later version. leafChat is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with leafChat. If not, see <http://www.gnu.org/licenses/>. Copyright 2012 Samuel Marshall. */ package com.leafdigital.scripting; import java.awt.Color; import org.w3c.dom.Element; import com.leafdigital.irc.api.UserCommandMsg; import com.leafdigital.ui.api.*; import util.xml.*; import leafchat.core.api.GeneralException; /** * Script item representing a /-command that the user can type directly. */ @UIHandler({"itemsettings.command"}) public class ItemCommand extends UserCodeItem { private String command, description = "(User script command)"; private static class Param { Class<?> c; String name; } private Param[] params; /** * Constructs from XML tag. * @param parent Parent script * @param e Element representing this item * @param index Index within script * @throws XMLException XML error * @throws GeneralException Other error */ public ItemCommand(Script parent,Element e,int index) throws XMLException,GeneralException { super(parent,e,index); command = XML.getRequiredAttribute(e,"name"); if(e.hasAttribute("description")) { description = e.getAttribute("description"); } Element[] paramElements=XML.getChildren(e,"param"); params=new Param[paramElements.length]; for(int i=0;i<paramElements.length;i++) { params[i]=new Param(); String type=XML.getRequiredAttribute(paramElements[i],"type"); if(type.equals("java.lang.String")) params[i].c=String.class; else if(type.equals("int")) params[i].c=int.class; else throw new GeneralException("Unexpected type= parameter for command item"); params[i].name=XML.getText(paramElements[i]); if(!params[i].name.matches("[A-Za-z][A-Za-z0-9_]*")) throw new GeneralException("Parameter name "+params[i].name+" invalid"); } } /** * Constructs blank item. * @param parent Parent script * @param index Index within script */ public ItemCommand(Script parent,int index) { super(parent,index); command="command"; params=new Param[0]; } @Override void save(Element e) { e.setAttribute("name", command); e.setAttribute("description", description); super.save(e); for(int i=0;i<params.length;i++) { Element param=XML.createChild(e,"param"); XML.setText(param,params[i].name); param.setAttribute("type",params[i].c.getName()); } } @Override String getSourceInit() { return "\t\tcontext.requestMessages(UserCommandMsg.class,new Item"+getIndex()+"(),\n" + "\t\t\tnew CommandFilter(\""+command+"\"),Msg.PRIORITY_NORMAL);\n" + "\t\tcontext.requestMessages(UserCommandListMsg.class,new Item"+getIndex()+"(),\n" + "\t\t\tMsg.PRIORITY_NORMAL);\n"; } @Override String getSourceMethods() { StringBuffer sb=new StringBuffer(); sb.append( "\tpublic class Item"+getIndex()+"\n"+ "\t{"+ "\t\tpublic void msg(UserCommandMsg msg)\n"+ "\t\t{\n"+ "\t\t\tmsg.markHandled();\n"+ "\t\t\t"+getContext().getMessageInfo(UserCommandMsg.class).getContextInit()+ "\n"+ "\t\t\tString params=msg.getParams();\n"); if(params.length>0) { sb.append("\t\t\tString INTERNAL_error=\"Expecting /"+command); for(int i=0;i<params.length;i++) { sb.append(" <"+params[i].name+">"); } sb.append("\";\n"); sb.append( "\t\t\tString[] INTERNAL_split=params.split(\"\\\\s+\","+params.length+");\n"+ "\t\t\tif(INTERNAL_split.length!="+params.length+")\n" + "\t\t\t{\n"+ "\t\t\t\tcommandDisplay.showError(\"Not enough parameters for command. \"+INTERNAL_error);\n"+ "\t\t\t\treturn;\n"+ "\t\t\t}\n"); for(int i=0;i<params.length;i++) { if(params[i].c==String.class) { sb.append( "\t\t\tString "+params[i].name+"=INTERNAL_split["+i+"];\n"); } else if(params[i].c==int.class) { sb.append( "\t\t\tint "+params[i].name+";\n"+ "\t\t\ttry\n"+ "\t\t\t{\n"+ "\t\t\t\t"+params[i].name+"=Integer.parseInt(INTERNAL_split["+i+"]);\n"+ "\t\t\t}\n"+ "\t\t\tcatch(NumberFormatException INTERNAL_e)\n"+ "\t\t\t{\n"+ "\t\t\t\tcommandDisplay.showError(\"Not a valid number for parameter "+ params[i].name+". \"+INTERNAL_error);\n"+ "\t\t\t\treturn;\n"+ "\t\t\t}\n"); } } } sb.append( convertUserCode()+"\n" + "\t\t}\n" + "\t\tpublic void msg(UserCommandListMsg msg)\n" + "\t\t{\n" + "\t\t\tmsg.addCommand(false, \"" + command + "\", UserCommandListMsg.FREQ_UNCOMMON, \"/" + command); for(int i=0; i<params.length; i++) { sb.append(" <" + params[i].name + ">"); } sb.append( "\", \"" + XML.esc(description) + "\");\n" + "\t\t}\n" + "\t}\n"); return sb.toString(); } @Override protected String getSummaryLabel() { StringBuffer sb=new StringBuffer("/<key>"+command+"</key>"); for(int i=0;i<params.length;i++) { sb.append(" <<key>"+params[i].name+"</key>>"); } return sb.toString(); } @Override public String getVariablesLabel() { StringBuffer sb=new StringBuffer("String <key>params</key>"); for(int i=0;i<params.length;i++) { sb.append(", "+params[i].c.getName().replaceFirst("^.*\\.","")+" <key>"+ params[i].name+"</key>"); } return sb.toString(); } @Override protected Color getNormalStripeRGB() { return new Color(0,128,0); } /** UI: Command edit */ public EditBox commandUI; /** UI: Description edit */ public EditBox descriptionUI; /** UI: type */ public Dropdown[] classUI; /** UI: name */ public EditBox[] nameUI; @Override protected Page getPage(Button ok) { Page p=super.getPage(ok); commandUI.setValue(command); descriptionUI.setValue(description); for(int i=0;i<classUI.length;i++) { classUI[i].addValue(null,"-"); classUI[i].addValue(String.class,"String"); classUI[i].addValue(int.class,"int"); if(params.length>i) { classUI[i].setSelected(params[i].c); nameUI[i].setValue(params[i].name); } } change(); return p; } /** * UI: Changed option */ @UIAction public void change() { boolean ok=commandUI.getFlag()==EditBox.FLAG_NORMAL; boolean hideAfter=false; for(int i=0;i<classUI.length;i++) { if(hideAfter) { classUI[i].setVisible(false); nameUI[i].setVisible(false); continue; } classUI[i].setVisible(true); nameUI[i].setVisible(true); if(classUI[i].getSelected()==null || nameUI[i].getValue().equals("")) { hideAfter=true; if(classUI[i].getSelected()!=null || !nameUI[i].getValue().equals("")) ok=false; } else { if(nameUI[i].getFlag()!=EditBox.FLAG_NORMAL) ok=false; } } allowOK(ok); } @Override protected void saveSettings() { String newCommand = commandUI.getValue(); if(!newCommand.equals(command)) { command = newCommand; markChanged(); } String newDescription = descriptionUI.getValue(); if(!newDescription.equals(description)) { description = newDescription; markChanged(); } int count=0; for(;count<classUI.length;count++) { if(classUI[count].getSelected()==null) break; } if(count==params.length) { boolean same=true; for(int i=0;i<params.length;i++) { if(!(params[i].c.equals(classUI[i].getSelected()) && params[i].name.equals(nameUI[i].getValue()))) { same=false; break; } } if(same) return; } params=new Param[count]; for(int i=0;i<params.length;i++) { params[i]=new Param(); params[i].c=(Class<?>)classUI[i].getSelected(); params[i].name=nameUI[i].getValue(); } markChanged(); } }