Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Having one scroll class for an entire project.

Guest
Sep 25, 2013 Sep 25, 2013

Hi

I'm using greensock's blitmask and scrolling in an Air iOS project, and am wondering what the best way is to set it up so you can have one central scroll class that all the classes can add clips to.

Is it doable to have a global model var that holds the movieclip that you want to scroll? ie a class sends one of it's moveiclips to the global var, and the global var dispatches an even to your scroll class, which removes the current MC it's scrolling, and injects the new one from the model?

Or am I going to have to have a new instance of the scroll class in every class that needs scrolling?

Cheers

TOPICS
ActionScript
1.3K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Guide , Sep 26, 2013 Sep 26, 2013

I think you're right that LoginController is the wrong place for this. When I was asking about the end goal, I meant more conceptually what you're trying to accomplish by having this scroller. Without more information that cuts to the heart of that and also more about how your Classes are actually relating with one another, I still can't give you a better implementation than dispatching a custom event with the MovieClip in it.

However, I think that there's a bad design smell about that--why on e

...
Translate
Guide ,
Sep 26, 2013 Sep 26, 2013

One way you could do it is have your Classes dispatch custom events that have the MovieClip as a property on the event, then a Controller that is listening on the Display list or an event bus that you create for communication hear the event and add it to the scroller.

However, that doesn't seem like the best implementation. It's simply the best I can do with the limited information you've provided. What's the end goal, are the Classes that have references to the MovieClips data Classes or View Classes, and what is their relationship to each other and the application as a whole?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Sep 26, 2013 Sep 26, 2013

Thanks Amy

My end goal...

Have one scroller class that I can send any one of the 30 moveiclips in the project to, and have the old moveiclip in the scroller be replaced. Some of the movieclips are static, and others dynamic, displaying new data retrieved from the server each time.

The classes that reference the movieclips are controller classes.

The problem I encountered was, in order to have just one instance of the scroller class (which happens to be instantiated in LoginController.as), LoginController.as now contains code for the help section, contact page etc... anything that needs scrolling - not good.

I then experimented sending each movieclip to be displayed (after it is dynamically created) to a setter in a common model I've injected into each of the classes constructors, and then trigger the scroller to kick the old MC out, and get this new MC.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Sep 26, 2013 Sep 26, 2013

I think you're right that LoginController is the wrong place for this. When I was asking about the end goal, I meant more conceptually what you're trying to accomplish by having this scroller. Without more information that cuts to the heart of that and also more about how your Classes are actually relating with one another, I still can't give you a better implementation than dispatching a custom event with the MovieClip in it.

However, I think that there's a bad design smell about that--why on earth do these controllers and views have references to these MovieClips they're not showing themselves? There has to be some deeper "something" about how these could be made/managed without this awkwardness. Where are these components that you're adding to the scroller when they're not in the scroller?

In the absence of that type of information, I can ony give you an example of how to implement my first (admittedly sort of crap) suggestion.

public interface IEventBusClient {

     function get eventBus():IEventDispatcher;

     function set eventBus(value:IEventDispatcher):void;

}

public class MovieClipEvent extends Event {

     pubic static const SEND_TO_SCROLLER:String = 'sendToScroller';

     public var movieClip:MovieClip;

     public function MovieClipEvent(type:String, mc:MovieClip) {

          super(type, false, true);

          movieClip = mc;

     }

     override publlic function clone():Event {

          return new MovieClipEvent(type, movieClip);

     }

}

public class SomeController implements IEventBusClient {

     protected var _eventBus:IEventDispatcher;

     public function get eventBus():IEventDispatcher {

          return _eventBus;

     }

     public function set eventBus(value:IEventDispatcher):void {

          _eventBus = value;

     }

     protected function invokeScroller(e:SomeEventType):void {

          if (_eventBus && someMovieClip) {

               _eventBus.dispatchEvent(new MovieClipEvent(MovieClipEvent.SEND_TO_SCROLLER, someMovieClip);

          }

     }

}

public class ScrollerController implements IEventBusClient {

    

     protected var _eventBus:IEventDispatcher; 

     protected var _scroller:ActualGreenSockTypeGoesHere;

     public function get eventBus():IEventDispatcher {

          return _eventBus;

     }

     public function set eventBus(value:IEventDispatcher):void {

          if (_eventBus != value) {

               if (_eventBus) {

                    _eventBus.removeEventistener(MovieClipEvent.ADD_TO_SCROLLER, updateScroller);

               }

               _eventBus = value;

               if (_eventBus) { 

                    _eventBus.addEventistener(MovieClipEvent.ADD_TO_SCROLLER, updateScroller);

               }

     }

     protected function updateScroller(e:MovieClipEvent):void {

          //remove old clip using whatever the greensock api says

          var mc:MovieClip = e.movieClip;

          if (mc) {

               //add movieclip to scroller using greensock api

          }

     }

}

You can then set eventBus on instances of these Classes to the display list or to an event dispatcher that you make for the purpose of providing communication. I like to have a separate event dispatcher that serves as a communication backbone in the "data" space (and by that I mean the model and controller classes), but I also will sometimes populate that variable with a reference to the display list or a more local event bus depending on what I'm doing--the thing that makes this technique tremendously powerful is that you can get a lot of flexibility just based on what object you pass in as the event bus.

I think I've made this suggestion before, but in case I haven't, you may want to consider using RobotLetg, since it can automate the process of providing those references.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Sep 26, 2013 Sep 26, 2013

Thanks Amy - I'll have a play with that.

No views. Just controllers - the code for each movieclip interaction is minimal (once I get them separated, that is), so I figured views would be overkill.

Controllers are communicating via events dispatched from a common global model injected into each controller's constructor.

The movieclips are stored in the Flash Pro lib, and I instantiate them in the controller, and then the controller interacts with them. eg the LoginController instantiates the MC, and deals with it's logic. When the user needs to see it, it should be sent to the scroller.

Conceptually, even though it's not a social networking app, same sort of thing as Facebook - mixture of static and dynamic clips that need to be scrolled on the iPhone.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Sep 27, 2013 Sep 27, 2013

A MovieClip is a View, whether you associate code with it or not. I'd highly recommend that you have your Views implement an Interface so that you can move the creation out of the Controllers. This will free you to later substitute Views that have all the correct properties and methods without being tied to a specific implementation.

It's a violation of separation of concerns to have the Controllers both instantiate the View and then interact with it. You may want to consider having a Builder that takes requests from the controllers to create Views, then hands the newly-created View back to the Controller and also passes it to the Scroller.

I actually prefer to use the Flash timeline as my Factory for creating Views, but when I need to create different variants (of data classes in my case) based on different needs, then I'll have a builder which contains a Dictionary that contains all the different factories needed to make that type of "thing," registered by a string that lines up to information in an XML file and also the timeline label where that particular thing will ultimately be used.

When the XML loads, I parse each file and call builder.createStuff(param1, param2...) and then the Builder looks in its dictionary and finds the Factory registered for param1 and delegates the actual creation to it, returning back the created Object which is then added into the overall object graph.

Again, this becomes a very powerful technique because you can dramatically change how your program behaves just by what you put in that Dictionary without touching anything else.

I'd also caution you about putting too much knowledge of your "global model" into your Controllers. If the main thing that they need it for is to communicate with one another, you're better off only telling them it's an IEventDispatcher. If they need access to specific parts of the model, define a formal Interface for each "face" that the Model needs to display to different parts of the Application.

That way, when you find that you need to break your Model into pieces--and I think this will happen, the direction that you're developing--you don't need to change any of the client code, you just hand it the new piece that implements the Interface that now makes up the composited Model.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Sep 27, 2013 Sep 27, 2013

Oh dear Amy - I've had too much vodka to read this, although my instincts tell me that this info is gold, and will be taken in much better in about 12 hours.

I will investigate then.

Thank you.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Sep 27, 2013 Sep 27, 2013

Thanks Amy

So when you say...

You may want to consider having a Builder that takes requests from the controllers to create Views, then hands the newly-created View back to the Controller and also passes it to the Scroller.

...what do you mean by 'hand it back to it' - how do you do that?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Sep 28, 2013 Sep 28, 2013
LATEST

If you want to keep maximum decoupling, you can do it via events. One way to do this is to have a property on your custom event that tells the Builder who gets the new product when it is created. Another way to do this is to have the Builder dispatch an event once the product is ready and then both the scroller and the Controller pick it up off the event. Another way to do it is to have each Controller coupled to a specific Interface and have al the Controllers watch the display list for ADDED_TO_STAGE (in capture phase) and pick up and start controlling objects of the given Interface once they are added. This is a variant of what I do, but I allow the Flash Player to act as my builder, so I don't have to write any code to accomplish the building, adding. or positioning.

However, since both your Builder and Controllers live in data space, you could probably get away with giving the Controller a reference to the Builder and asking for the object directly.

newView = builder.createStuff(...)

The issue with doing that is that now the fact that the scroller is being informed of the new view is not obvious and is kind of a hidden side-effect. This could be handled by adding a layer whose job it is to intercede between the Controller(s), the Builder, and the Scroller.  However, if you go that route, I would say you're better off going directly to RobotLegs without passing go, because you'd just be reinventing their much more elegant wheel.

Another possible strategy is to get everyone in one room during startup and let the Builder build everything then, then the Controllers always have a reference to their respective Views and simply request that they be added to or removed from the scroller. This has the advantage that you can throw away the Builder after startup, and this is exactly how I use my own Builder.

Message was edited by: Amy Blankenship

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines