/* * File : TextActivitybase.java * Created : 28-may-2001 10:19 * 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.automation.TextActivityContentKit; import edu.xtec.jclic.boxes.*; import edu.xtec.jclic.media.EventSounds; import edu.xtec.jclic.project.JClicProject; import edu.xtec.util.JDomUtility; import edu.xtec.util.StrUtils; import java.awt.*; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JScrollPane; import javax.swing.text.*; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.08.28 */ public class TextActivityBase extends Activity implements TextActivityContentKit.Compatible { protected TextActivityDocument tad; protected StyleContext styleContext; //ActiveBagContent boxesContent; //ActiveBagContent popupsContent; protected boolean hasCheckButton; protected String checkButtonText; protected boolean prevScreen; protected int prevScreenMaxTime; protected String prevScreenText; protected BoxBase prevScreenStyle; // transient properties protected StyledDocument prevScreenDocument; /** Creates new TextActivityBase */ public TextActivityBase(JClicProject project) { super(project); styleContext=new StyleContext(); MutableAttributeSet mas=styleContext.getStyle(StyleContext.DEFAULT_STYLE); if(mas!=null){ StyleConstants.setFontFamily(mas, BoxBase.getDefaultFont().getFamily()); StyleConstants.setBackground(mas, Color.white); } tad=new TextActivityDocument(styleContext); hasCheckButton=false; checkButtonText=""; prevScreen=false; prevScreenMaxTime=0; prevScreenText=null; prevScreenDocument=null; prevScreenStyle=new BoxBase(); } public static final String CHECK_BUTTON="checkButton", PREV_SCREEN="prevScreen", TEXT="text"; @Override public org.jdom.Element getJDomElement(){ org.jdom.Element e=super.getJDomElement(); if(hasCheckButton) e.addContent(new org.jdom.Element(CHECK_BUTTON).setText(checkButtonText)); if(prevScreen){ org.jdom.Element child=new org.jdom.Element(PREV_SCREEN); if(prevScreenMaxTime>0) child.setAttribute(MAX_TIME, Integer.toString(prevScreenMaxTime)); if(prevScreenText!=null){ child.addContent(prevScreenStyle.getJDomElement()); JDomUtility.setParagraphs(child, prevScreenText); } e.addContent(child); } try{ e.addContent(tad.getJDomElement()); } catch(Exception ex){ System.err.println("Error getting document contents!"); return null; } return e; } @Override public void setProperties(org.jdom.Element e, Object aux) throws Exception{ org.jdom.Element child; super.setProperties(e, aux); if((child=e.getChild(CHECK_BUTTON))!=null){ hasCheckButton=true; checkButtonText=child.getText(); } if((child=e.getChild(PREV_SCREEN))!=null){ prevScreen=true; if((prevScreenText=JDomUtility.getParagraphs(child))!=null){ prevScreenStyle=BoxBase.getBoxBase(child.getChild(BoxBase.ELEMENT_NAME)); prevScreenDocument=new DefaultStyledDocument(); TextActivityDocument.boxBaseToStyledDocument(prevScreenStyle, prevScreenDocument); prevScreenDocument.insertString(0, prevScreenText, null); } prevScreenMaxTime=JDomUtility.getIntAttr(child, MAX_TIME, prevScreenMaxTime); } setTextActivityDocument(e.getChild(TextActivityDocument.ELEMENT_NAME)); } public void setTextActivityDocument(org.jdom.Element e) throws Exception{ tad=TextActivityDocument.getTextActivityDocument(e, this); } @Override public void setProperties(edu.xtec.jclic.clic3.Clic3Activity c3a) throws Exception{ super.setProperties(c3a); setWindowSize(new Dimension(c3a.txtCW, c3a.txtCH)); hasCheckButton=c3a.btCorregir; checkButtonText=c3a.txBtCorregir; if(c3a.avPrevHelp>0){ prevScreen=true; prevScreenMaxTime=c3a.avTimePH; if(c3a.avPrevHelp==2){ prevScreenText=c3a.txPrev; prevScreenStyle=c3a.getBoxBase(3); } messages[PREVIOUS]=new ActiveBoxContent(); messages[PREVIOUS].setBoxBase(messages[MAIN].bb); c3a.setActiveBoxTextContent(messages[PREVIOUS], c3a.initMessPrev); } tad.readClic3Data(c3a, this); } public void setStyleContext(StyleContext sc){ if(sc!=null){ try{ setTextActivityDocument(tad.getJDomElement(sc)); styleContext=sc; } catch(Exception ex){ System.err.println("Error updating document styles:\n"+ex); } } } public StyleContext getStyleContext(){ return styleContext; } protected Evaluator buildClic3Evaluator(edu.xtec.jclic.clic3.Clic3Activity c3a, boolean complex) throws Exception{ org.jdom.Element e=new org.jdom.Element(Evaluator.ELEMENT_NAME); String evaluatorClassName= complex ? ComplexEvaluator.class.getName() : BasicEvaluator.class.getName(); e.setAttribute(JDomUtility.CLASS, evaluatorClassName); e.setAttribute(BasicEvaluator.CHECK_CASE, JDomUtility.boolString(c3a.avMaj)); e.setAttribute(BasicEvaluator.CHECK_ACCENTS, JDomUtility.boolString(c3a.avAcc)); e.setAttribute(BasicEvaluator.CHECK_PUNCTUATION, JDomUtility.boolString(c3a.avPunt)); e.setAttribute(BasicEvaluator.CHECK_DOUBLE_SPACES, JDomUtility.boolString(c3a.avDblSpc)); if(complex){ e.setAttribute(ComplexEvaluator.DETAIL, JDomUtility.boolString(c3a.avLletra)); e.setAttribute(ComplexEvaluator.CHECK_STEPS, Integer.toString(c3a.avScope)); e.setAttribute(ComplexEvaluator.CHECK_SCOPE, Integer.toString(c3a.avMaxScope)); } return Evaluator.getEvaluator(e, c3a.project); } public int getMinNumActions(){ return (tad==null ? 0 : tad.tmb.size()); } @Override public boolean prepareMedia(PlayStation ps){ if(!super.prepareMedia(ps)) return false; //if(boxesContent!=null) boxesContent.prepareMedia(ac); //if(popupsContent!=null) popupsContent.prepareMedia(ac); if(tad!=null){ tad.boxesContent.prepareMedia(ps); tad.popupsContent.prepareMedia(ps); } return true; } @Override public boolean helpSolutionAllowed(){ return true; } public Activity.Panel getActivityPanel(PlayStation ps) { return new Panel(ps); } public class Panel extends Activity.Panel implements java.awt.event.ActionListener { JScrollPane scrollPane=null; JButton checkButton=null; TextActivityPane pane=null; boolean showingPrevScreen=false; javax.swing.Timer prevScreenTimer=null; TextTarget.PopupTimer popupTimer=null; protected Panel(PlayStation ps){ super(ps); popupTimer=new TextTarget.PopupTimer(this); } public void clear(){ if(prevScreenTimer!=null){ prevScreenTimer.stop(); prevScreenTimer=null; } } @Override public void doLayout(){ int w=getWidth(), h=getHeight(); if(checkButton!=null && checkButton.isVisible()){ int hb=checkButton.getPreferredSize().height; h-=hb; checkButton.setBounds(0, h, w, hb); } if(scrollPane!=null && pane!=null){ if(pane.getBounds().isEmpty()) pane.setBounds(0, 0, w, h); scrollPane.setBounds(0, 0, w, h); } } @Override public void buildVisualComponents() throws Exception{ super.buildVisualComponents(); if(acp!=null){ TextActivityContentKit kit=new TextActivityContentKit(tad, checkButtonText, prevScreenText); if(acp.generateContent(kit, ps)){ checkButtonText=kit.checkButtonText; prevScreenText=kit.prevScreenText; } } if(prevScreen==true && prevScreenText!=null){ prevScreenDocument=new DefaultStyledDocument(); TextActivityDocument.boxBaseToStyledDocument(prevScreenStyle, prevScreenDocument); try{ prevScreenDocument.insertString(0, prevScreenText, null); } catch (Exception e){ System.err.println("Error displaying initial screen:\n"+e); } } pane=buildPane(); scrollPane=new JScrollPane(pane); scrollPane.setBorder(BorderFactory.createEmptyBorder()); scrollPane.getVerticalScrollBar().setBorder(BorderFactory.createLineBorder(Color.darkGray, 1)); add(scrollPane); if(hasCheckButton){ checkButton=new JButton(StrUtils.secureString(checkButtonText, " ")); checkButton.setOpaque(false); checkButton.addActionListener(this); add(checkButton); } if(prevScreen && prevScreenMaxTime>0){ prevScreenTimer=new javax.swing.Timer(1000 * prevScreenMaxTime, this); prevScreenTimer.setRepeats(false); } } protected TextActivityPane buildPane(){ return new TextActivityPane(this); } @Override public void initActivity() throws Exception{ //super.initActivity(); if(prevScreen) preInitActivity(); else startActivity(); } @Override public void startActivity() throws Exception{ super.initActivity(); showingPrevScreen=false; //setCounters(0, 0, 0); setAndPlayMsg(MAIN, EventSounds.START); //ps.setMsg(messages[MAIN]); initDocument(); if(checkButton!=null) checkButton.setVisible(true); ps.playMsg(); //if(messages[MAIN]==null || messages[MAIN].mediaContent==null) // playEvent(EventSounds.START); pane.requestFocus(); playing=true; } public void preInitActivity(){ if(messages[PREVIOUS]==null || prevScreen==false) return; showingPrevScreen=true; if(checkButton!=null) checkButton.setVisible(false); enableCounters(true, false, false); ps.setCounterValue(TIME_COUNTER, 0); ps.setMsg(messages[PREVIOUS]); pane.setEditable(false); pane.setStyledDocument(prevScreenDocument != null ? prevScreenDocument : tad); if(prevScreenTimer!=null){ ps.setCountDown(TIME_COUNTER, prevScreenMaxTime); prevScreenTimer.start(); } ps.playMsg(); } protected void initDocument() throws Exception{ if(tad!=null){ if(pane.getDocument()!=tad) pane.setStyledDocument(tad); //pane.setEditable(true); pane.setEnabled(true); } } public void render(Graphics2D g2, Rectangle dirtyRegion) { } @Override public void requestFocus(){ if(playing && pane!=null) pane.requestFocus(); } public Dimension setDimension(Dimension desiredMaxSize){ return new Dimension( Math.min(desiredMaxSize.width, getWindowSize().width), Math.min(desiredMaxSize.height, getWindowSize().height)); } @Override public void setCursor(Cursor cursor){ if(pane!=null) pane.setCursor(cursor); super.setCursor(cursor); } public void actionPerformed(java.awt.event.ActionEvent e) { if(checkButton!=null && e.getSource()==checkButton){ if(playing) doCheck(true); } if(prevScreenTimer!=null && e.getSource()==prevScreenTimer && showingPrevScreen){ ps.startActivity(this); } } @Override public void forceFinishActivity(){ if(playing) doCheck(false); } protected void doCheck(boolean fromButton){ } @Override public void showHelp(){ if(!helpWindowAllowed() || pane==null) return; HelpActivityComponent hac=null; if(showSolution){ hac=new HelpActivityComponent(this){ TextActivityPane tap=null; JScrollPane jsp=null; public void render(Graphics2D g2, Rectangle dirtyRegion){ } @Override public void init(){ tap=buildPane(); try{ // build new document tap.setStyledDocument(TextActivityDocument.getTextActivityDocument(tad.getJDomElement(), TextActivityBase.this)); } catch(Exception ex){ // reuse existing document (lost floating elements) tap.setStyledDocument(tad); } // Modified 04-Feb-2011 // Correction of bug #64: // Leave the component not editable but enabled: tap.setEditable(false); //tap.setEnabled(false); // ------------------- jsp=new JScrollPane(tap); jsp.setBorder(BorderFactory.createEmptyBorder()); jsp.getVerticalScrollBar().setBorder(BorderFactory.createLineBorder(Color.darkGray, 1)); add(jsp); Dimension size=scrollPane.getBounds().getSize(); jsp.setBounds(0, 0, size.width, size.height); if(tap.getBounds().isEmpty()) tap.setBounds(0, 0, size.width, size.height); setPreferredSize(size); setMaximumSize(size); setMinimumSize(size); } }; hac.init(); } if(ps.showHelp(hac, helpMsg)) ps.reportNewAction(getActivity(), ACTION_HELP, null, null, false, -1); if(hac!=null) hac.end(); } } public TextActivityDocument getDocument(){ return tad; } }