You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnosygnu_xowa/150_gfui/src_200_ipt/gplx/gfui/IptBndMgr.java

294 lines
11 KiB

9 years ago
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.gfui; import gplx.*;
public class IptBndMgr implements SrlAble {
@gplx.Internal protected 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);}
@gplx.Internal protected 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);
}
}
@gplx.Internal protected List_adp Cfgs() {return cfgs;} List_adp cfgs = List_adp_.new_();
@gplx.Internal protected 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._.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);
}
}
@gplx.Internal protected 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_._.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;
9 years ago
else throw Err_.new_unhandled(v);
9 years ago
}
}
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_._.Stop(UsrMsg.new_("Error while processing event").Add("bnd", SrlAble_.XtoStr(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_._.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_();
}