package haven;
import haven.Resource.Image;
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class ToolbarWnd extends Window implements DTarget, DropTarget {
private static final Color pressedColor = new Color(196, 196, 196, 196);
public final static Tex bg = Resource.loadtex("gfx/hud/invsq");
private static final int BELTS_NUM = 15;
private static final BufferedImage ilockc = Resource.loadimg("gfx/hud/lockc");
private static final BufferedImage ilockch = Resource.loadimg("gfx/hud/lockch");
private static final BufferedImage ilocko = Resource.loadimg("gfx/hud/locko");
private static final BufferedImage ilockoh = Resource.loadimg("gfx/hud/lockoh");
@SuppressWarnings("unchecked")
private static final Indir<Resource>[] defbelt = new Indir[10];
public final static Coord bgsz = bg.sz().add(-1, -1);
private Properties beltsConfig;
private Coord gsz, off, beltNumC;
public Slot pressed, dragging, layout[];
private IButton lockbtn, flipbtn, minus, plus;
public boolean flipped = false, locked = false;
public int belt, key;
private Tex[] nums;
private static Tex[] beltNums;
public String name;
public final static RichText.Foundry ttfnd = new RichText.Foundry(TextAttribute.FAMILY, "SansSerif", TextAttribute.SIZE, 10);
static {
/* Text rendering is slow, so pre-cache the belt numbers. */
beltNums = new Tex[BELTS_NUM];
for (int i = 0; i < BELTS_NUM; i++) {
beltNums[i] = new TexI(Utils.outline2(Text.render(Integer.toString(i)).img, Color.BLACK, true));
}
}
public ToolbarWnd(Coord c, Widget parent, String name, Properties bc) {
super(c, Coord.z, parent, null);
this.name = name;
beltsConfig = bc;
init(1, 10, new Coord(5, 10), KeyEvent.VK_0);
}
public ToolbarWnd(Coord c, Widget parent, String name, Properties bc, int belt, int key, int sz, Coord off) {
super(c, Coord.z, parent, null);
this.name = name;
beltsConfig = bc;
init(belt, sz, off, key);
}
public ToolbarWnd(Coord c, Widget parent, String name, Properties bc, int belt, int key) {
super(c, Coord.z, parent, null);
this.name = name;
beltsConfig = bc;
init(belt, 10, new Coord(5, 10), key);
}
private void loadOpts() {
synchronized (Config.window_props) {
if (Config.window_props.getProperty(name + "_locked", "false").equals("true")) {
locked = true;
}
if (Config.window_props.getProperty(name + "_flipped", "false").equals("true")) {
flip();
}
if (Config.window_props.getProperty(name + "_folded", "false").equals("true")) {
folded = true;
checkfold();
}
visible = Config.window_props.getProperty(name, "true").equals("true");
c = new Coord(Config.window_props.getProperty(name + "_pos", c.toString()));
}
}
private void init(int belt, int sz, Coord off, int key) {
gsz = new Coord(1, sz);
this.off = off;
fbtn.show();
mrgn = new Coord(2, 18);
layout = new Slot[sz];
loadOpts();
cbtn.visible = false;
lockbtn = new IButton(Coord.z, this, locked ? ilockc : ilocko, locked ? ilocko : ilockc, locked ? ilockch : ilockoh) {
public void click() {
locked = !locked;
if (locked) {
up = ilockc;
down = ilocko;
hover = ilockch;
} else {
up = ilocko;
down = ilockc;
hover = ilockoh;
}
Config.setWindowOpt(name + "_locked", locked);
}
};
lockbtn.recthit = true;
flipbtn = new IButton(Coord.z, this, Resource.loadimg("gfx/hud/flip"), Resource.loadimg("gfx/hud/flip"), Resource.loadimg("gfx/hud/flipo")) {
public void click() {
flip();
}
};
minus = new IButton(Coord.z, this, Resource.loadimg("gfx/hud/charsh/minusup"), Resource.loadimg("gfx/hud/charsh/minusdown")) {
public void click() {
prevBelt();
}
};
plus = new IButton(Coord.z, this, Resource.loadimg("gfx/hud/charsh/plusup"), Resource.loadimg("gfx/hud/charsh/plusdown")) {
public void click() {
nextBelt();
}
};
flipbtn.recthit = true;
loadBelt(belt);
this.key = key;
pack();
/* Text rendering is slow, so pre-cache the hotbar numbers. */
nums = new Tex[sz];
for (int i = 0; i < sz; i++) {
String slot;
if (key == KeyEvent.VK_0) {
slot = Integer.toString(i);
} else if (key == KeyEvent.VK_F1) {
slot = "F" + Integer.toString(i + 1);
} else {
slot = "N" + Integer.toString(i);
}
nums[i] = new TexI(Utils.outline2(Text.render(slot).img, Color.BLACK, true));
}
}
protected void nextBelt() {
loadBelt(belt + 2);
}
protected void prevBelt() {
loadBelt(belt - 2);
}
public static Properties getBelts() {
Properties loadInfo = new Properties();
try {
String configFileName = "belts_" + MaidFrame.getCurrentSession().getUI().sess.charname.replaceAll("[^a-zA-Z()]", "_") + ".conf";
loadInfo.load(new FileInputStream(configFileName));
} catch (FileNotFoundException e) {
} catch (Exception e) {
}
return loadInfo;
}
protected void loadBelt(int beltNr) {
belt = beltNr % BELTS_NUM;
if (belt < 0)
belt += BELTS_NUM;
synchronized (beltsConfig) {
for (int slot = 0; slot < layout.length; slot++) {
String icon = beltsConfig.getProperty("belt_" + belt + "_" + slot, "");
if (icon.length() > 0) {
layout[slot] = new Slot(icon, belt, slot);
} else {
layout[slot] = null;
}
}
}
}
public void saveBelts() {
synchronized (beltsConfig) {
String charName = MaidFrame.getCurrentSession().getUI().sess.charname;
if (charName == null)
return;
String configFileName = "belts_" + charName.replaceAll("[^a-zA-Z()]", "_") + ".conf";
try {
beltsConfig.store(new FileOutputStream(configFileName), "Belts actions for " + MaidFrame.getCurrentSession().getUI().sess.charname);
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
}
public void wdgmsg(Widget sender, String msg, Object... args) {
if (sender == cbtn)
ui.destroy(this);
Boolean _folded = folded;
if (sender == fbtn)
super.wdgmsg(sender, msg, args);
if (_folded != folded) {
Config.setWindowOpt(name + "_folded", folded);
}
}
public void draw(GOut g) {
super.draw(g);
if (folded)
return;
for (int y = 0; y < gsz.y; y++) {
for (int x = 0; x < gsz.x; x++) {
Coord p = getcoord(x, y);
g.image(bg, p);
int slot = x + y;
if (key == KeyEvent.VK_0)
slot = (slot + 1) % 10;
Slot s = layout[x + y];
Resource btn = (s == null) ? null : s.getres();
if (btn != null) {
Image img = btn.layer(Resource.imgc);
if (img != null) {
Tex btex = img.tex();
if (s == pressed) {
g.chcolor(pressedColor);
}
if (Config.highlightSkills)
g.chcolor(btn.getStateColor());
g.image(btex, p.add(1, 1));
} else {
System.out.println(btn.name);
}
}
g.aimage(nums[slot], p.add(bg.sz()), 1, 1);
g.chcolor();
}
}
g.chcolor();
Resource res;
if ((dragging != null) && ((res = dragging.getres()) != null)) {
final Tex dt = res.layer(Resource.imgc).tex();
ui.drawafter(new UI.AfterDraw() {
public void draw(GOut g) {
g.image(dt, ui.mc.add(dt.sz().div(2).inv()));
}
});
}
g.aimage(beltNums[belt], beltNumC, 1, 1);
}
private Coord getcoord(int x, int y) {
Coord p = xlate(bgsz.mul(new Coord(x, y)), true);
if (off.x > 0)
if (flipped) {
p.x += off.y * (x / off.x);
} else {
p.y += off.y * (y / off.x);
}
return p;
}
public void checkfold() {
super.checkfold();
Coord max = new Coord(ssz);
if ((folded) && (flipped)) {
max.x = 0;
recalcsz(max);
}
placecbtn();
}
protected void recalcsz(Coord max) {
sz = max.add(wbox.bsz().add(mrgn.mul(2)).add(tlo).add(rbo)).add(-1, -1);
wsz = sz.sub(tlo).sub(rbo);
if (folded)
if (flipped)
wsz.x = wsz.x / 2;
else
wsz.y = wsz.y / 2;
asz = wsz.sub(wbox.bl.sz()).sub(wbox.br.sz()).sub(mrgn.mul(2));
}
public void flip() {
flipped = !flipped;
gsz = new Coord(gsz.y, gsz.x);
mrgn = new Coord(mrgn.y, mrgn.x);
pack();
Config.setWindowOpt(name + "_flipped", flipped);
}
protected void placecbtn() {
cbtn.c = new Coord(wsz.x - 3 - Utils.imgsz(cbtni[0]).x, 3).sub(mrgn).sub(wbox.tloff());
if (flipped) {
fbtn.c = new Coord(cbtn.c.x, wsz.y - 3 - Utils.imgsz(fbtni[0]).y - mrgn.y - wbox.tloff().y);
if (lockbtn != null)
lockbtn.c = new Coord(3 - wbox.tloff().x - mrgn.x, cbtn.c.y);
if (flipbtn != null)
flipbtn.c = new Coord(5 - wbox.tloff().x - mrgn.x, fbtn.c.y);
if (plus != null)
plus.c = cbtn.c.sub(16, 0);
if (minus != null) {
minus.c = fbtn.c.sub(16, 0);
beltNumC = minus.c.add(plus.c).div(2).add(36, 22);
}
} else {
fbtn.c = new Coord(3 - wbox.tloff().x, cbtn.c.y);
if (lockbtn != null)
lockbtn.c = new Coord(fbtn.c.x, wsz.y - 21 - mrgn.y - wbox.tloff().y);
if (flipbtn != null)
flipbtn.c = new Coord(cbtn.c.x - 2, wsz.y - 21 - mrgn.y - wbox.tloff().y);
if (plus != null)
plus.c = flipbtn.c.sub(0, 16);
if (minus != null) {
minus.c = lockbtn.c.sub(0, 16);
beltNumC = minus.c.add(plus.c).div(2).add(20, 38);
}
}
}
public void pack() {
ssz = bgsz.mul(gsz);
if (off.x > 0)
if (flipped) {
ssz.x += off.y * ((gsz.x / off.x) - ((gsz.x % off.x == 0) ? 1 : 0)) + 16;
} else {
ssz.y += off.y * ((gsz.y / off.x) - ((gsz.y % off.x == 0) ? 1 : 0)) + 16;
}
checkfold();
placecbtn();
}
private Slot bhit(Coord c) {
int i = index(c);
if (i >= 0)
return (layout[i]);
else
return (null);
}
private int index(Coord c) {
for (int y = 0; y < gsz.y; y++) {
for (int x = 0; x < gsz.x; x++) {
if (c.isect(getcoord(x, y), bgsz))
return x + y;
}
}
return -1;
}
public boolean mousedown(Coord c, int button) {
Slot h = bhit(c);
if (button == 1) {
if (h != null) {
pressed = h;
ui.grabmouse(this);
} else {
super.mousedown(c, button);
}
} else if ((button == 3) && (!locked)) {
clearslot(index(c));
}
return (true);
}
public boolean mouseup(Coord c, int button) {
Slot h = bhit(c);
if (button == 1) {
if (dragging != null) {
ui.dropthing(ui.root, ui.mc, dragging.getres());
dragging = pressed = null;
} else if (pressed != null) {
if (pressed == h)
h.use();
pressed = null;
}
ui.grabmouse(null);
}
if (dm) {
Config.setWindowOpt(name + "_pos", this.c.toString());
}
super.mouseup(c, button);
return (true);
}
public void clearslot(int slot) {
if ((slot < 0) || (slot >= layout.length)) {
return;
}
Slot s = layout[slot];
layout[slot] = null;
setBeltSlot(slot, "");
if ((s != null) && (s.isitem)) {
ui.slen.wdgmsg("belt", s.slot, 3, ui.modflags());
}
}
public void mousemove(Coord c) {
if ((!locked) && (dragging == null) && (pressed != null)) {
dragging = pressed;
int slot = index(c);
if (slot >= 0) {
clearslot(slot);
}
pressed = null;
} else {
super.mousemove(c);
}
}
public boolean drop(Coord cc, Coord ul) {
if (!locked) {
int s = getbeltslot();
if (s < 0) {
String msg = "No empty item slots!";
ui.cons.out.println(msg);
ui.slen.error(msg);
} else {
int slot = index(cc);
if (slot >= 0) {
String val = "@" + s;
layout[slot] = new Slot(val, belt, slot);
ui.slen.wdgmsg("setbelt", s, 0);
setbeltslot(belt, slot, val);
}
}
}
return (true);
}
public boolean iteminteract(Coord cc, Coord ul) {
return (false);
}
public boolean dropthing(Coord c, Object thing) {
if ((!locked) && (thing instanceof Resource)) {
int slot = index(c);
if (slot < 0) {
return false;
}
Resource res = (Resource) thing;
setBeltSlot(slot, res.name);
layout[slot] = new Slot(res.name, belt, slot);
return true;
}
return false;
}
private void setBeltSlot(int slot, String icon) {
setbeltslot(belt, slot, icon);
}
private Resource curttr = null;
private boolean curttl = false;
private Text curtt = null;
private long hoverstart;
public Object tooltip(Coord c, boolean again) {
Slot slot = bhit(c);
Resource res = (slot == null) ? null : slot.getres();
long now = System.currentTimeMillis();
if ((res != null) && ((res.layer(Resource.action) != null) || (res.layer(Resource.tooltip) != null))) {
if (!again)
hoverstart = now;
boolean ttl = (now - hoverstart) > 500;
if ((res != curttr) || (ttl != curttl)) {
curtt = rendertt(res, ttl);
curttr = res;
curttl = ttl;
}
return (curtt);
} else {
hoverstart = now;
return ("");
}
}
private static Text rendertt(Resource res, boolean withpg) {
Resource.AButton ad = res.layer(Resource.action);
Resource.Pagina pg = res.layer(Resource.pagina);
String tt;
if (ad != null) {
tt = ad.name;
} else {
tt = res.layer(Resource.tooltip).t;
}
if (withpg && (pg != null)) {
tt += "\n\n" + pg.text;
}
return (ttfnd.render(tt, 0));
}
private boolean checkKey(char ch, KeyEvent ev) {
if (!visible) {
return false;
}
int code = ev.getKeyCode();
int slot = code - key;
boolean alt = ev.isAltDown();
boolean ctrl = ev.isControlDown();
if (alt && key == KeyEvent.VK_F1) {
slot = code - KeyEvent.VK_0;
if ((slot > 0) && (slot <= 5)) {
loadBelt(slot * 2);
return true;
}
} else if (ctrl && key == KeyEvent.VK_0) {
slot = code - KeyEvent.VK_0;
if ((slot > 0) && (slot <= 5)) {
slot = ((slot - 1) << 1) + 1;
loadBelt(slot);
return true;
}
} else if (!alt && !ctrl && (slot >= 0) && (slot < gsz.x * gsz.y)) {
if (key == KeyEvent.VK_0)
slot = (slot == 0) ? 9 : slot - 1;
Slot h = layout[slot];
if (h != null)
h.use();
return true;
}
return false;
}
public boolean globtype(char ch, KeyEvent ev) {
if (!checkKey(ch, ev))
return (super.globtype(ch, ev));
else
return true;
}
public boolean type(char key, KeyEvent ev) {
if (key == 27) {
wdgmsg(fbtn, "click");
return (true);
}
if (!checkKey(key, ev))
return (super.type(key, ev));
else
return true;
}
public void removedef(int slot) {
for (int i = 0; i < layout.length; i++) {
Slot s = layout[i];
if ((s != null) && s.isitem && (s.slot == slot)) {
clearslot(i);
}
}
}
public static void setbelt(int slot, Indir<Resource> res) {
synchronized (defbelt) {
defbelt[slot] = res;
}
if (res == null) {
MenuGrid mnu = MaidFrame.getCurrentSession().getUI().mnu;
mnu.digitbar.removedef(slot);
mnu.functionbar.removedef(slot);
mnu.numpadbar.removedef(slot);
}
}
public static Indir<Resource> getbelt(int slot) {
Indir<Resource> res;
synchronized (defbelt) {
res = defbelt[slot];
}
return res;
}
public static int getbeltslot() {
synchronized (defbelt) {
for (int i = 0; i < defbelt.length; i++) {
if (defbelt[i] == null) {
return i;
}
}
}
return -1;
}
private void setbeltslot(int belt, int slot, String value) {
synchronized (beltsConfig) {
beltsConfig.setProperty("belt_" + belt + "_" + slot, value);
}
saveBelts();
}
public static class Slot {
public boolean isitem;
public String action;
public int slot;
public Resource res;
public int belt, ind;
public Slot(String str, int belt, int ind) {
this.ind = ind;
this.belt = belt;
if (str.charAt(0) == '@') {
isitem = true;
slot = Integer.decode(str.substring(1));
} else {
isitem = false;
action = str;
res = Resource.load(action);
}
}
public Resource getres() {
if ((res == null) && (isitem)) {
Indir<Resource> indir = getbelt(slot);
if (indir == null) {
res = null;
} else {
res = indir.get();
}
}
return res;
}
public void use() {
UI ui = UI.instance;
if (isitem) {
if (slot >= 0) {
ui.slen.wdgmsg("belt", slot, 1, ui.modflags());
}
} else if (ui.mnu != null) {
ui.mnu.use(res);
}
}
}
}