Skip to content

Commit 56ff671

Browse files
committed
Added support for slots, which is a powerful new way to inject and override view content from the controller.
1 parent feb76f4 commit 56ff671

File tree

789 files changed

+13425
-2545
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

789 files changed

+13425
-2545
lines changed

.idea/workspace.xml

Lines changed: 78 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.codename1.rad.attributes;
2+
3+
import com.codename1.rad.controllers.ViewController;
4+
import com.codename1.rad.models.Attribute;
5+
6+
public class ViewControllerAttribute extends Attribute<ViewController> {
7+
public ViewControllerAttribute(ViewController value) {
8+
super(value);
9+
}
10+
}

common/src/main/java/com/codename1/rad/controllers/ActionSupport.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ public static void dispatchEvent(ActionEvent evt) {
8585
}
8686
}
8787
}
88+
89+
public static <T extends ActionEvent> T as(ActionEvent e, Class<T> type) {
90+
if (type.isAssignableFrom(e.getClass())) {
91+
return (T)e;
92+
}
93+
return null;
94+
}
8895

8996

9097

common/src/main/java/com/codename1/rad/controllers/ApplicationController.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,36 @@ public Form getCurrentForm() {
160160
}
161161
public static class StopEvent extends ApplicationEvent{}
162162
public static class DestroyEvent extends ApplicationEvent{}
163+
164+
public FormController getCurrentFormController() {
165+
Form f = CN.getCurrentForm();
166+
if (f == null) {
167+
return null;
168+
}
169+
ViewController vc = ViewController.getViewController(f);
170+
if (vc == null) {
171+
return null;
172+
}
173+
return vc.getFormController();
174+
}
175+
176+
public String getCurrentPath() {
177+
FormController fc = getCurrentFormController();
178+
if (fc == null) {
179+
return "";
180+
}
181+
return fc.getPathString("/");
182+
}
183+
184+
private FormController currentFormController;
185+
186+
@Override
187+
public void actionPerformed(ControllerEvent evt) {
188+
super.actionPerformed(evt);
189+
if (!evt.isConsumed()) {
190+
evt.as(FormController.FormShownEvent.class, fse -> {
191+
currentFormController = fse.getSourceFormController();
192+
});
193+
}
194+
}
163195
}

common/src/main/java/com/codename1/rad/controllers/Controller.java

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@
55
*/
66
package com.codename1.rad.controllers;
77

8+
import com.codename1.rad.events.FillSlotEvent;
89
import com.codename1.rad.models.Entity;
10+
import com.codename1.rad.models.Tag;
911
import com.codename1.rad.nodes.ActionNode;
1012
import com.codename1.rad.nodes.ActionNode.ActionNodeEvent;
11-
import com.codename1.rad.nodes.Node;
1213
import com.codename1.rad.nodes.ViewNode;
1314
import com.codename1.rad.ui.EntityView;
15+
import com.codename1.rad.ui.Slot;
16+
import com.codename1.ui.Component;
1417
import com.codename1.ui.events.ActionListener;
1518
import com.codename1.ui.util.EventDispatcher;
19+
import com.codename1.util.SuccessCallback;
20+
1621
import java.util.ArrayList;
1722
import java.util.HashMap;
1823
import java.util.List;
@@ -142,6 +147,8 @@ public void addActionListener(ActionNode action, ActionListener<ActionNodeEvent>
142147
addEventListener(h.wrapperListener);
143148

144149
}
150+
151+
145152

146153
public void removeActionListener(ActionNode action, ActionListener<ActionNodeEvent> l) {
147154
ActionHandler h = findActionHandler(action, l);
@@ -303,6 +310,12 @@ public <T> T lookup(Class<T> type) {
303310
return null;
304311
}
305312

313+
/**
314+
* Obtains a lookup as an entity. This is a a convenient wrapper around {@link #lookup(Class)} that can
315+
* be used in cases where you expect to receive an Entity.
316+
* @param type
317+
* @return
318+
*/
306319
public Entity lookupEntity(Class type) {
307320
return (Entity)lookup(type);
308321
}
@@ -319,13 +332,117 @@ public void addLookup(Object obj) {
319332
lookups.put(obj.getClass(), obj);
320333
}
321334

335+
/**
336+
* Adds a lookup with a specific clas as a key.
337+
* @param type The class to use as the key of the lookup.
338+
* @param object The value of the lookup.
339+
* @param <T> The type of object.
340+
*/
322341
public <T> void addLookup(Class<T> type, T object) {
323342
if (object == null) return;
324343
if (lookups == null) {
325344
lookups = new HashMap<>();
326345
}
327346
lookups.put(type, object);
328347
}
348+
349+
/**
350+
* Looks up an object starting at the parent controller.
351+
* @param type The type of object to lookup.
352+
* @param <T> The type of object to lookup.
353+
* @return A matching object or null.
354+
*/
355+
public <T> T parentLookup(Class<T> type) {
356+
if (parent == null) {
357+
return null;
358+
}
359+
return parent.lookup(type);
360+
}
361+
362+
/**
363+
* Looks up an entity starting at the parent controller.
364+
* @param type The type of the entity to look for.
365+
* @return A matching Entity or null.
366+
*/
367+
public Entity parentLookupEntity(Class type) {
368+
if (parent == null) return null;
369+
return parent.lookupEntity(type);
370+
}
371+
372+
/**
373+
* Calls {@link #withLookup(Class, SuccessCallback)} on the parent controller.
374+
* @param type The type of object we're looking for.
375+
* @param callback Callback executed only if lookup finds something.
376+
* @param <T> The type of object to look for.
377+
* @return True if lookup finds something.
378+
*/
379+
public <T> boolean withParentLookup(Class<T> type, SuccessCallback<T> callback) {
380+
T o = parentLookup(type);
381+
if (o == null) return false;
382+
callback.onSucess(o);
383+
return true;
384+
}
385+
386+
/**
387+
* Calls {@link #lookupEntity(Class)} on the Parent controller.
388+
* @param type The typeof entity to look for. This may also be an Interface.
389+
* @param callback Callback executed only if a matching entity is found.
390+
* @return True if entity is found.
391+
*/
392+
public boolean withParentLookupEntity(Class type, SuccessCallback<Entity> callback) {
393+
Entity o = parentLookupEntity(type);
394+
if (o == null) return false;
395+
callback.onSucess(o);
396+
return true;
397+
398+
}
399+
400+
/**
401+
* Does lookup for object of given type. If found, it passes it to the given callback.
402+
* @param type The type of object to lookup.
403+
* @param callback Callback executed only if the lookup is found.
404+
* @param <T> The type of object to look for.
405+
* @return True if the lookup is found.
406+
*/
407+
public <T> boolean withLookup(Class<T> type, SuccessCallback<T> callback) {
408+
T o = lookup(type);
409+
if (o == null) return false;
410+
callback.onSucess(o);
411+
return true;
412+
}
413+
414+
/**
415+
* Looks up an entity of a given class, and executes the provided callback with it if the
416+
* entity is found.
417+
* @param type A type of entity. This may be a Class or an Interface.
418+
* @param callback Call back that is only called if the lookup finds a match.
419+
* @return Boolean returns true if the lookup was found.
420+
*/
421+
public boolean withLookupEntity(Class type, SuccessCallback<Entity> callback) {
422+
Entity o = lookupEntity(type);
423+
if (o == null) return false;
424+
callback.onSucess(o);
425+
return true;
426+
427+
}
428+
429+
/**
430+
* Adds a listener to be notified when the Slot placeholder with the given ID is requesting to be filled.
431+
* @param slotId The ID of the slot that you wish to fill with this handler.
432+
* @param l Listener that is called when a slot with the given ID is requesting to be filled. To set content in the slot
433+
* you can obtain a reference to the slot via {@link FillSlotEvent#getSlot()} and call {@link Slot#setContent(Component)}
434+
* on it. *Make sure you call {@link FillSlotEvent#consume()} if you set the content to prevent the event
435+
* from bubbling up the controller hierarchy and being overridden by another controller.*
436+
*/
437+
public void fillSlot(Tag slotId, ActionListener<FillSlotEvent> l) {
438+
addEventListener(evt -> {
439+
FillSlotEvent fse = evt.as(FillSlotEvent.class);
440+
if (fse != null && fse.getSlot().getId() == slotId) {
441+
l.actionPerformed(fse);
442+
}
443+
});
444+
}
445+
329446

330447

331448
}

common/src/main/java/com/codename1/rad/controllers/ControllerEvent.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,21 @@
55
*/
66
package com.codename1.rad.controllers;
77

8+
import com.codename1.ui.CN;
9+
import com.codename1.ui.Component;
10+
import com.codename1.ui.Form;
811
import com.codename1.ui.events.ActionEvent;
12+
import com.codename1.util.AsyncResource;
13+
import com.codename1.util.SuccessCallback;
914

1015
/**
1116
* A base event for all controller events. This is the fundamental building block for how information
1217
* propagates up the controller hierarchy from views or child-controllers.
1318
* @author shannah
1419
*/
1520
public class ControllerEvent extends ActionEvent {
21+
22+
private AsyncResource asyncResource;
1623

1724
/**
1825
* Creates a new controller event.
@@ -41,5 +48,63 @@ public <T extends ControllerEvent> T as(Class<T> type) {
4148
}
4249
return null;
4350
}
51+
52+
public <T extends ControllerEvent> boolean as(Class<T> type, SuccessCallback<T> callback) {
53+
T cevt = as(type);
54+
if (cevt == null) return false;
55+
callback.onSucess(cevt);
56+
return true;
57+
}
58+
59+
public <T extends AsyncResource> T getAsyncResource(Class<T> type) {
60+
if (!isConsumed() || asyncResource == null || !type.isAssignableFrom(asyncResource.getClass())) {
61+
return null;
62+
}
63+
return (T) asyncResource;
64+
}
65+
66+
public void setAsyncResource(AsyncResource task) {
67+
asyncResource = task;
68+
}
69+
70+
public AsyncResource getAsyncResource() {
71+
return asyncResource;
72+
}
73+
74+
public ViewController getViewController() {
75+
Component cmp = getComponent();
76+
if (cmp == null) {
77+
return null;
78+
}
79+
return ViewController.getViewController(cmp);
80+
}
81+
82+
public FormController getFormController() {
83+
ViewController ctl = getViewController();
84+
if (ctl == null) return null;
85+
return ctl.getFormController();
86+
}
87+
88+
public AppSectionController getAppSectionController() {
89+
ViewController ctl = getViewController();
90+
if (ctl == null) return null;
91+
return ctl.getSectionController();
92+
}
93+
94+
public ApplicationController getApplicationController() {
95+
ViewController ctl = getViewController();
96+
if (ctl == null) {
97+
Form f = CN.getCurrentForm();
98+
if (f == null) {
99+
return null;
100+
}
101+
ctl = ViewController.getViewController(f);
102+
103+
}
104+
105+
if (ctl == null) return null;
106+
return ctl.getApplicationController();
107+
}
108+
44109

45110
}

0 commit comments

Comments
 (0)