package jp.ac.kyutech.mns.ist;
import java.awt.event.KeyEvent;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
import jp.ac.kyutech.mns.ist.sheetmap.MatrixHolder;
import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.activities.PActivity;
import edu.umd.cs.piccolo.util.PBounds;
public class LayoutAbstract {
PCamera camera;
// ArrayList<LayoutContent> sorted;
MatrixHolder<LayoutContent> matrix;
int rownum_or_colnum = -1;
public LayoutAbstract(PCamera cam){
camera = cam;
// sorted = new ArrayList<LayoutContent>();
matrix = new MatrixHolder<LayoutContent>();
}
//カーソルキーで上下左右するときに,次のフォーカスを探す
// public LayoutContent getNext(int cur, int offset){
// int size = sorted.size();
// int expect = cur + offset;
// if (size <= expect) {
// if (cur == size-1) return null; else return sorted.get(size-1);
// } else if (expect < 0){
// if (cur == 0) return null; else return sorted.get(0);
// } else {
// return sorted.get(expect);
// }
// }
public LayoutContent getUDLR(int keyCode, LayoutContent currentFocus){
LayoutContent lc = matrix.getUDLR(keyCode, currentFocus);
if (lc == null && keyCode == KeyEvent.VK_LEFT){
lc = matrix.getPreviousRowTail(currentFocus);
}
if (lc == null && keyCode == KeyEvent.VK_RIGHT){
lc = matrix.getNextRowHead(currentFocus);
}
return lc;
}
public void layout(int wait, LayoutTarget target){
class LayoutTask extends TimerTask{
ArrayList<LayoutContent> cnt;
LayoutTask(ArrayList<LayoutContent> _cnt){ cnt = _cnt; }
public void run(){
ArrayList<PActivity> palist = move(cnt);
long mtime = System.currentTimeMillis();
if (palist == null) return;
for (PActivity pact : palist) if (pact != null) pact.setStartTime(mtime);
}
}
Timer t = new Timer();
t.schedule(new LayoutTask(target.getLayoutContents()), wait);
//カーソルキー移動用の配列追加
// sorted.clear();
// sorted.addAll(target.getLayoutContents());
}
//縦方向にならべるレイアウト
public ArrayList<PActivity> move(ArrayList<LayoutContent> cnt){
int varticalNum = getBestFitLayoutV(cnt, camera.getViewBounds(), 0, 0);
ArrayList<PActivity> palist = new ArrayList<PActivity>();
int ix=0,iy=0;
double x = 0, y = 0, xmax = 0, w = 0;
double xgap = 0, ygap = 0;
int varticalCount = 0;
matrix.removeAll();
for(LayoutContent pn: cnt){
if (!pn.hasContent()) continue;
PActivity pa = pn.animateToPositionScaleRotation(x, y, 1, 0, 1000);
// System.out.println("x y "+x+" "+y);
matrix.put(ix, iy, pn);
palist.add(pa);
y += pn.getFullBounds().getHeight() + ygap;
iy++;
// x += pn.getFullBoundsReference().getWidth() + xgap;
if (xmax < pn.getFullBounds().getWidth()) xmax = pn.getFullBounds().getWidth();
varticalCount++;
if (varticalCount == varticalNum){
varticalCount = 0;
w = w + xmax + xgap;
x = w;
y = 0;
xmax = 0;
ix++;
iy=0;
}
}
return palist;
}
public Rectangle2D maxContent(ArrayList<LayoutContent> cnt){
Rectangle2D maximumDim = null;
double maxDimSq = 0;
for(LayoutContent fr: cnt){
Rectangle2D temp = fr.getFullBounds();
double sq = temp.getWidth()*temp.getHeight();
if (maxDimSq < sq){
maxDimSq = sq;
maximumDim = temp;
}
}
return maximumDim;
}
public PBounds contentregion(LayoutTarget target){
ArrayList<LayoutContent> cnt = target.getLayoutContents();
int varticalNum = getBestFitLayoutV(cnt, camera.getViewBounds(), 0, 0);
PBounds returnPB = new PBounds();
double x = 0, y = 0, xmax = 0, w = 0;
double xgap = 0, ygap = 0;
int varticalCount = 0;
for(LayoutContent pn: cnt){
if (!pn.hasContent()) continue;
if (returnPB != null) {
PBounds aPB = new PBounds(pn.mysize());
aPB.setOrigin(x,y);
returnPB.add(aPB);
}
y += pn.getFullBounds().getHeight() + ygap;
// x += pn.getFullBoundsReference().getWidth() + xgap;
if (xmax < pn.getFullBounds().getWidth()) xmax = pn.getFullBounds().getWidth();
varticalCount++;
if (varticalCount == varticalNum){
varticalCount = 0;
w = w + xmax + xgap;
x = w;
y = 0;
xmax = 0;
}
}
return returnPB;
}
public int getBestFitLayoutV(Collection<LayoutContent> rects2,
Rectangle2D availableScreenSize, double xgap, double ygap) {
ArrayList<Rectangle2D> dims = new ArrayList<Rectangle2D>();
for(LayoutContent fr: rects2){
dims.add(fr.mysize());
}
int num = dims.size();
double parentrate = availableScreenSize.getWidth()/availableScreenSize.getHeight();
if (Double.isNaN(parentrate)) {
parentrate = 1.66;
}
// System.out.println("LayoutAbst Parent "+parentrate);
TreeMap<Double,Integer> resultRates = new TreeMap<Double,Integer>();
for(int i=1;i<=num;i++){
double fitrate = fitrateV(dims, i, xgap, ygap);
resultRates.put(Math.abs(parentrate - fitrate), i);
// System.out.println(i+"/"+num+" "+Math.abs(parentrate - fitrate)+" "+fitrate+" parent="+parentrate+" fitrateV");
}
ArrayList<Integer> intres = new ArrayList<Integer>(resultRates.values());
if (intres.size()>0) rownum_or_colnum = intres.get(0);
// System.out.println("LayAB 採用"+rownum_or_colnum);
return rownum_or_colnum;
}
public double fitrateV(ArrayList<Rectangle2D> boxes, int varticalNum, double xgap, double ygap){
double x = 0, y = 0, w = 0, h = 0;
int varticalCount = 0;
for(Rectangle2D pn: boxes){
y += pn.getHeight() + ygap;
if (x < pn.getWidth()) x = pn.getWidth();
varticalCount++;
if (varticalCount == varticalNum){
w += x + xgap;
if (h < y) h = y;
varticalCount = 0;
y = 0;
x = 0;
}
}
w += x + xgap;
if (h < y) h = y;
return w/h;
}
public double fitrateH(ArrayList<Rectangle2D> boxes, int horizontalNum, double xgap, double ygap){
double x = 0, y = 0, w = 0, h = 0;
int horizonCount = 0;
for(Rectangle2D pn: boxes){
x += pn.getWidth() + xgap;
if (y < pn.getHeight()) y = pn.getHeight();
horizonCount++;
if (horizonCount == horizontalNum){
h += y + ygap;
if (w < x) w = x;
horizonCount = 0;
y = 0;
x = 0;
}
}
h += y + ygap;
if (w < x) w = x;
return w/h;
}
// public double fitrateHH(ArrayList<Rectangle2D> boxes, int horizontalNum, double xgap, double ygap){
// double x = 0, y = 0, w = 0, h = 0;
// int horizonCount = 0;
// // System.out.print("Try "+horizontalNum);
// for(Rectangle2D pn: boxes){
// x += pn.getWidth() + xgap;
// if (y < pn.getHeight()) y = pn.getHeight();
// horizonCount++;
// if (horizonCount == horizontalNum){
// h += y + ygap;
// if (w < x) w = x;
// horizonCount = 0;
// y = 0;
// x = 0;
// }
// }
// h += y + ygap;
// if (w < x) w = x;
// return w/h;
// }
}