When to use GWT ensureInjected()? - css

I created a few styles into a CSSResource and it works well whether I use
GWT.<MyResources>create(MyResources.class).myStyles().ensureInjected();
or not.
Could anyone shed a light on this and explain when to use ensureInjected or not?
Thank you!
Daniel

As Christian said, inside the UiBinder ui.xml file you don't have to worry about invoking ensureInjected(), the following XML statements do the job:
<ui:with field='myStyle' type='com...MyStyle'/>
<div class='{myStyle.redBorder}'/>
Of course this is assuming that there is somewhere a MyStyle interface defined:
public interface MyStyle {
public String redBorder();
}
Now I agree with you that things get annoying when you need to manipulate the CssResource extension outside of UiBinder templates. Precisely because you have to take care of invoking ensureInjected() somewhere before using the MyStyle instance with your widgets.
I personally use GIN to inject instances of extensions of CssResource whenever I need them.That way you can implement a custom GIN provider ensuring that ensureInjected() is called on the CssResource before injecting it.
There are three steps involved there:
Create an interface for MyStyle alongside with a CSS file.
MyStyle.java
public interface MyStyle {
public String redBorder();
}
MyStyle.css
.redBorder { border: 1px solid red; }
Expose it through a ClientBundle extension.
Resources.java
public interface Resources extends ClientBundle {
#Source("MyStyle.css")
public MyStyle style();
}
Configure a GIN provider method to inject your instances of MyStyle.
ClientModule.java
public class ClientModule extends AbstractGinModule {
#Override
protected void configure() {
//...
}
#Provides MyStyle createStyle(final Resources resources) {
MyStyle style = resources.style();
style.ensureInjected();
return style;
}
}
We smoothly inject the Resources instance here above, which means no more hassle of a static accessor calling GWT.<Resources>create(Resources.class) anywhere, it just all happens through the GIN injection.
Having done that you can inject your instances of MyStyle when you need them.
For example (in some MVP context):
private Widget widget;
#Inject
public SomeView(final MyStyle style) {
//...
widget = uiBinder.createAndBindUi(this);
widget.addStyleName(style.redBorder());
}

Good question - one situation that comes to my mind is when you want to use styles from some global stylesheet in a UiBinder template - then you need to call ensureInjected to... ensure the styles are indeed injected when you are referencing them (the "local" UiBinder styles, that you define in xml are automagically injected).
You can see this used as such in the Mail example:
public void onModuleLoad() {
// Inject global styles.
GWT.<GlobalResources>create(GlobalResources.class).css().ensureInjected();
// Create the UI defined in Mail.ui.xml.
DockLayoutPanel outer = binder.createAndBindUi(this);
// ...rest of the code
}
Note how ensureInjected is called before binding the UI.
This is the only situation I know that warrants using ensureInjected, but maybe I missed something.

The rule is easy: you have to call ensureInjected() explicitly, unless the CssResource is being generated from an <ui:style> in a UiBinder template (because most of the time you won't have a handle on the generated CssResource.
Specifically, <ui:with> provides no special treatment for CssResources.
Also, a few widgets take a specific ClientBundle as argument to a constructor (such as CellTable), they will then call ensureInjected() on the CssResource they use.

If you use UiBinder the call to ensureInjected is provided by the tag ui:with. For any other css you are using in a client bundle (i.e. legacy css excluded) and that are not declared in a ui:with block, you have to call ensureInjected explicitly.

Related

Define rootscope variable in an .ASPX file

I am trying to define an AngularJS rootscope variable in a .ASPX file to use in a TypeScript file, but I am unsure of how to do this. I am open to any way to be able to define a value in an .ASPX file and use it in TypeScript, so any other suggestion will work for me.
If you simply need to tell TypeScript that the property is there, you can extend the rootScope interface:
interface extendedRootScope extends ng.IRootScopeService {
myProp: number;
}
Then when you inject $rootScope in your controller, type it as your new interface:
export class MyController {
constructor(private $rootScope: extendedRootScope) { }
someMethod() {
// Access this.$rootScope.myProp
}
}
If you need to access $rootScope from outside the Angular world (like in your ASPX page) to add the property, you can do something like this:
<script>
var injector = angular.element('[ng-app]').injector();
var $rootScope = injector.get('$rootScope');
$rootScope.myProp = 1;
</script>
This assumes you are using ng-app to initialize your Angular app.
Similarly, you could create an Angular service on the fly in a script tag, inject $rootScope into that service, and add properties to it.

How to add JS and CSS to all content parts in an Orchard module

I am writing a module for Orchard CMS 1.8.1
I would like to add custom styles to all content parts that I have written for the module. I need these to work regardless of the theme chosen by the website admins. I could add links to the CSS and JS files in every view file for every content part - but that seems messy and prone to future bugs - what's the best way to have a single file that loads up the styles needed for all my content parts?
Should I provide a different Content.cshtml that includes the links? This also seems like it could be problematic if the admins need their own control over the main Content.cshtml
Many thanks
Handler should do the trick, I wrote this from the top of my head so not sure if it really works.
First create ResourceManifest.cs and define your stylesheets and scripts
public class ResourceManifest : IResourceManifestProvider
{
public void BuildManifests(ResourceManifestBuilder builder)
{
var manifest = builder.Add();
manifest.DefineStyle("MyStylesheet").SetUrl("mystylesheet.min.css", "mystylesheet.css").SetVersion("1.0.0");
manifest.DefineScript("MyScript").SetUrl("myscript.min.js", "myscript.js").SetVersion("1.0.0");
}
}
Then it should be enough to create content handler and override the BuildDisplayShape
public class MyResourceHandler : ContentHandler
{
private readonly Work<IResourceManager> _resourceManager;
public MyResourceHandler(Work<IResourceManager> resourceManager)
{
_resourceManager = resourceManager;
}
protected override void BuildDisplayShape(BuildDisplayContext context)
{
if (context.DisplayType == "Detail" && context.ContentItem.Has(typeof(MyPart)))
{
this._resourceManager.Value.Require("stylesheet", "MyStylesheet");
this._resourceManager.Value.Require("script", "MyScript");
}
base.BuildDisplayShape(context);
}
}
Adjust the IF as necessary. And let me know if it works ;)
Beauty of using ResourceManifest with versioning is that anyone can replace your stylesheets/javascript with their own just by defining style in their own ResourceManifest (module/theme) with same name and higher version number and don't have to touch any original files.

GWT DataGrid : "Unable to find ImageResource method value("cellTableLoading")" when overriding styles

I tried to override styles for GWT DataGrid component like described here :
DataGrid / CellTable styling frustration -- overriding row styles
My interface
public interface DataGridResources extends DataGrid.Resources {
#Source({ DataGrid.Style.DEFAULT_CSS, "myDataGrid.css" })
DataGrid.Style dataGrid();
}
public static final DataGridResources dataGridResources =
Datagrid instance using Inteface
GWT.create(DataGridResources.class);
static {
dataGridResources.dataGrid().ensureInjected();
}
...
dataGrid = new DataGrid<User>(10, dataGridResources);
But I get the following error :
Rebinding xxx.DataGridResources
-Invoking generator com.google.gwt.resources.rebind.context.InlineClientBundleGenerator
--Creating assignment for dataGrid()
---Creating image sprite classes
----Unable to find ImageResource method value("cellTableLoading") in xxx.DataGridResources : Could not find no-arg method named cellTableLoading in type xxx.DataGridResources
--Generator 'com.google.gwt.resources.rebind.context.InlineClientBundleGenerator' threw an exception while rebinding 'xxx.DataGridResources'
-Deferred binding failed for 'xxx.DataGridResources'; expect subsequent failures
The following works. Really.
public interface Resources extends DataGrid.Resources {
interface Style extends DataGrid.Style { }
#Source(value = {DataGrid.Style.DEFAULT_CSS, "myDataGrid.css"})
public Style dataGridStyle();
}
Also you don't need to call ensureInjected() since DataGrid will call it for you.
Anyway there is something wrong in the error log: it looks for cellTableLoading style which is not part of the DataGrid.Resources interface (is part of CellTable.Resources). Have you left some spurious CSS classes in myDataGrid.css that are not defined in the original interface?
Maybe you have moved from CellTable to DataGrid by simply renaming the css, but without changing the inner class names.

Flex watch bindable property other class

I'm creating an application using Flex 4.
When the app is started, it reads a XML file and populate objects. The .send() call is asynchronous, so I would want to listen/watch to this populated object, and when it has finished, dispatch an event for other classes, so they can use it.
package model{
public class LectureService extends HTTPService{
[Bindable]
private var _lecture:Lecture;
...
}
The xml is parsed correctly and loaded inside the object lecture of the class Lecture.
If I use the MXML notation in the main.mxml app, it works fine (the object is used when the it is populated after the async request):
<mx:Image id="currentSlide" source={lectureService.lecture.slides.getItemAt(0).path} />
BUT, I have another ActionScript class and I'm not able to listen to this dispatched (by [Bindable]) event.
package components{
public class LectureSlideDisplay extends Image
{
public function LectureSlideDisplay()
{
super();
this.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onChangeTest);
}
private function onChangeTest(e:PropertyChangeEvent):void {
trace('test');
}
I have already tried:
using (like above) addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, methodName).
tried to change the [Bindable] to [Bindalbe("nameEvent")] and listen for this, nothing.
using CreateWatcher method, doesn't work.
tried to have a look to the generated code of the class, but didn't help me
if (this.hasEventListener("propertyChange")){
this.dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent(this, "lecture", oldValue, value));
}
How can I listen and have the populated object in another class?
Maybe the problem is that I'm listening from another class, but in this case how can I implement this?
It seems the event is dispatched, but I can't listen to it.
For who wants the answer, I have resolved changing the addEventListener object.
It is not right to use:
this.addEventListener(...)
Use instead:
lectureService.addEventListener(...)
I have changed my code to listen to this event in the main app MXML, and then inside the handler method, call the public method of your components to use the new data.
You can't solve all your problems by just extending the class. You should really look into Commands for your HTTP requests.
The change property event is used internally for watchers and won't dispatch in the overall component. What you want to do for your LectureSlideDisplay is to override the source setter. Every time it is called, a new value is being binded to it:
package components{
public class LectureSlideDisplay extends Image
{
override public function set source(value:Object):void
{
super.source = value;
// do whatever
}
public function LectureSlideDisplay()
{
super();
}
}
}
You should really read up on how Binding works.
Consider to use BindingUtils class. You can found documentation here. And a couple of usage samples: one, two.

How do I manage library symbols with linked classes in Flash CS4 to compile/debug in Flash Builder 4?

I'm building a video player using Flash CS4 (hereby referred to as "Flash") to create the graphic symbols and compiling and debugging with Flash Builder 4 ("FB4"). Here are the steps I take in my current workflow:
--Create the graphic symbols in Flash. I've created a few different symbols for the player, but I'll focus on just the play/pause button ("ppbutton") here.
--In the Library panel, I go to the ppbutton symbol's Linkage properties and link to a class named assets.PlayPauseButtonAsset that extends MovieClip. I do not actually have an assets package nor do I have a class file for PlayPauseButtonAsset as Flash will create them for me when I publish.
--In Flash's Publish settings, I set the project to export a SWC that will be used in FB4, called VideoPlayerAssets.swc.
--After the SWC is created, I create my FB4 project called "VideoPlayer" and add the SWC to my path. FB4 creates the class VideoPlayer in the default package automatically.
--In VideoPlayer.as, I import assets.*, which imports all of the symbol classes I created in Flash and are available via VideoPlayerAssets.swc. I can now instantiate the ppbutton and add to the stage, like this:
var ppbutton:PlayPauseButtonAsset = new PlayPauseButtonAsset();
addChild(ppbutton);
At this point ppbutton doesn't have any functionality because I didn't create any code for it. So I create a new class called video.controls.PlayPauseButtonLogic which extends assets.PlayPauseButtonAsset. I add some logic, and now I can use that new class to put a working ppbutton on the stage:
var ppbutton:PlayPauseButtonLogic = new PlayPauseButtonLogic();
addChild(ppbutton);
This works fine, but you may be asking why I didn't just link the ppbutton symbol in Flash to the video.controls.PlayPauseButtonLogic class in the first place. The reason is that I have a designer creating the UI in Flash and I don't want to have to re-publish the SWC from Flash every time I make a change in the logic. Basically, I want my designer to be able to make a symbol in Flash, link that symbol to a logically named class in Linkage properties, and export the SWC. I do not want to have to touch that .fla file again unless the designer makes changes to the symbols or layout. I'm using a versioning system for the project as well and it's cleaner to make sure only the designer is touching the .fla file.
So, finally, here's the issue I'm running into:
--As the design gets more complex, the designer is nesting symbols to position the video controls on the control bar. He creates a controlbar symbol and links it to assets.ControlBarAsset. The controlbar symbol contains the ppbutton symbol.
--The designer publishes the SWC and ControlBarAsset is now available in FB4. I create new class called video.controls.ControlBarLogic that extends assets.ControlBarAsset so I can add some logic to the controlbar, and I add the controlbar to the stage:
var controlbar:ControlBarLogic = new ControlBarLogic();
addChild(controlbar);
--This works, but the ppbutton doesn't do anything. That's because ppbutton, while inside controlbar, is still only linked to PlayPauseButtonAsset, which doesn't have any logic. I'm no longer instantiating a ppbutton object because it's part of controlbar.
That's where I'm stuck today. I can't seem to simply re-cast controlbar's ppbutton as PlayPauseButtonLogic as I get a Type error. And I don't want to have to make a class that has to instantiate each of the video player controls, the place them at their x and y values on the stage according to how the designer placed them, as that would require me to open the .fla and check the various properties of a symbol, then add those values to the code. If the designer made a change, I'd have to go into the code each time just to update those properties each time. Not good.
How do I re-cast nested symbols to use the logic classes that I create that extend the asset classes? Remember, the solution is not to link Flash symbols to actual classes so I don't have to keep recompiling the SWC, unless there's a way to do that without having to re-compile the SWC. I want the designer to do his thing, publish the SWC, and be done with it. Then I can take his SWC, apply my logic to his assets, and be able to debug and compile the final SWF.
Here is the solution that i use sometimes:
Instead of making PlayPauseButtonLogic extends PlayPauseButtonAsset, use this class as a warpper of PalyPauseButtonAsset, use composition instead of inheritance ! ; ).
You will get something like this in your ControlBarLogic class:
//constructor exemple
public function ControlBarLogic(){
//all logic of PPButton is inside PlayPauseButtonLogic
//you just pass a reference to the PlayPauseButtonAsset button contained inside ControlBarAsset
var ppButtonLogic: PlayPauseButtonLogic=new PlayPauseButtonLogic(refToButtonAsset)
//the warper class can extends EventDispatcher so you will be able to listen to custom or redisatched events
ppButtonLogic.addEventListener("ppPause",onPause)
}
hope it will help you
You can have two classes, one holding functionality and the other providing its graphical implementation (asset/skin)
Have PlayPauseButtonLogic extend AssetWrapper.
A simple way to solve your issue regarding event listeners, you can do the following:
package {
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.IEventDispatcher;
public class AssetWrapper implements IEventDispatcher {
private var _skin:DisplayObjectContainer;
public function AssetWrapper( skin:DisplayObjectContainer = null ) {
if ( skin ) setSkin(skin);
}
public function setSkin(skin:DisplayObjectContainer):void{
_skin = skin;
}
public function dispatchEvent(event:Event):Boolean{
_skin.dispatchEvent(event);
}
public function hasEventListener(type:String):Boolean{
return _skin.hasEventListener(type);
}
public function willTrigger(type:String):Boolean{
return _skin.willTrigger(type);
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
_skin.removeEventListener(type, listener, useCapture);
}
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
_skin.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
}
}
EDIT:
You can then, of course, just add as many properties/methods to AssetWrapper that delegate to the DisplayObject (skin) as you need. It also gives you more control onto those properties/methods.
i.e:
public function get x( ):Number {
return _skin.x;
}
public function set x( v:Number ):void {
if ( _skin.x = v ) return;
if ( _useWholePixels ) _skin.x = Math.round(v);
else _skin.x = v;
}
That way, for instance, you can tween your AssetWrapper instance directly. Also, you can control if you want it to be placed in round numbers (x=100) or not (x=100.5)
For methods, just the same idea:
public function addChild( child:DisplayObject ):DisplayObject {
return _skin.addChild( child );
}
Then to use it, you would extend AssetWrapper and implement a concrete behavior:
package {
import flash.display.DisplayObjectContainer;
import flash.events.MouseEvent;
public class SimpleButton extends AssetWrapper {
public function SimpleButton( skin:DisplayObjectContainer = null ) {
super(skin)
}
override public function setSkin( skin:DisplayObjectContainer):void {
super.setSkin( skin );
addEventListener(MouseEvent.ROLL_OVER, _onRollOver );
addEventListener(MouseEvent.ROLL_OUT, _onRollOut );
}
protected function _onRollOver(e:MouseEvent):void {
_skin.alpha = .5;
}
...
}
And you would use it as follows:
//you can get your graphical assets in many different ways
var buttonSkin:Sprite = new LibraryButtonSkin
//or
var ButtonSkinClass:Class = this.loaderInfo.applicationDomain.getDefinition("SimpleButtonSkin") as Class;
buttonSkin = new ButtonSkinClass;
var button:SimpleButton = new SimpleButton(buttonSkin);
button.addEventListener(MouseEvent.CLICK, _handleButton);
It is just a guide, in the real implementation you want to make sure you check for things like if a skin already exists, then remove all added listeners. You would probably could listen for an ADDED_TO_STAGE event and trigger a initialize method...
Also is a great to clean up after your instance by implement a destroy() method where you make sure all added listeners are removed and null/stop things like timers, sounds, etc.
Wow all the flow and we sunk in the finish line....
well, what about something like this
AbstractButtonBehavior
PlayButtonBehavior extends...
The trick, the graphic components should all implement some interface that allow them to pass a behavior at instantiation time, or even better, at runtime. The you just plug the login in, the logic will always remain outside and the poor assets will keep asking or answering to the same interface call, allowing you to work outside them.
could be?.

Resources