/* * This file is part of the Haven & Hearth game client. * Copyright (C) 2009 Fredrik Tolf <fredrik@dolda2000.com>, and * Björn Johannessen <johannessen.bjorn@gmail.com> * * Redistribution and/or modification of this file is subject to the * terms of the GNU Lesser General Public License, version 3, as * published by the Free Software Foundation. * * 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. * * Other parts of this source tree adhere to other copying * rights. Please see the file `COPYING' in the root directory of the * source tree for details. * * A copy the GNU Lesser General Public License is distributed along * with the source tree of which this file is a part in the file * `doc/LPGL-3'. If it is missing for any reason, please see the Free * Software Foundation's website at <http://www.fsf.org/>, or write * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ package haven; import haven.CharWnd.Study; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.TreeMap; public class UI { static public UI instance; public RootWidget root; public SlenHud slen; public MenuGrid mnu; public Speedget spd; public Study study; public WikiBrowser wiki; private Widget keygrab, mousegrab; public Map<Integer, Widget> widgets = new TreeMap<Integer, Widget>(); public Map<Widget, Integer> rwidgets = new HashMap<Widget, Integer>(); Receiver rcvr; public Coord mc, lcc = Coord.z; public Session sess; public IHWindowParent chat; public MapView mainview; public boolean modshift, modctrl, modmeta, modsuper; long lastevent = System.currentTimeMillis(); public Widget mouseon; public FSMan fsm; public Console cons = new WidgetConsole(); private Collection<AfterDraw> afterdraws = null; public final Maid maid; public Fightview fview; public interface Receiver { public void rcvmsg(int widget, String msg, Object... args); } public interface AfterDraw { public void draw(GOut g); } private class WidgetConsole extends Console { { setcmd("q", new Command() { public void run(Console cons, String[] args) { HackThread.tg().interrupt(); } }); setcmd("lo", new Command() { public void run(Console cons, String[] args) { sess.close(); } }); setcmd("fs", new Command() { public void run(Console cons, String[] args) { if ((args.length >= 2) && (fsm != null)) { if (Utils.atoi(args[1]) != 0) fsm.setfs(); else fsm.setwnd(); } } }); } private void findcmds(Map<String, Command> map, Widget wdg) { if (wdg instanceof Directory) { Map<String, Command> cmds = ((Directory) wdg).findcmds(); synchronized (cmds) { map.putAll(cmds); } } for (Widget ch = wdg.child; ch != null; ch = ch.next) findcmds(map, ch); } public Map<String, Command> findcmds() { Map<String, Command> ret = super.findcmds(); findcmds(ret, root); return (ret); } } @SuppressWarnings("serial") public static class UIException extends RuntimeException { public String mname; public Object[] args; public UIException(String message, String mname, Object... args) { super(message); this.mname = mname; this.args = args; } } public UI(Maid maid, Coord sz, Session sess) { instance = this; this.maid = maid; root = new RootWidget(this, sz); widgets.put(0, root); rwidgets.put(root, 0); this.sess = sess; } public void close() { this.sess.close(); } public void setreceiver(Receiver rcvr) { this.rcvr = rcvr; } public void bind(Widget w, int id) { widgets.put(id, w); rwidgets.put(w, id); } public void drawafter(AfterDraw ad) { synchronized (afterdraws) { afterdraws.add(ad); } } public void draw(GOut g) { afterdraws = new LinkedList<AfterDraw>(); root.draw(g); synchronized (afterdraws) { for (AfterDraw ad : afterdraws) { ad.draw(g); } } afterdraws = null; } public void newwidget(int id, String type, Coord c, int parent, Object... args) throws InterruptedException { WidgetFactory f; if (type.indexOf('/') >= 0) { int ver = -1, p; if ((p = type.indexOf(':')) > 0) { ver = Integer.parseInt(type.substring(p + 1)); type = type.substring(0, p); } Resource res = Resource.load(type, ver); res.loadwaitint(); f = res.layer(Resource.CodeEntry.class).get(WidgetFactory.class); } else { f = Widget.gettype(type); } synchronized (this) { Widget pwdg = widgets.get(parent); if (pwdg == null) throw (new UIException("Null parent widget " + parent + " for " + id, type, args)); Widget wdg = f.create(c, pwdg, args); bind(wdg, id); wdg.binded(); if (wdg instanceof MapView) mainview = (MapView) wdg; } } public void grabmouse(Widget wdg) { // new if (wdg == null) { for (Widget w = root.child; w != null; w = w.next) { if (w instanceof Item) { mousegrab = w; return; } } mousegrab = wdg; } else { mousegrab = wdg; } } public boolean isgrabbingmouse() { // new return mousegrab != null; } public void grabkeys(Widget wdg) { keygrab = wdg; } private void removeid(Widget wdg) { if (rwidgets.containsKey(wdg)) { int id = rwidgets.get(wdg); widgets.remove(id); rwidgets.remove(wdg); } for (Widget child = wdg.child; child != null; child = child.next) removeid(child); } public void destroy(Widget wdg) { if ((mousegrab != null) && mousegrab.hasparent(wdg)) mousegrab = null; if ((keygrab != null) && keygrab.hasparent(wdg)) keygrab = null; wdg.destroy(); wdg.unlink(); removeid(wdg); } public void destroy(int id) { synchronized (this) { if (widgets.containsKey(id)) { Widget wdg = widgets.get(id); destroy(wdg); } } } public void wdgmsg(Widget sender, String msg, Object... args) { int id; synchronized (this) { if (!rwidgets.containsKey(sender)) throw (new UIException("Wdgmsg sender (" + sender.getClass().getName() + ") is not in rwidgets", msg, args)); id = rwidgets.get(sender); } if (rcvr != null) rcvr.rcvmsg(id, msg, args); } public void uimsg(int id, String msg, Object... args) { Widget wdg; synchronized (this) { wdg = widgets.get(id); } if (wdg != null) wdg.uimsg(msg.intern(), args); else throw (new UIException("Uimsg to non-existent widget " + id, msg, args)); } private void setmods(InputEvent ev) { int mod = ev.getModifiersEx(); modshift = (mod & InputEvent.SHIFT_DOWN_MASK) != 0; modctrl = (mod & InputEvent.CTRL_DOWN_MASK) != 0; modmeta = (mod & (InputEvent.ALT_DOWN_MASK | InputEvent.ALT_GRAPH_DOWN_MASK)) != 0; /* * modsuper = (mod & InputEvent.SUPER_DOWN_MASK) != 0; */ } public void type(KeyEvent ev) { setmods(ev); if (keygrab == null) { if (!root.type(ev.getKeyChar(), ev)) root.globtype(ev.getKeyChar(), ev); } else { keygrab.type(ev.getKeyChar(), ev); } } public void keydown(KeyEvent ev) { setmods(ev); if (keygrab == null) { if (!root.keydown(ev)) root.globtype((char) 0, ev); } else { keygrab.keydown(ev); } } public void keyup(KeyEvent ev) { setmods(ev); if (keygrab == null) root.keyup(ev); else keygrab.keyup(ev); } private Coord wdgxlate(Coord c, Widget wdg) { return (c.add(wdg.c.inv()).add(wdg.parent.rootpos().inv())); } public boolean dropthing(Widget w, Coord c, Object thing) { if (w instanceof DropTarget) { if (((DropTarget) w).dropthing(c, thing)) return (true); } for (Widget wdg = w.lchild; wdg != null; wdg = wdg.prev) { Coord cc = w.xlate(wdg.c, true); if (c.isect(cc, wdg.sz)) { if (dropthing(wdg, c.add(cc.inv()), thing)) return (true); } } return (false); } Widget temp = null; // new public void mousedown(MouseEvent ev, Coord c, int button) { // new addons.MainScript.stop(button); // new setmods(ev); lcc = mc = c; if (mousegrab == null) { root.mousedown(c, button); } else if (modflags() == 5 && mousegrab instanceof Item) { temp = mousegrab; mousegrab.hide(); mousegrab = null; root.mousedown(c, button); } else { mousegrab.mousedown(wdgxlate(c, mousegrab), button); } } public void mouseup(MouseEvent ev, Coord c, int button) { // new setmods(ev); mc = c; if (temp != null) { root.mouseup(c, button); mousegrab = temp; temp = null; mousegrab.show(); } else if (mousegrab == null) { root.mouseup(c, button); } else { mousegrab.mouseup(wdgxlate(c, mousegrab), button); } } public void mousemove(MouseEvent ev, Coord c) { setmods(ev); mc = c; if (mousegrab == null) { root.mousemove(c); } else { mousegrab.mousemove(wdgxlate(c, mousegrab)); root.mousemove(c); // new } } public void mousewheel(MouseEvent ev, Coord c, int amount) { setmods(ev); lcc = mc = c; // if(mousegrab == null) // new root.mousewheel(c, amount); // else // new // mousegrab.mousewheel(wdgxlate(c, mousegrab), amount); } public int modflags() { // new int num; num = ((modshift ? 1 : 0) | (modctrl ? 2 : 0) | (modmeta ? 4 : 0) | (modsuper ? 8 : 0)); return num; } }