package kakuro.gui;
import java.awt.*;
import java.awt.event.*;
import kakuro.table.ITable;
import kakuro.table.Position;
import kakuro.table.TableException;
import java.util.*;
/** Fehér cella a grafikus felületen. */
class GamefieldWhite extends Gamefield {
static final long serialVersionUID = 1245754576l;
/** Egér a komponens belsejében van-e. Ez a mező azért kellett, mert a fókuszkezelés miatt
* simán lehetett gépelni a mezőbe számokat a grafikus felületen át, amíg az inputfókuszt meg nem
* kapta egy másik fehér cella - tehát a táblát elhagyva is ide gépelt még a felhasználó, és ez nem
* volt szép. */
private boolean inside = false;
/** Alap konstruktor.
*
* @param gui grafikus felület
* @param table tábla aminek része a cella
* @param label felirat
* @param pos cella helye
* @param user felhasználó által beírt érték, ez pl. mentésből a szerver adja meg
* */
public GamefieldWhite(Gui gui, Gametable table, String label, Position pos, String user) {
super(gui, table, label, pos);
if (user!=null) _value = user;
}
/** Háttér és border beállítása */
void init() {
super.init();
//setBackground(new Color(208, 205, 183));
setBackground(new Color(221, 204, 153));
setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.LOWERED));
}
/** Felüldefiniált paint függvény, a felhasználó által beírt értéket rajzolja ki, illetve ha be van
* kapcsolva a debug mód a kliensben, akkor piciben kiírja a valódi értéket is.
*
* @param g grafika
* */
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
if (_smallFont == null)
_smallFont = g2d.getFont().deriveFont(Font.ITALIC, 10);
if (_gui!=null && _gui.showDebugInfo()) {
g2d.setFont(_smallFont);
g2d.drawString(_label, 3, 10);
}
if (_value != null) {
if (_largeFont == null) {
_largeFont = _smallFont.deriveFont(Font.BOLD, 20);
}
g2d.setFont(_largeFont);
g2d.drawString(_value, getSize().width / 2 - 10,
getSize().height / 2 + 5);
g2d.setFont(_smallFont);
}
}
/** Egéresemény kezelés, egér belép a cella területére. Ilyenkor a cella magához ragadja az inputfókuszt,
* hogy reagálni tudjon a billentyűzet-eseményekre is. Beállítja a hátteret, és a tippeket a tipp-panelen.
*
* @param me egéresemény
* */
public void _mouseEntered(MouseEvent me) {
setBackground(new Color(231, 214, 163));
requestFocusInWindow();
Position leftBlackPos = _table.getFirstBlackToLeft(_pos);
Position upBlackPos = _table.getFirstBlackToUp(_pos);
int hSum = _table.getSum(leftBlackPos, ITable.SUM_HORIZONTAL);
int vSum = _table.getSum(upBlackPos, ITable.SUM_VERTICAL);
int hRun = _table.getRunToRight(leftBlackPos);
int vRun = _table.getRunToDown(upBlackPos);
Iterator<String> h1 = _gui.getServer().getHint(hSum, hRun);
Iterator<String> h2 = _gui.getServer().getHint(vSum, vRun);
if (hRun>1) _gui.setHint1(getHint(h1, "Vízszintes:<br />", hSum + " = "));
if (vRun >1) _gui.setHint2(getHint(h2, "Függőleges:<br />", vSum + " = "));
inside = true;
}
/** Egéresemény kezelés, az egér elhagyja a cellát. Hátteret állít, tippeket törli.
*
* @param me egéresemény
* */
public void _mouseExited(MouseEvent me) {
setBackground(new Color(221, 204, 153));
_gui.clearHint();
inside = false;
}
/** Billentyűzet-leütés eseménykezelő. Space-re töröl, számbillentyűk értékét megjegyzi. Ellenőrzi azt,
* hogy a megadott szám előfordul-e valahol a szóban, ha igen, felvillantja a mezőket,
* lásd {@link Gamefield#flash()}. Ha egy szó minden celláját kitöltötték már, akkor ellenőrzi az összegeket is.
*
* @param e billenyűzet leütés esemény*/
public void _keyTyped(KeyEvent e) {
if (!inside) return;
_gui.debug("keyTyped event in " + _label + ": " + e.getKeyChar());
char c = e.getKeyChar();
try {
if (c==KeyEvent.VK_SPACE) {
_table.getModel().writeCell(_pos, 0 ,ITable.VALUE_NORMAL);
_value = "";
repaint();
return;
}
int i = Integer.parseInt("" + c);
int[] hbl = _table.getHorizontalBlock(_pos);
int[] vbl = _table.getVerticalBlock(_pos);
int hdig = _table.duplicatedDigitInBlock(hbl ,i);
int vdig = _table.duplicatedDigitInBlock(vbl ,i);
if (i > 0 && i <= 9) {
Position h_p_sum = _table.getFirstBlackToLeft(_pos);
Position v_p_sum = _table.getFirstBlackToUp(_pos);
int h_length = _table.getRunToRight(h_p_sum);
int v_length = _table.getRunToDown(v_p_sum);
_value = "" + c;
_table.getModel().writeCell(_pos, i,ITable.VALUE_NORMAL);
if (hdig != -1){
_table.flashFields(createListForPositions(h_p_sum.x+hdig+1,h_p_sum.y,h_p_sum.x+hdig+1,h_p_sum.y));
_table.flashFields(createListForPositions(_pos.x,_pos.y,_pos.x,_pos.y));
_gui.debug("This digit already exists in this horizontal block !");
}
if (vdig != -1){
_table.flashFields(createListForPositions(v_p_sum.x,v_p_sum.y+vdig+1,v_p_sum.x,v_p_sum.y+vdig+1));
_table.flashFields(createListForPositions(_pos.x,_pos.y,_pos.x,_pos.y));
_gui.debug("This digit already exists in this vertical block !");
}
hbl = _table.getHorizontalBlock(_pos);
vbl = _table.getVerticalBlock(_pos);
if (_table.blockIsFull(hbl)){
if (_table.horizontalSumIsOK(_pos, hbl) == false){
_table.flashFields(createListForPositions(h_p_sum.x,h_p_sum.y,h_p_sum.x+h_length,h_p_sum.y));
_gui.debug("Sum is wrong in the horizontal block !");
}
}
if (_table.blockIsFull(vbl)){
if (_table.verticalSumIsOK(_pos, vbl) == false){
_table.flashFields(createListForPositions(v_p_sum.x,v_p_sum.y,v_p_sum.x,v_p_sum.y+v_length));
_gui.debug("Sum is wrong in the vertical block !");
}
}
repaint();
if (_table.getModel().isReady()){
_gui.setReady();
}
}
} catch (java.lang.NumberFormatException nfe) {
} catch (TableException te) {
}
}
/**
* Listát készít azon cellákról, akik a megadott koordináták közé esnek. Paraméterek inklúzív értendők!
*
* @param x1 bal x koordináta
* @param y1 bal y koordináta
* @param x2 jobb x koordináta
* @param y2 jobb y koordináta
*
* @return cellák listája
* */
protected ArrayList<Position> createListForPositions(int x1,int y1, int x2, int y2){
ArrayList<Position> list = new ArrayList<Position>();
Position _p_f;
for(int m = x1;m <= x2; m++){
for(int n = y1;n <= y2; n++){
_p_f = new Position(m,n);
list.add(_p_f);
}
}
return list;
}
/** Vizuális figyelmeztetés, cellát felvillantja pirossal. Indít egy Timert a háttérben, az intézi a
* fokozatos színátmenetet. */
protected void flash() {
TimerTask task = new TimerTask() {
int runs = 0;
int max = 10;
Color bg = null;
Color to = Color.RED;
private int getInter(int f, int t, int step) {
if (f<t) {
return f+((int)((t-f)/max)*step);
} else {
return t+((int)((f-t)/max)*step);
}
}
public void run() {
if (++runs>20) {
setBackground(bg);
cancel();
return;
}
if (bg==null) bg = new Color(221, 204, 153);
if (runs<10) {
setBackground(new Color(getInter(bg.getRed(), to.getRed(), runs), getInter(bg.getGreen(), to.getGreen(), runs), getInter(bg.getBlue(), to.getBlue(), runs)));
}
if (runs==10) setBackground(to);
if (runs>10) {
setBackground(new Color(getInter(to.getRed(), bg.getRed(), runs-max), getInter(to.getGreen(), bg.getGreen(), runs-max), getInter(to.getBlue(), bg.getBlue(), runs-max)));
}
}
};
Timer timer = new Timer(true);
timer.schedule(task, 100, 100);
}
}