forked from pquiring/javaforce
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathComponent.java
More file actions
executable file
·795 lines (730 loc) · 21.4 KB
/
Copy pathComponent.java
File metadata and controls
executable file
·795 lines (730 loc) · 21.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
package javaforce.webui;
/** Base class for all components.
*
* @author pquiring
*/
import java.util.*;
import java.net.*;
import javaforce.*;
import javaforce.webui.event.*;
public abstract class Component {
public String id;
public Container parent;
public WebUIClient client;
public String name;
public ArrayList<String> classes = new ArrayList<String>();
public HashMap<String, String> attrs = new HashMap<String, String>();
public HashMap<String, String> styles = new HashMap<String, String>();
public int x,y,width,height; //position and size (updated with mouseenter event)
public int clr = 0, backclr = 0xcccccc, borderclr = 0;
// private boolean drag;
private int drag_type;
private int x1, y1, x2, y2; //drag bounds
private ArrayList<Event> pendingEvents;
//define constants
public static final int VERTICAL = 1;
public static final int HORIZONTAL = 2;
public static final int LEFT = 1;
public static final int CENTER = 2;
public static final int RIGHT = 3;
public static final int TOP = 4;
public static final int BOTTOM = 5;
//overflow constants
public static final int VISIBLE = 10;
public static final int HIDDEN = 11;
public static final int SCROLL = 12;
public static final int AUTO = 13;
public static class Event {
public String msg;
public String[] args;
}
private static class OnEvent {
public String event;
public String js;
}
public ArrayList<OnEvent> events = new ArrayList<OnEvent>();
/** Component constructor.
*/
public Component() {
}
/** Gets Component's ID.*/
public String getID() {
return id;
}
/** Sets Component's name. */
public void setName(String name) {
this.name = name;
}
/** Gets Component's name. */
public String getName() {
return name;
}
/** Returns Component's parent Container. */
public Container getParent() {
return parent;
}
/** Returns Component's top-most parent Container. */
public Container getTopParent() {
Container top = parent;
do {
Container next = top.getParent();
if (next == null) return top;
top = next;
} while (true);
}
/** Provides the client (connection to web browser side) and init other variables. */
public void setClient(WebUIClient client) {
if (id != null) return;
this.client = client;
id = "c" + client.getNextID();
}
/** Returns client (waits until Component is presented to user). */
public WebUIClient getClient() {
while (client == null) {
JF.sleep(50);
}
return client;
}
/** Perform any initialization with the client.
* Containers should call init() on all sub-components.
*/
public void init() {}
/** Perform any post loading events.
* Containers should call events() on all sub-components.
*/
public void events() {
if (pendingEvents != null) {
for(Event event : pendingEvents) {
sendEvent(event.msg, event.args);
}
}
}
/** Returns HTML to render component. */
public abstract String html();
private HashMap<String,Object> map = new HashMap<>();
/** Set user define property. */
public void setProperty(String key, Object value) {
map.put(key, value);
}
/** Get user define property. */
public Object getProperty(String key) {
return map.get(key);
}
/** Invokes getClient().sendEvent() */
public void sendEvent(String msg, String[] args) {
if (client != null) {
client . sendEvent(id, msg, args);
} else {
if (pendingEvents == null) pendingEvents = new ArrayList<>();
Event event = new Event();
event.msg = msg;
event.args = args;
pendingEvents.add(event);
}
}
/** Invokes getClient().sendData() */
public void sendData(byte[] data) {
if (client != null) {
client . sendData(data);
}
}
public void sendOnResize() {
sendEvent("onresize", null);
}
public void setClass(String cls) {
classes.clear();
classes.add(cls);
sendEvent("setclass", new String [] {"cls=" + cls});
}
public boolean hasClass(String cls) {
return classes.contains(cls);
}
public void addClass(String cls) {
if (hasClass(cls)) return;
classes.add(cls);
sendEvent("addclass", new String[] {"cls=" + cls});
}
public void removeClass(String cls) {
classes.remove(cls);
sendEvent("delclass", new String[] {"cls=" + cls});
}
public void setFlex(boolean state) {
if (state) addClass("pad"); else removeClass("pad");
}
public boolean hasAttr(String attr) {
return attrs.containsKey(attr);
}
public void addAttr(String attr, String value) {
attrs.put(attr, value);
}
public void removeAttr(String attr) {
attrs.remove(attr);
}
public boolean hasStyle(String style) {
return styles.containsKey(style);
}
public void setStyle(String style, String value) {
styles.put(style, value);
}
public void removeStyle(String style) {
styles.remove(style);
}
public String getStyle(String style) {
return styles.get(style);
}
public void setFontSize(int size) {
setStyle("font-size", size + "pt");
}
public void setAlign(int align) {
switch (align) {
case LEFT:
setStyle("text-align", "left");
break;
case CENTER:
setStyle("text-align", "center");
break;
case RIGHT:
setStyle("text-align", "right");
break;
}
}
public void setVerticalAlign(int align) {
switch (align) {
case TOP:
setStyle("vertical-align", "top");
break;
case CENTER:
setStyle("vertical-align", "middle");
break;
case BOTTOM:
setStyle("vertical-align", "bottom");
break;
}
}
private OnEvent getEvent(String onX) {
int cnt = events.size();
for(int a=0;a<cnt;a++) {
OnEvent event = events.get(a);
if (event.event.equals(onX)) return event;
}
return null;
}
public void addEvent(String onX, String js) {
OnEvent event;
event = getEvent(onX);
if (event != null) {
event.js = js.replaceAll("'", "\"");
} else {
event = new OnEvent();
event.event = onX;
event.js = js.replaceAll("'", "\"");
events.add(event);
}
}
public String getEvents() {
StringBuilder sb = new StringBuilder();
int cnt = events.size();
for(int a=0;a<cnt;a++) {
sb.append(' ');
OnEvent event = events.get(a);
sb.append(event.event);
sb.append("='");
sb.append(event.js);
sb.append("'");
}
return sb.toString();
}
public void requestPos() {
sendEvent("getpos", null);
}
public void requestPosSize() {
sendEvent("getpossize", null);
}
public void requestSize() {
sendEvent("getsize", null);
}
public void setSize(int width, int height) {
this.width = width;
this.height = height;
if (width > 0) {setStyle("width", width + "px");}
if (height > 0) {setStyle("height", height + "px");}
sendEvent("setsize", new String[] {"w=" + width, "h=" + height});
}
public int getX() {
return x;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
setStyle("width", width + "px");
sendEvent("setwidth", new String[] {"w=" + width});
}
public void setMaxWidth() {
setStyle("width", "100%");
}
public void setAutoWidth() {
setStyle("width", "auto");
}
public int getY() {
return y;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
setStyle("height", height + "px");
sendEvent("setheight", new String[] {"h=" + height});
}
public void setMaxHeight() {
setStyle("height", "100%");
}
public void setAutoHeight() {
setStyle("height", "auto");
}
public void setColor(int clr) {
this.clr = clr;
String style = String.format("#%06x", clr);
setStyle("color", style);
sendEvent("setclr", new String[] {"clr=" + style});
}
public int getColor() {
return clr;
}
public void setBackColor(int clr) {
this.backclr = clr;
String style = String.format("#%06x", clr);
setStyle("background-color", style);
sendEvent("setbackclr", new String[] {"clr=" + style});
}
public int getBackColor() {
return backclr;
}
public void setBorderColor(int clr) {
this.borderclr = clr;
String style = String.format("#%06x", clr);
setStyle("border-color", style);
sendEvent("setborderclr", new String[] {"clr=" + style});
}
public int getBorderColor() {
return borderclr;
}
/** Returns all attributes defined for a component (id, attrs, class, styles) */
public String getAttrs() {
StringBuilder sb = new StringBuilder();
sb.append(" id='" + id + "'");
if (attrs.size() > 0) {
int size = attrs.size();
String[] keys = attrs.keySet().toArray(new String[size]);
String[] vals = attrs.values().toArray(new String[size]);
for(int a=0;a<size;a++) {
if (vals[a] == null) {
sb.append(" " + keys[a]);
} else {
sb.append(" " + keys[a] + "='" + vals[a] + "'");
}
}
}
if (classes.size() > 0) {
sb.append(" class='");
for(int a=0;a<classes.size();a++) {
if (a > 0) sb.append(' ');
sb.append(classes.get(a));
}
sb.append("'");
}
sb.append(getEvents());
if (styles.size() > 0) {
sb.append(" style='");
int size = styles.size();
String[] keys = styles.keySet().toArray(new String[size]);
String[] vals = styles.values().toArray(new String[size]);
for(int a=0;a<size;a++) {
sb.append(keys[a] + ":" + vals[a] + ";");
}
sb.append("'");
}
return sb.toString();
}
private boolean isVisible = true;
/** Sets component to initial invisible. */
protected void initInvisible() {
isVisible = false;
setStyle("display", "none");
}
public void setVisible(boolean state) {
isVisible = state;
if (state) {
sendEvent("display", new String[] {"val="}); //reset to css rules
setStyle("display", "");
} else {
sendEvent("display", new String[] {"val=none"});
setStyle("display", "none");
}
for(int a=0;a<visible.length;a++) {
visible[a].onVisible(this, state);
}
}
public boolean isVisible() {
return isVisible;
}
public void setPosition(int x, int y) {
sendEvent("setpos", new String[] {"x=" + x, "y=" + y});
this.x = x;
this.y = y;
setStyle("left", Integer.toString(x));
setStyle("top", Integer.toString(y));
}
public void setReadonly(boolean state) {
if (state) {
addAttr("readonly", "readonly");
} else {
removeAttr("readonly");
}
}
public void setDisabled(boolean state) {
if (state) {
addAttr("disabled", "true");
} else {
removeAttr("disabled");
}
}
public void setBorderGray(boolean state) {
if (state)
addClass("bordergray");
else
removeClass("bordergray");
}
public void setBorder(boolean state) {
if (state)
addClass("border");
else
removeClass("border");
}
public void setFocus() {
sendEvent("focus", null);
}
public static final int DRAG_MOVE = 1;
public static final int DRAG_NS = 2;
public static final int DRAG_EW = 3;
public static final int DRAG_NESW = 4;
public static final int DRAG_NWSE = 5;
/** Enables dragging a component.
* drag_type = DRAG_... types (sets cursor type)
* coords = (x1,y1)-(x2,y2) = dragging bounds (-1=no bounds)
*/
public void enableDragging(int drag_type, int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
switch (drag_type) {
case DRAG_MOVE: addClass("drag_move"); break;
case DRAG_NS: addClass("drag_ns_resize"); break;
case DRAG_EW: addClass("drag_ew_resize"); break;
case DRAG_NESW: addClass("drag_nesw_resize"); break;
case DRAG_NWSE: addClass("drag_nwse_resize"); break;
}
sendEvent("enabledrag", new String[] {"x1=" + x1,"y1=" + y1,"x2=" + x2,"y2=" + y2, "type=" + drag_type});
}
public String encode(String str) {
try {
return URLEncoder.encode(str, "utf-8");
} catch (Exception e) {
return null;
}
}
public String decode(String url) {
try {
return URLDecoder.decode(url, "utf-8");
} catch (Exception e) {
return null;
}
}
public String toString() {
return getClass().getName() + ":" + id;
}
//event handlers
/** Dispatches event. */
public void dispatchEvent(String event, String[] args) {
MouseEvent me = new MouseEvent();
KeyEvent ke = new KeyEvent();
if (args != null) {
for(int a=0;a<args.length;a++) {
if (args[a].equals("ck=true")) {
me.ctrlKey = true;
ke.ctrlKey = true;
}
if (args[a].equals("ak=true")) {
me.altKey = true;
ke.altKey = true;
}
if (args[a].equals("sk=true")) {
me.shiftKey = true;
ke.shiftKey = true;
}
}
}
switch (event) {
case "click":
onClick(args, me);
break;
case "action":
action();
break;
case "changed":
onChanged(args);
break;
case "mousedown":
onMouseDown(args);
break;
case "mouseup":
onMouseUp(args);
break;
case "mousemove":
onMouseMove(args);
break;
case "mouseenter":
onMouseEnter(args);
break;
case "keydown":
onKeyDown(args, ke);
break;
case "keyup":
onKeyUp(args, ke);
break;
case "possize":
onPosSize(args);
break;
case "pos":
onPos(args);
break;
case "size":
onSize(args);
break;
case "onloaded":
onLoaded(args);
break;
case "drawrect":
onDrawRect(args);
break;
default:
onEvent(event, args);
break;
}
}
/** Process custom events. */
public void onEvent(String event, String[] args) {}
public void onPosSize(String[] args) {
for(int a=0;a<moved.length;a++) {
moved[a].onMoved(this, x, y);
}
for(int a=0;a<resized.length;a++) {
resized[a].onResized(this, width, height);
}
for(int c=0;c<args.length;c++) {
String a = args[c];
if (a.startsWith("x=")) {
x = Integer.valueOf(a.substring(2));
}
if (a.startsWith("y=")) {
y = Integer.valueOf(a.substring(2));
}
if (a.startsWith("w=")) {
width = Integer.valueOf(a.substring(2));
}
if (a.startsWith("h=")) {
height = Integer.valueOf(a.substring(2));
}
}
}
public void onSize(String[] args) {
for(int c=0;c<args.length;c++) {
String a = args[c];
if (a.startsWith("w=")) {
width = Integer.valueOf(a.substring(2));
}
if (a.startsWith("h=")) {
height = Integer.valueOf(a.substring(2));
}
}
for(int a=0;a<resized.length;a++) {
resized[a].onResized(this, width, height);
}
}
public void onPos(String[] args) {
for(int c=0;c<args.length;c++) {
String a = args[c];
if (a.startsWith("x=")) {
x = Integer.valueOf(a.substring(2));
}
if (a.startsWith("y=")) {
y = Integer.valueOf(a.substring(2));
}
}
for(int a=0;a<moved.length;a++) {
moved[a].onMoved(this, x, y);
}
}
protected void onLoaded(String[] args) {
for(int a=0;a<loaded.length;a++) {
loaded[a].loaded(this);
}
}
private Loaded[] loaded = new Loaded[0];
public void addLoadedListener(Loaded handler) {
loaded = Arrays.copyOf(loaded, loaded.length + 1);
loaded[loaded.length-1] = handler;
}
protected void onClick(String[] args, MouseEvent me) {
if (WebUIServer.debug) JFLog.log("onClick:" + this + ":" + click.length);
for(int a=0;a<click.length;a++) {
click[a].onClick(me, this);
}
}
private Click[] click = new Click[0];
public void addClickListener(Click handler) {
addEvent("onclick", "onClick(event, this);");
click = Arrays.copyOf(click, click.length + 1);
click[click.length-1] = handler;
}
public void click() {
onClick(null, new MouseEvent());
}
protected void onMouseUp(String[] args) {
for(int a=0;a<mouseUp.length;a++) {
mouseUp[a].onMouseUp(this);
}
}
private MouseUp[] mouseUp = new MouseUp[0];
public void addMouseUpListener(MouseUp handler) {
addEvent("onmouseup", "onMouseUp(event, this);");
mouseUp = Arrays.copyOf(mouseUp, mouseUp.length + 1);
mouseUp[mouseUp.length-1] = handler;
}
protected void onMouseDown(String[] args) {
for(int a=0;a<mouseDown.length;a++) {
mouseDown[a].onMouseDown(this);
}
}
private MouseDown[] mouseDown = new MouseDown[0];
public void addMouseDownListener(MouseDown handler) {
addEvent("onmousedown", "onMouseDown(event, this);");
mouseDown = Arrays.copyOf(mouseDown, mouseDown.length + 1);
mouseDown[mouseDown.length-1] = handler;
}
protected void onMouseMove(String[] args) {
for(int a=0;a<mouseMove.length;a++) {
mouseMove[a].onMouseMove(this);
}
}
private MouseMove[] mouseMove = new MouseMove[0];
public void addMouseMoveListener(MouseMove handler) {
addEvent("onmousemove", "onMouseMove(event, this);");
mouseMove = Arrays.copyOf(mouseMove, mouseMove.length + 1);
mouseMove[mouseMove.length-1] = handler;
}
protected void onMouseEnter(String[] args) {
for(int a=0;a<mouseMove.length;a++) {
mouseMove[a].onMouseMove(this);
}
}
private MouseEnter[] mouseEnter = new MouseEnter[0];
public void addMouseEnterListener(MouseEnter handler) {
//TODO : addEvent() ???
mouseEnter = Arrays.copyOf(mouseEnter, mouseEnter.length + 1);
mouseEnter[mouseEnter.length-1] = handler;
}
protected void onKeyUp(String[] args, KeyEvent ke) {
for(int a=0;a<keyUp.length;a++) {
keyUp[a].onKeyUp(ke, this);
}
}
private KeyUp[] keyUp = new KeyUp[0];
public void addKeyUpListener(KeyUp handler) {
addEvent("onkeyup", "onKeyUp(event, this);");
keyUp = Arrays.copyOf(keyUp, keyUp.length + 1);
keyUp[keyUp.length-1] = handler;
}
protected void onKeyDown(String[] args, KeyEvent ke) {
for(int a=0;a<keyDown.length;a++) {
keyDown[a].onKeyDown(ke, this);
}
}
private KeyDown[] keyDown = new KeyDown[0];
public void addKeyDownListener(KeyDown handler) {
addEvent("onkeydown", "onKeyDown(event, this);");
keyDown = Arrays.copyOf(keyDown, keyDown.length + 1);
keyDown[keyDown.length-1] = handler;
}
protected void onChanged(String[] args) {
for(int a=0;a<changed.length;a++) {
changed[a].onChanged(this);
}
}
private Changed[] changed = new Changed[0];
public void addChangedListener(Changed handler) {
changed = Arrays.copyOf(changed, changed.length + 1);
changed[changed.length-1] = handler;
}
private Visible[] visible = new Visible[0];
public void addVisibleListener(Visible handler) {
visible = Arrays.copyOf(visible, visible.length + 1);
visible[visible.length-1] = handler;
}
private Validate[] validate = new Validate[0];
public void addValidateListener(Validate handler) {
validate = Arrays.copyOf(validate, validate.length + 1);
validate[validate.length-1] = handler;
}
public boolean validate() {
for(int a=0;a<validate.length;a++) {
if (!validate[a].validate(this)) return false;
}
return true;
}
private Action[] action = new Action[0];
public void addActionListener(Action handler) {
action = Arrays.copyOf(action, action.length + 1);
action[action.length-1] = handler;
}
public void action() {
for(int a=0;a<action.length;a++) {
action[a].action(this);
}
}
private Resized[] resized = new Resized[0];
public void addResizedListener(Resized handler) {
addEvent("onresize", "onResize(event, this);");
resized = Arrays.copyOf(resized, resized.length + 1);
resized[resized.length-1] = handler;
}
private Moved[] moved = new Moved[0];
public void addMovedListener(Moved handler) {
addEvent("onmoved", "onMoved(event, this);");
moved = Arrays.copyOf(moved, moved.length + 1);
moved[moved.length-1] = handler;
}
public void onDrawRect(String[] args) {
Rectangle rect = new Rectangle();
for(int c=0;c<args.length;c++) {
String a = args[c];
if (a.startsWith("x=")) {
rect.x = Integer.valueOf(a.substring(2));
}
if (a.startsWith("y=")) {
rect.y = Integer.valueOf(a.substring(2));
}
if (a.startsWith("w=")) {
rect.width = Integer.valueOf(a.substring(2));
}
if (a.startsWith("h=")) {
rect.height = Integer.valueOf(a.substring(2));
}
}
onDrawRect(rect);
}
public void onDrawRect(Rectangle rect) {}
}