/* XOWA: the XOWA Offline Wiki Application Copyright (C) 2012-2017 gnosygnu@gmail.com XOWA is licensed under the terms of the General Public License (GPL) Version 3, or alternatively under the terms of the Apache License Version 2.0. You may use XOWA according to either of these licenses as is most appropriate for your project on a case-by-case basis. The terms of each license can be found in the source code repository: GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ package gplx.gfui.ipts; import gplx.*; import gplx.gfui.*; import gplx.core.interfaces.*; public class IptBndMgr implements SrlAble { public IptEventType EventsToFwd() {return eventsToFwd;} public void EventsToFwd_set(IptEventType v) {eventsToFwd = v;} IptEventType eventsToFwd = IptEventType_.KeyDown; public void EventsToFwd_add(IptEventType v) {eventsToFwd = eventsToFwd.Add(v);} public boolean Has(IptEventType type) {return IptEventType_.Has(curTypes, type);} public void Clear() {hash.Clear(); curTypes = IptEventType_.None; ClearLists(); chainMgr.Clear();} public void Add(IptBnd bnd) { for (IptBndHash list : regy) if (IptEventType_.Has(bnd.EventTypes(), list.EventType())) list.Add(bnd); for (int i = 0; i < bnd.Ipts().Count(); i++) { IptArg arg = (IptArg)bnd.Ipts().Get_at(i); chainMgr.Add(arg); } } public List_adp Cfgs() {return cfgs;} List_adp cfgs = List_adp_.New(); public void Cfgs_delAll() { List_adp del = List_adp_.New(); for (int i = 0; i < cfgs.Count(); i++) { IptCfgPtr ptr = (IptCfgPtr)cfgs.Get_at(i); IptCfg cfg = IptCfgRegy.Instance.GetOrNew(ptr.CfgKey()); cfg.Owners_del(ptr.CfgKey()); for (IptBndHash list : regy) { for (int j = 0; j < list.Count(); j++) { IptBndListItm itmList = list.Get_at(j); for (int k = 0; k < itmList.Count(); k++) { IptBnd bnd = itmList.Get_at(k); if (String_.Eq(ptr.BndKey(), bnd.Key())) { list.Del(bnd); } } } } del.Add(cfg); } for (int i = 0; i < del.Count(); i++) { IptCfg cfg = (IptCfg)del.Get_at(i); cfgs.Del(cfg); } } public void Change(String key, IptArg[] ary) { IptBnd old = null; for (IptBndHash list : regy) { for (int j = 0; j < list.Count(); j++) { IptBndListItm itmList = list.Get_at(j); for (int i = 0; i < itmList.Count(); i++) { IptBnd bnd = itmList.Get_at(i); if (String_.Eq(key, bnd.Key())) { old = bnd; break; } } } } if (old == null) return; this.Del(old); old.Ipts().Clear(); if (ary == IptArg_.Ary_empty) return; // "unbind"; exit after deleting; DATE:2014-05-13 old.Ipts().Add_many((Object[])ary); this.Add(old); } public void Del_by_key(String key) {Del_by(true, key);} public void Del_by_ipt(IptArg ipt) { if (IptArg_.Is_null_or_none(ipt)) return; Del_by(false, ipt.Key()); } private void Del_by(boolean del_by_key, String del_key) { int regy_len = regy.length; List_adp deleted = List_adp_.New(); for (int i = 0; i < regy_len; i++) { IptBndHash list = regy[i]; int list_len = list.Count(); for (int j = 0; j < list_len; j++) { IptBndListItm bnds = list.Get_at(j); int bnds_len = bnds.Count(); for (int k = 0; k < bnds_len; k++) { IptBnd itm_bnd = bnds.Get_at(k); if (del_by_key) { if (String_.Eq(del_key, itm_bnd.Key())) { deleted.Add(itm_bnd); } } else { if (itm_bnd.Ipts().Count() != 1) continue; // only delete if bnd has 1 ipt; should only be called by xowa which does 1 bnd per ipt IptArg itm_ipt = (IptArg)itm_bnd.Ipts().Get_at(0); if (String_.Eq(del_key, itm_ipt.Key())) deleted.Add(itm_bnd); } } } } int deleted_len = deleted.Count(); for (int i = 0; i < deleted_len; i++) { IptBnd bnd = (IptBnd)deleted.Get_at(i); this.Del(bnd); bnd.Ipts().Clear(); } } public void Del(IptBnd bnd) { for (IptBndHash list : regy) { if (IptEventType_.Has(bnd.EventTypes(), list.EventType())) { list.Del(bnd); } } for (int i = 0; i < bnd.Ipts().Count(); i++) { IptArg arg = (IptArg)bnd.Ipts().Get_at(i); chainMgr.Del(arg); } } public boolean Process(IptEventData evData) { IptBndHash list = regy[AryIdx(evData.EventType())]; String key = evData.EventArg().Key(); if (!String_.Eq(chainMgr.ActiveKey(), "")) key = chainMgr.ActiveKey() + key; IptBndListItm itm = list.Get_by(key); String chainP = ""; if (evData.EventType() == IptEventType_.KeyDown) { chainP = chainMgr.Process(evData.EventArg()); if (!String_.Eq(chainP, "") && itm == null) UsrDlg_.Instance.Note("cancelled... {0}", chainP); } if (itm == null) { return false; } return itm.Exec(evData); } public Object Srl(GfoMsg owner) { GfoMsg m = GfoMsg_.srl_(owner, "mgr"); for (int i = 0; i < hash.Count(); i++) ((IptBnd)hash.Get_at(i)).Srl(m); return this; } IptArgChainMgr chainMgr = new IptArgChainMgr(); Ordered_hash hash = Ordered_hash_.New(); IptEventType curTypes = IptEventType_.None; public static IptBndMgr new_() {return new IptBndMgr();} IptBndHash[] regy = new IptBndHash[8]; IptBndMgr() {ClearLists();} void ClearLists(){ MakeList(IptEventType_.KeyDown); MakeList(IptEventType_.KeyUp); MakeList(IptEventType_.KeyPress); MakeList(IptEventType_.MouseMove); MakeList(IptEventType_.MouseDown); MakeList(IptEventType_.MouseUp); MakeList(IptEventType_.MouseWheel); MakeList(IptEventType_.MousePress); } void MakeList(IptEventType eventType) {regy[AryIdx(eventType)] = new IptBndHash(eventType);} static int AryIdx(IptEventType eventType) { int v = eventType.Val(); if (v == IptEventType_.KeyDown.Val()) return 0; else if (v == IptEventType_.KeyUp.Val()) return 1; else if (v == IptEventType_.KeyPress.Val()) return 2; else if (v == IptEventType_.MouseDown.Val()) return 3; else if (v == IptEventType_.MouseUp.Val()) return 4; else if (v == IptEventType_.MouseMove.Val()) return 5; else if (v == IptEventType_.MouseWheel.Val()) return 6; else if (v == IptEventType_.MousePress.Val()) return 7; else throw Err_.new_unhandled(v); } } class IptBndHash implements SrlAble { private IptBndListItm wildcard_list; public IptEventType EventType() {return eventType;} IptEventType eventType; public int Count() {return hash.Count();} public IptBndListItm Get_by(String key) {return wildcard_list == null ? (IptBndListItm)hash.Get_by(key) : wildcard_list;} public IptBndListItm Get_at(int i) {return (IptBndListItm)hash.Get_at(i);} public void Add(IptBnd bnd) { for (int i = 0; i < bnd.Ipts().Count(); i++) { IptArg arg = (IptArg)bnd.Ipts().Get_at(i); if (!IptArg_.EventType_match(arg, eventType)) continue; // bnd may have multiple ipts of different evTypes; only add bnd if evType matches if (String_.Eq(arg.Key(), IptArg_.Wildcard_key)) { if (wildcard_list == null) wildcard_list = new IptBndListItm(IptArg_.Wildcard_key); wildcard_list.Add(bnd); } else { IptBndListItm itm = (IptBndListItm)hash.Get_by(arg.Key()); if (itm == null) { itm = new IptBndListItm(arg.Key()); hash.Add(arg.Key(), itm); } itm.Add(bnd); } } } public void Del(IptBnd bnd) { for (int i = 0; i < bnd.Ipts().Count(); i++) { IptArg arg = (IptArg)bnd.Ipts().Get_at(i); if (!IptArg_.EventType_match(arg, eventType)) continue; // bnd may have multiple ipts of different evTypes; only add bnd if evType matches hash.Del(arg.Key()); } } public Object Srl(GfoMsg owner) { GfoMsg m = GfoMsg_.srl_(owner, "list").Add("eventType", eventType.Name()); for (int i = 0; i < hash.Count(); i++) ((IptBndListItm)hash.Get_at(i)).Srl(m); return this; } Ordered_hash hash = Ordered_hash_.New(); public IptBndHash(IptEventType eventType) {this.eventType = eventType;} } class IptBndListItm implements SrlAble { public String IptKey() {return iptKey;} private String iptKey; public int Count() {return list.Count();} public IptBnd Get_at(int i) {return (IptBnd)list.Get_at(i);} public void Add(IptBnd bnd) {list.Add_at(0, bnd);} public boolean Exec(IptEventData evData) { for (int i = 0; i < list.Count(); i++) { IptBnd bnd = (IptBnd)list.Get_at(i); try {bnd.Exec(evData);} catch (Exception exc) { UsrDlg_.Instance.Stop(UsrMsg.new_("Error while processing event").Add("bnd", SrlAble_.To_str(bnd)).Add("exc", Err_.Message_lang(exc))); return false; } if (evData.CancelIteration) break; } return true; } public Object Srl(GfoMsg owner) { GfoMsg m = GfoMsg_.srl_(owner, "itm").Add("iptKey", iptKey); for (int i = 0; i < list.Count(); i++) ((IptBnd)list.Get_at(i)).Srl(m); return this; } List_adp list = List_adp_.New(); public IptBndListItm(String iptKey) {this.iptKey = iptKey;} } class IptArgChainMgr { public void Clear() {regy.Clear();} public String Process(IptArg arg) { // if (String_.Eq(arg.Key(), "key_7")) return ""; Hash_adp hash = (Hash_adp)active.Get_by(arg.Key()); if (hash == null) { active = regy; String r = activeKey; activeKey = ""; return r; } active = hash; activeKey = activeKey + arg.Key() + ","; UsrDlg_.Instance.Note("{0} pressed...", activeKey); return ""; } public String ActiveKey() {return activeKey;} String activeKey = ""; public IptArgChainMgr() {active = regy;} Hash_adp active; public void Add(IptArg arg) { if (arg.getClass() != IptKeyChain.class) return; IptKeyChain chain = (IptKeyChain)arg; Add_recur(regy, chain.Chained(), 0); } public void Del(IptArg arg) { if (arg.getClass() != IptKeyChain.class) return; IptKeyChain chain = (IptKeyChain)arg; Del_recur(regy, chain.Chained(), 0); } void Add_recur(Hash_adp cur, IptArg[] ary, int i) { if (i == ary.length - 1) return; // -1 b/c last should not be registered; ex: key.a,key.b should register key.a only IptArg ipt = ary[i]; Hash_adp next = (Hash_adp)cur.Get_by(ipt.Key()); if (next == null) { next = Hash_adp_.New(); cur.Add(ipt.Key(), next); } Add_recur(next, ary, i + 1); }// a,b,c void Del_recur(Hash_adp cur, IptArg[] ary, int i) { IptArg ipt = ary[i]; if (i == ary.length - 1) { cur.Del(ipt.Key()); return; // -1 b/c last should not be registered; ex: key.a,key.b should register key.a only } Hash_adp next = (Hash_adp)cur.Get_by(ipt.Key()); if (next == null) { return; } Del_recur(next, ary, i + 1); if (cur.Count() == 1) cur.Clear(); } Hash_adp regy = Hash_adp_.New(); }