/* * File : Identify.java * Created : 24-oct-2001 17:03 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2005 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * 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; either version 2 of the License, or * (at your option) any later version. * * This program 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 (see the LICENSE file). */ package edu.xtec.jclic.activities.text; import edu.xtec.jclic.*; import edu.xtec.jclic.media.EventSounds; import edu.xtec.jclic.project.JClicProject; import edu.xtec.util.Actions; import edu.xtec.util.JDomUtility; import java.awt.AWTEvent; import java.awt.event.*; import javax.swing.*; import javax.swing.text.*; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.09.16 */ public class Identify extends TextActivityBase { public static final int IDENTIFY_WORDS=0, IDENTIFY_CHARS=1; protected int type; //boolean evalOnTheFly; /** Creates new Identify */ public Identify(JClicProject project) { super(project); //evalOnTheFly=false; setType(IDENTIFY_WORDS); hasCheckButton=true; checkButtonText=""; } public static final String[] TYPES={"identifyWords", "identifyChars"}; @Override public org.jdom.Element getJDomElement(){ org.jdom.Element e=super.getJDomElement(); e.setAttribute(TYPE, TYPES[type]); return e; } @Override public void setProperties(org.jdom.Element e, Object aux) throws Exception{ super.setProperties(e, aux); //evalOnTheFly=!hasCheckButton; setType(JDomUtility.getStrIndexAttr(e, TYPE, TYPES, type)); } @Override public void setProperties(edu.xtec.jclic.clic3.Clic3Activity c3a) throws Exception{ super.setProperties(c3a); setType(c3a.puzMode==edu.xtec.jclic.clic3.Clic3.IDPARAULES ? IDENTIFY_WORDS : IDENTIFY_CHARS); //evalOnTheFly=!hasCheckButton; //evalOnTheFly=c3a.avCont; //if(evalOnTheFly) // hasCheckButton=false; } @Override public Activity.Panel getActivityPanel(PlayStation ps) { return new Panel(ps); } /** Getter for property type. * @return Value of property type. */ public int getType() { return type; } /** Setter for property type. * @param type New value of property type. */ public void setType(int type) { this.type = (type==IDENTIFY_CHARS ? IDENTIFY_CHARS : IDENTIFY_WORDS); tad.setTargetType(type==IDENTIFY_CHARS ? TextActivityDocument.TT_CHAR : TextActivityDocument.TT_WORD); } class Panel extends TextActivityBase.Panel { TextActivityDocument playDoc; int nActions; int score; boolean[] validChars; boolean[] marks; boolean[] targets; protected Panel(PlayStation ps){ super(ps); playDoc=null; nActions=0; score=0; validChars=null; marks=null; targets=null; } @Override protected void initDocument() throws Exception{ if(tad!=null){ playing=false; playDoc=new TextActivityDocument(styleContext); tad.cloneDoc(playDoc, false, false, true); if(!buildCheckArrays()) return; pane.setStyledDocument(playDoc); playDoc.attachTo(pane, Identify.Panel.this); pane.setEditable(false); pane.requestFocus(); nActions=0; score=0; } } private boolean buildCheckArrays(){ if(playDoc==null) return false; int l=playDoc.getLength(); if(l>0){ char[] chars; try{ chars=playDoc.getText(0, l).toCharArray(); } catch(BadLocationException ex){ playDoc=null; return false; } validChars=new boolean[l]; marks=new boolean[l]; targets=new boolean[l]; for(int i=0; i<l; i++){ marks[i]=false; targets[i]=false; validChars[i]=Character.isLetterOrDigit(chars[i]); } for(int i=0; i<playDoc.tmb.size(); i++){ TargetMarker tm=playDoc.tmb.getElement(i); for(int j=tm.begOffset; j<tm.endOffset; j++) targets[j]=true; } } else{ validChars=new boolean[1]; marks=new boolean[1]; targets=new boolean[1]; } return true; } @Override protected TextActivityPane buildPane(){ //IdentifyPane p=new IdentifyPane(this); IdentifyPane p=new IdentifyPane(); p.setActions(); return p; } class IdentifyPane extends TextActivityPane{ //public IdentifyPane(Identify act){ protected IdentifyPane(){ super(Identify.Panel.this); enableEvents(AWTEvent.MOUSE_EVENT_MASK); } @Override public boolean processMouse(MouseEvent e){ if(!super.processMouse(e) || !playing || playDoc==null) return false; if(e.getID()==MouseEvent.MOUSE_PRESSED) select(viewToModel(e.getPoint())); return false; } protected void select(int p){ if(p<0 || p>=marks.length){ playEvent(EventSounds.ACTION_ERROR); return; } nActions++; boolean marked=marks[p]; int l=1; TargetMarker tm=playDoc.tmb.getElementByOffset(p, false); if(tm!=null){ p=tm.begOffset; l=tm.getLength(); } else{ if(!validChars[p]){ playEvent(EventSounds.ACTION_ERROR); return; } if(type==IDENTIFY_WORDS){ int it=p; while(it>0 && validChars[it]==true) it--; int p0=it+1; it=p; p=p0; while(it<validChars.length && validChars[it]==true) it++; l=it-p0; } } playDoc.setCharacterAttributes(p, l, styleContext.getStyle(marked ? StyleContext.DEFAULT_STYLE : TextActivityDocument.TARGET), true); for(int i=0; i<l; i++) marks[p+i]=!marked; //if(evalOnTheFly){ if(!hasCheckButton){ TargetMarkerBag tmb=playDoc.tmb; boolean ok=(tm!=null && marks[p]==true); boolean finishedOk=checkScore(); try{ tabp.ps.reportNewAction(Identify.this, ACTION_SELECT, playDoc.getText(p, l), (marked ? "true":"false"), ok, score); } catch(Exception ex){ // should never done } if(finishedOk){ finishActivity(true); return; } } playEvent(EventSounds.CLICK); } protected void setActions(){ java.util.Map<String, Object[]> actionKeys=Actions.getActionKeys(this); ActionMap am=new ActionMap(); am.setParent(getActionMap()); setActionMap(am); //Originals: Actions.mapTraceAction(this, actionKeys, DefaultEditorKit.beepAction); Actions.mapTraceAction(this, actionKeys, "requestFocus"); Actions.mapTraceAction(this, actionKeys, "toggle-componentOrientation"); am.setParent(null); } } protected boolean checkScore(){ score=0; for(int i=0; i<playDoc.tmb.size(); i++){ if(marks[playDoc.tmb.getElement(i).begOffset]==true) score++; } for(int i=0; i<targets.length; i++) if(marks[i] && !targets[i]) return false; return (score==playDoc.tmb.size()); } @Override protected void doCheck(boolean fromButton){ if(playDoc==null || playDoc.tmb.size()==0) return; TargetMarkerBag tmb=playDoc.tmb; int i, j; playDoc.setCharacterAttributes(0, marks.length, styleContext.getStyle(StyleContext.DEFAULT_STYLE), true); for(i=0; i<marks.length; i++){ if(marks[i]){ for(j=i; j<marks.length; j++) if(!marks[j]) break; playDoc.setCharacterAttributes(i, j-i, styleContext.getStyle(TextActivityDocument.TARGET_ERROR), true); i=j; } } for(i=0; i<tmb.size(); i++){ TargetMarker tm=tmb.getElement(i); playDoc.applyStyleToTarget(tm, marks[tm.begOffset] ? TextActivityDocument.TARGET : StyleContext.DEFAULT_STYLE, false, true); } boolean finishedOk=checkScore(); ps.setCounterValue(SCORE_COUNTER, score); ps.setCounterValue(ACTIONS_COUNTER, nActions); if(!finishedOk){ if(fromButton){ playEvent(EventSounds.FINISHED_ERROR); pane.requestFocus(); } } else finishActivity(true); } @Override public void finishActivity(boolean result){ pane.setEnabled(false); super.finishActivity(result); } } }