/*
* File : WordSearch.java
* Created : 09-sep-2001 19:24
* 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.textGrid;
import edu.xtec.jclic.*;
import edu.xtec.jclic.automation.ActiveBagContentKit;
import edu.xtec.jclic.boxes.*;
import edu.xtec.jclic.media.EventSounds;
import edu.xtec.jclic.project.JClicProject;
import edu.xtec.util.JDomUtility;
import java.awt.*;
import java.awt.event.MouseEvent;
import javax.swing.JList;
import javax.swing.JScrollPane;
/**
*
* @author Francesc Busquets (fbusquets@xtec.cat)
* @version 13.09.10
*/
public class WordSearch extends Activity implements ActiveBagContentKit.Compatible{
String[] clues;
int [] clueItems;
/** Creates new WordSearch*/
public WordSearch(JClicProject project) {
super(project);
boxGridPos=AB;
abc=new ActiveBagContent[1];
clues=null;
clueItems=null;
}
@Override
public void initNew(){
super.initNew();
clues=new String[0];
clueItems=new int[0];
tgc=TextGridContent.initNew(3, 3, 'A');
}
@Override
public org.jdom.Element getJDomElement(){
org.jdom.Element ex, ex2;
if(clues==null || tgc==null) return null;
org.jdom.Element e=super.getJDomElement();
e.addContent(tgc.getJDomElement());
ex=new org.jdom.Element(CLUES);
for(int i=0; i<clues.length; i++){
ex2=new org.jdom.Element(CLUE);
ex2.setAttribute(ID, Integer.toString(clueItems[i]));
ex2.setText(clues[i]);
ex.addContent(ex2);
}
e.addContent(ex);
if(abc[0]!=null){
e.addContent(abc[0].getJDomElement().setAttribute(ID, SECONDARY));
ex=new org.jdom.Element(LAYOUT);
ex.setAttribute(POSITION, LAYOUT_NAMES[boxGridPos]);
e.addContent(ex);
if(scramble[0]){
ex=new org.jdom.Element(SCRAMBLE);
ex.setAttribute(TIMES, Integer.toString(shuffles));
ex.setAttribute(SECONDARY, JDomUtility.boolString(scramble[0]));
e.addContent(ex);
}
}
return e;
}
@Override
public void setProperties(org.jdom.Element e, Object aux) throws Exception{
org.jdom.Element child, child2;
super.setProperties(e, aux);
if((child=e.getChild(TextGridContent.ELEMENT_NAME))==null)
throw new IllegalArgumentException("WordSearch without TextGridContent!");
tgc=TextGridContent.getTextGridContent(child);
if((child=e.getChild(CLUES))==null)
throw new IllegalArgumentException("WordSearch without clues!");
java.util.List cluesList=child.getChildren(CLUE);
int numClues=cluesList.size();
clues=new String[numClues];
clueItems=new int[numClues];
for(int i=0; i<numClues; i++){
child2=((org.jdom.Element)cluesList.get(i));
clueItems[i]=JDomUtility.getIntAttr(child2, ID, i);
clues[i]=child2.getText();
}
child=e.getChild(ActiveBagContent.ELEMENT_NAME);
if(child!=null){
if(!SECONDARY.equals(child.getAttributeValue(ID)))
throw new IllegalArgumentException("WordSearch expects only \"secondary\" BagContent!");
abc[0]=ActiveBagContent.getActiveBagContent(child, project.mediaBag);
if((child=e.getChild(SCRAMBLE))!=null){
shuffles=JDomUtility.getIntAttr(child, TIMES, shuffles);
scramble[0]=JDomUtility.getBoolAttr(child, SECONDARY, scramble[0]);
}
else{
scramble[0]=false;
}
}
else abc[0]=null;
if((child=e.getChild(LAYOUT))!=null)
boxGridPos=JDomUtility.getStrIndexAttr(child, POSITION, LAYOUT_NAMES, boxGridPos);
}
@Override
public void setProperties(edu.xtec.jclic.clic3.Clic3Activity c3a) throws Exception{
super.setProperties(c3a);
boxGridPos=c3a.graPos;
tgc=new TextGridContent();
tgc.nch=c3a.nctxh;
tgc.ncw=c3a.nctxw;
tgc.w=c3a.txtCW;
tgc.h=c3a.txtCH;
tgc.border=c3a.delim[1];
tgc.text=c3a.graTxt;
clues=c3a.tags[0];
clueItems=new int[clues.length];
for(int i=0; i<clues.length; i++)
clueItems[i]=i;
tgc.bb=c3a.getBoxBase(0);
// read second grid
if(c3a.bar[0]){
// clic3 problem
c3a.txtCW=c3a.txtCW2;
c3a.txtCH=c3a.txtCH2;
// ---
abc[0]=c3a.createActiveBagContent(0);
abc[0].setBoxBase(c3a.getBoxBase(1));
}
else abc[0]=null;
}
public int getMinNumActions(){
return clues.length;
}
@Override
public boolean helpSolutionAllowed(){
return true;
}
@Override
public boolean hasRandom(){
return true;
}
public Activity.Panel getActivityPanel(PlayStation ps) {
return new Panel(ps);
}
/** Getter for property clues.
* @return Value of property clues.
*
*/
public String[] getClues() {
return clues;
}
/** Setter for property clues.
* @param cl New value of property "clues"
* @param clItems New value of property "clueItems"
*
*/
public void setClues(String[] cl, int[] clItems) {
clues = cl;
if(clues==null)
clues=new String[0];
clueItems=clItems;
if(clueItems==null || clueItems.length!=clues.length){
clueItems=new int[clues.length];
for(int i=0; i<clueItems.length; i++)
clueItems[i]=i;
}
}
class Panel extends Activity.Panel{
TextGrid grid;
ActiveBoxBag bgAlt;
boolean [] resolvedClues;
protected Panel(PlayStation ps){
super(ps);
bc=new BoxConnector(this);
resolvedClues=new boolean[clues.length];
grid=null;
bgAlt=null;
}
public void clear(){
if(grid!=null){grid.end();grid=null;}
if(bgAlt!=null){bgAlt.end();bgAlt=null;}
}
@Override
public void buildVisualComponents() throws Exception{
if(firstRun) super.buildVisualComponents();
clear();
if(acp!=null && abc!=null)
acp.generateContent(new ActiveBagContentKit(0, 0, abc, false), ps);
if(tgc!=null){
grid=TextGrid.createEmptyGrid(null, this, margin, margin, tgc, false);
//if(acp!=null) acp.generateContent(abc[0].nch, abc[0].ncw, abc, false, ac);
if(abc[0]!=null)
bgAlt=ActiveBoxGrid.createEmptyGrid(null, this, margin, margin, abc[0]);
grid.setVisible(true);
invalidate();
}
}
@Override
public void initActivity() throws Exception{
super.initActivity();
if(!firstRun) buildVisualComponents();
else firstRun=false;
setAndPlayMsg(MAIN, EventSounds.START);
//ps.setMsg(messages[MAIN]);
if(grid!=null){
grid.setChars(tgc.text);
grid.randomize();
grid.setAllCellsAttribute(TextGrid.INVERTED, false);
for(int i=0; i<clueItems.length; i++)
resolvedClues[i]=false;
if(bgAlt!=null){
bgAlt.setContent(abc[0]);
if(scramble[0])
shuffle(new ActiveBoxBag[]{bgAlt}, true, true);
bgAlt.setVisible(false);
}
//ps.playMsg();
//if(messages[MAIN]==null || messages[MAIN].mediaContent==null)
// playEvent(EventSounds.START);
playing=true;
}
}
public int getCurrentScore(){
int result=0;
if(clues!=null)
for(int i=0; i<clues.length; i++)
if(resolvedClues[i]) result++;
return result;
}
public void render(Graphics2D g2, Rectangle dirtyRegion) {
if(grid!=null) grid.update(g2, dirtyRegion, this);
if(bgAlt!=null) bgAlt.update(g2, dirtyRegion, this);
if(bc.active) bc.update(g2, dirtyRegion, this);
}
public Dimension setDimension(Dimension preferredMaxSize){
if(grid==null || getSize().equals(preferredMaxSize))
return preferredMaxSize;
if(bgAlt!=null)
return BoxBag.layoutDouble(preferredMaxSize, grid, bgAlt, boxGridPos, margin);
else
return BoxBag.layoutSingle(preferredMaxSize, grid, margin);
}
@Override
public void processMouse(MouseEvent e){
Point pt1, pt2;
Point p=e.getPoint();
boolean m=false;
if(playing) switch(e.getID()){
case MouseEvent.MOUSE_PRESSED:
ps.stopMedia(1);
if(bc.active){
bc.end();
pt1=grid.getLogicalCoords(bc.origin);
pt2=grid.getLogicalCoords(bc.dest);
if(pt1!=null && pt2!=null){
String s=grid.getStringBetween(pt1.x, pt1.y, pt2.x, pt2.y);
if(s!=null && s.length()>0){
boolean ok=false;
boolean repeated=false;
int c;
for(c=0; c<clues.length; c++)
if(s.equals(clues[c])) {ok=true; break;}
if(ok && !(repeated=resolvedClues[c])){
resolvedClues[c]=true;
grid.setAttributeBetween(pt1.x, pt1.y, pt2.x, pt2.y, TextGrid.INVERTED, true);
if(bgAlt!=null){
int k=clueItems[c];
if(k>=0 && k<bgAlt.getNumCells()){
//ActiveBox bx=bgAlt.getActiveBoxWithIdLoc(clueItems[c]);
ActiveBox bx=bgAlt.getActiveBox(clueItems[c]);
if(bx!=null){
bx.setVisible(true);
m=bx.playMedia(ps);
}
}
}
}
if(!repeated){
int r=getCurrentScore();
ps.reportNewAction(getActivity(), ACTION_SELECT, s, null, ok, r);
if(r==clues.length)
finishActivity(true);
else if(!m)
playEvent(ok ? EventSounds.ACTION_OK : EventSounds.ACTION_ERROR);
}
else if(!ok && !m)
playEvent(EventSounds.ACTION_ERROR);
}
else playEvent(EventSounds.ACTION_ERROR);
}
}
else{
if(grid.contains(p)){
playEvent(EventSounds.CLICK);
bc.begin(p);
}
}
break;
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
if(bc.active){
bc.moveTo(p);
}
break;
}
}
@Override
public void showHelp(){
if(!helpWindowAllowed() || grid==null) return;
HelpActivityComponent hac=null;
if(showSolution){
hac=new HelpActivityComponent(this){
JScrollPane scrollPane=null;
JList cluesList=null;
public void render(Graphics2D g2, Rectangle dirtyRegion){
// do nothing
}
@Override
public void init(){
cluesList=new JList(clues);
cluesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
cluesList.addListSelectionListener(this);
scrollPane=new JScrollPane(cluesList);
add(scrollPane);
Dimension size=grid.getBounds().getSize();
scrollPane.setBounds(DEFAULT_MARGIN, DEFAULT_MARGIN, size.width, size.height);
size.width+=2*DEFAULT_MARGIN;
size.height+=2*DEFAULT_MARGIN;
setPreferredSize(size);
setMaximumSize(size);
setMinimumSize(size);
Point p=(Point)getClientProperty(HelpActivityComponent.PREFERRED_LOCATION);
if(p!=null) p.translate((int)grid.x-DEFAULT_MARGIN, (int)grid.y-DEFAULT_MARGIN);
}
@Override
public void doLayout(){
Rectangle r=getBounds();
if(scrollPane!=null)
scrollPane.setBounds(DEFAULT_MARGIN, DEFAULT_MARGIN, r.width-2*DEFAULT_MARGIN, r.height-2*DEFAULT_MARGIN);
}
@Override
public void valueChanged(javax.swing.event.ListSelectionEvent ev) {
if(bgAlt!=null && !ev.getValueIsAdjusting()){
int i=cluesList.getSelectedIndex();
if(i<0){
unmarkBox();
} else{
playEvent(EventSounds.CLICK);
markBox(bgAlt.getActiveBox(clueItems[i]), true);
}
}
}
};
hac.init();
}
if(ps.showHelp(hac, helpMsg))
ps.reportNewAction(getActivity(), ACTION_HELP, null, null, false, getCurrentScore());
if(hac!=null)
hac.end();
}
}
}