/* * File : DoublePuzzle.java * Created : 20-apr-2001 10:31 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2018 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.puzzles; 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; /** * @author Francesc Busquets ([email protected]) * @version 13.08.28 */ public class DoublePuzzle extends Activity implements ActiveBagContentKit.Compatible { /** Creates new DoublePuzzle */ public DoublePuzzle(JClicProject project) { super(project); abc = new ActiveBagContent[1]; boxGridPos = AB; dragCells = true; } @Override public void initNew() { super.initNew(); abc[0] = ActiveBagContent.initNew(3, 2, 'A'); } @Override public org.jdom.Element getJDomElement() { org.jdom.Element ex; if (abc[0] == null) return null; org.jdom.Element e = super.getJDomElement(); e.addContent(abc[0].getJDomElement()); ex = new org.jdom.Element(SCRAMBLE); ex.setAttribute(TIMES, Integer.toString(shuffles)); e.addContent(ex); ex = new org.jdom.Element(LAYOUT); ex.setAttribute(POSITION, LAYOUT_NAMES[boxGridPos]); e.addContent(ex); return e; } @Override public void setProperties(org.jdom.Element e, Object aux) throws Exception { org.jdom.Element child; super.setProperties(e, aux); child = e.getChild(ActiveBagContent.ELEMENT_NAME); if (child != null) abc[0] = ActiveBagContent.getActiveBagContent(child, project.mediaBag); if (abc[0] == null) throw new IllegalArgumentException("Puzzle without data!"); if ((child = e.getChild(SCRAMBLE)) != null) shuffles = JDomUtility.getIntAttr(child, TIMES, shuffles); 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); abc[0] = c3a.createActiveBagContent(0); boxGridPos = c3a.graPos; abc[0].setBoxBase(c3a.getBoxBase(0)); dragCells = true; } public int getMinNumActions() { if (abc[0] == null) return 0; return abc[0].getNumCells(); } @Override public boolean hasRandom() { return true; } @Override public boolean shuffleAlways() { return true; } @Override public boolean helpSolutionAllowed() { return true; } public Activity.Panel getActivityPanel(PlayStation ps) { return new Panel(ps); } class Panel extends Activity.Panel { ActiveBoxBag bgA, bgB; protected Panel(PlayStation ps) { super(ps); bc = new BoxConnector(this); } public void clear() { if (bgA != null) { bgA.end(); bgA = null; } if (bgB != null) { bgB.end(); bgB = null; } } @Override public void buildVisualComponents() throws Exception { if (firstRun) super.buildVisualComponents(); clear(); if (abc[0] != null) { if (acp != null) acp.generateContent(new ActiveBagContentKit(abc[0].nch, abc[0].ncw, abc, false), ps); bgA = ActiveBoxGrid.createEmptyGrid(null, this, margin, margin, abc[0]); bgB = ActiveBoxGrid.createEmptyGrid(null, this, margin, margin, abc[0]); bgA.setContent(abc[0]); bgA.setVisible(true); bgB.setVisible(true); ActiveBox bgbA = bgA.getBackgroundActiveBox(); ActiveBox bgbB = bgB.getBackgroundActiveBox(); if (bgbA != null && bgbB != null) bgbB.exchangeContent(bgbA); invalidate(); } } @Override public void initActivity() throws Exception { super.initActivity(); if (!firstRun) buildVisualComponents(); else firstRun = false; setAndPlayMsg(MAIN, EventSounds.START); if (bgA != null && bgB != null) { shuffle(new ActiveBoxBag[] { bgA }, true, true); if (useOrder) currentItem = bgA.getNextItem(-1); playing = true; } } public void render(Graphics2D g2, Rectangle dirtyRegion) { if (bgA != null) bgA.update(g2, dirtyRegion, this); if (bgB != null) bgB.update(g2, dirtyRegion, this); if (bc.active) bc.update(g2, dirtyRegion, this); } public Dimension setDimension(Dimension preferredMaxSize) { if (bgA == null || bgB == null || getSize().equals(preferredMaxSize)) return preferredMaxSize; return BoxBag.layoutDouble(preferredMaxSize, bgA, bgB, boxGridPos, margin); } @Override public void processMouse(MouseEvent e) { ActiveBox bx1, bx2; Point p = e.getPoint(); if (playing) switch (e.getID()) { case MouseEvent.MOUSE_PRESSED: ps.stopMedia(1); if (bc.active) { if (dragCells) bx1 = bc.getBox(); else bx1 = bgA.findActiveBox(bc.origin); bc.end(); bx2 = bgB.findActiveBox(p); if (bx1 != null && bx2 != null && bx2.isInactive()) { boolean ok = false; String src = bx1.getDescription() + " (" + bx1.idOrder + ")"; String dest = "(" + bx2.idOrder + ")"; if (bx1.getContent().isEquivalent(abc[0].getActiveBoxContent(bx2.idOrder), true)) { ok = true; bx1.exchangeContent(bx2); bx1.setVisible(false); if (useOrder) currentItem = bgA.getNextItem(currentItem); } int cellsAtPlace = bgA.countInactiveCells(); ps.reportNewAction(DoublePuzzle.this, ACTION_PLACE, src, dest, ok, cellsAtPlace); if (ok && cellsAtPlace == bgA.getNumCells()) finishActivity(true); else playEvent(ok ? EventSounds.ACTION_OK : EventSounds.ACTION_ERROR); } repaint(); } else { if ((bx1 = bgA.findActiveBox(p)) != null && !bx1.isInactive() && (!useOrder || bx1.idOrder == currentItem)) { if (dragCells) bc.begin(p, bx1); else bc.begin(p); if (!bx1.playMedia(ps)) playEvent(EventSounds.CLICK); } } break; case MouseEvent.MOUSE_MOVED: case MouseEvent.MOUSE_DRAGGED: bc.moveTo(p); break; } } @Override public void showHelp() { if (!helpWindowAllowed() || bgA == null) return; HelpActivityComponent hac = null; if (showSolution) { hac = new HelpActivityComponent(this) { ActiveBoxBag abb = null; public void render(Graphics2D g2, Rectangle dirtyRegion) { if (abb != null) abb.update(g2, dirtyRegion, this); } @Override public void init() { abb = ActiveBoxGrid.createEmptyGrid(null, this, DEFAULT_MARGIN, DEFAULT_MARGIN, abc[0]); abb.setContent(abc[0]); abb.setVisible(true); Dimension size = bgA.getBounds().getSize(); abb.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) bgA.x - DEFAULT_MARGIN, (int) bgA.y - DEFAULT_MARGIN); } @Override public void processMouse(MouseEvent e) { ActiveBox bx; if (abb != null) switch (e.getID()) { case MouseEvent.MOUSE_PRESSED: bx = abb.findActiveBox(e.getPoint()); if (bx != null) { boolean m = bx.playMedia(ps); markBox(bgB.getActiveBox(bx.idLoc), false); if (!m) playEvent(EventSounds.CLICK); } break; case MouseEvent.MOUSE_RELEASED: unmarkBox(); break; } } }; hac.init(); } if (ps.showHelp(hac, helpMsg)) ps.reportNewAction(getActivity(), ACTION_HELP, null, null, false, bgA.countInactiveCells()); if (hac != null) hac.end(); } } }