mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
287 lines
10 KiB
Java
287 lines
10 KiB
Java
/*
|
|
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);}
|
|
@gplx.Internal protected 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().FetchAt(i);
|
|
chainMgr.Add(arg);
|
|
}
|
|
}
|
|
@gplx.Internal protected ListAdp Cfgs() {return cfgs;} ListAdp cfgs = ListAdp_.new_();
|
|
@gplx.Internal protected void Cfgs_delAll() {
|
|
ListAdp del = ListAdp_.new_();
|
|
for (int i = 0; i < cfgs.Count(); i++) {
|
|
IptCfgPtr ptr = (IptCfgPtr)cfgs.FetchAt(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.GetAt(j);
|
|
for (int k = 0; k < itmList.Count(); k++) {
|
|
IptBnd bnd = itmList.FetchAt(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.FetchAt(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.GetAt(j);
|
|
for (int i = 0; i < itmList.Count(); i++) {
|
|
IptBnd bnd = itmList.FetchAt(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().AddMany((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;
|
|
ListAdp deleted = ListAdp_.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.GetAt(j);
|
|
int bnds_len = bnds.Count();
|
|
for (int k = 0; k < bnds_len; k++) {
|
|
IptBnd itm_bnd = bnds.FetchAt(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().FetchAt(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.FetchAt(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().FetchAt(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(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.FetchAt(i)).Srl(m);
|
|
return this;
|
|
}
|
|
IptArgChainMgr chainMgr = new IptArgChainMgr();
|
|
OrderedHash hash = OrderedHash_.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_.unhandled(v);
|
|
}
|
|
}
|
|
class IptBndHash implements SrlAble {
|
|
public IptEventType EventType() {return eventType;} IptEventType eventType;
|
|
public int Count() {return hash.Count();}
|
|
public IptBndListItm Get(String iptKey) {return (IptBndListItm)hash.Fetch(iptKey);}
|
|
public IptBndListItm GetAt(int i) {return (IptBndListItm)hash.FetchAt(i);}
|
|
public void Add(IptBnd bnd) {
|
|
for (int i = 0; i < bnd.Ipts().Count(); i++) {
|
|
IptArg arg = (IptArg)bnd.Ipts().FetchAt(i);
|
|
if (!IptArg_.EventType_match(arg, eventType)) continue; // bnd may have multiple ipts of different evTypes; only add bnd if evType matches
|
|
IptBndListItm itm = (IptBndListItm)hash.Fetch(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().FetchAt(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.FetchAt(i)).Srl(m);
|
|
return this;
|
|
}
|
|
OrderedHash hash = OrderedHash_.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 FetchAt(int i) {return (IptBnd)list.FetchAt(i);}
|
|
public void Add(IptBnd bnd) {list.AddAt(0, bnd);}
|
|
public boolean Exec(IptEventData evData) {
|
|
for (int i = 0; i < list.Count(); i++) {
|
|
IptBnd bnd = (IptBnd)list.FetchAt(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.FetchAt(i)).Srl(m);
|
|
return this;
|
|
}
|
|
ListAdp list = ListAdp_.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 "";
|
|
HashAdp hash = (HashAdp)active.Fetch(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;}
|
|
HashAdp 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(HashAdp 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];
|
|
HashAdp next = (HashAdp)cur.Fetch(ipt.Key());
|
|
if (next == null) {
|
|
next = HashAdp_.new_();
|
|
cur.Add(ipt.Key(), next);
|
|
}
|
|
Add_recur(next, ary, i + 1);
|
|
}// a,b,c
|
|
void Del_recur(HashAdp 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
|
|
}
|
|
HashAdp next = (HashAdp)cur.Fetch(ipt.Key());
|
|
if (next == null) {
|
|
return;
|
|
}
|
|
Del_recur(next, ary, i + 1);
|
|
if (cur.Count() == 1)
|
|
cur.Clear();
|
|
}
|
|
HashAdp regy = HashAdp_.new_();
|
|
}
|