View Poll Results: Content Provider vs View Model

Voters
15. You may not vote on this poll
  • I favour the Content Provider Pattern (JFace)

    9 60.00%
  • I favour the View Model Pattern (Swing)

    1 6.67%
  • I don't understand the diffrence between them

    5 33.33%
  • I don't care

    0 0%
Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 22

Thread: Content Provider vs View Model

  1. #11
    Join Date
    Aug 2004
    Location
    Germany, Magdeburg
    Posts
    279

    Default

    One more thing: I think it may be better to develop the ContentProvider pattern in a seperate project, as it doesn't have any dependency to spring-rcp (as it shouldn't).
    Sure! :-) But the question is, how much code is needed. All that is really needed is adding a tree/list model being feed using a Content/Label provider pridge. Also the JTree object should be hidden by a special implementation. Lets call it JTreeViewer. Shouldn't be much of a fuzz.

    But a special project it should surely be. I really wonder why this hasn't done before. I always hated to deal with table models. This is always so boring.


    Cheers,

    Martin (Kersten)

  2. #12
    Join Date
    Sep 2004
    Location
    Ghent, Belgium
    Posts
    224

    Default

    Yep, not a lot of code would be needed. A few "higher level" classes (TableViewer, ListViewer, TreeViewer and maybe TreeTableViewer) using Swing components internally.

    These Viewer implementations should provide refresh/add/remove methods, and methods for getting/setting the selection.

    In a second fase, filtering and sorting could be added, and editing for the TableViewer. (I hate the table editing in Swing, I looked at the JFace approach, and I think it's better, they have hooks for validation, custom editors, automatic sorting when editing stops, ...)

    I'd also put some extras in the TableViewer implementation, such as "double click auto resize column" behaviour, and automatic sorting when clicking on the header, so users of the TableViewer class would get this for free.

    Peter

  3. #13
    Join Date
    Aug 2004
    Location
    Germany, Magdeburg
    Posts
    279

    Default

    Thinking about selection provider... :-) That would be an add for Spring RPC ;-).

    To the Spring RPC folks: By the way I have sent Keth an email with a minimalistic application design, but I didn't got any response. (about a week ago) Do you have any informations on that?

  4. #14
    Join Date
    Dec 2004
    Location
    Oslo, Norway
    Posts
    17

    Default

    Quote Originally Posted by pdbruycker
    Yep, not a lot of code would be needed. A few "higher level" classes (TableViewer, ListViewer, TreeViewer and maybe TreeTableViewer) using Swing components internally.

    These Viewer implementations should provide refresh/add/remove methods, and methods for getting/setting the selection.

    In a second fase, filtering and sorting could be added, and editing for the TableViewer. (I hate the table editing in Swing, I looked at the JFace approach, and I think it's better, they have hooks for validation, custom editors, automatic sorting when editing stops, ...)

    I'd also put some extras in the TableViewer implementation, such as "double click auto resize column" behaviour, and automatic sorting when clicking on the header, so users of the TableViewer class would get this for free.

    Peter
    Now your'e talkin! Or, at least now I understand what you guys are talking about. :-)

    This is quite spot on with what I am trying to do in my own Swing framework. I have TableView and TreeView etc and the point is to just hand them List collections of domain model objects an after that treat them in a uniform way to the extent possible.

    In addition to the methods you suggest I would add ViwChange and ViewSelection events that smoothes out the differense between the similar JTable and JTree events (but also conveying the original events) and returning Lists of domain model object that have changed or has been selected.

    Also, I would like to add view relationship that takes care of the relationship between the domain objects involved (I call them relationship resolvers) so that when an object at the 1 end of a 1:M relationship is selected, the View in the M end can display the appropriate related objects.

    This would sort of turn the Swing framework inside out and make it more developer friendly than GUI-tool builder firendly, and we need that!

    As a further suggestion, add a generic CRUD API that can be extended to EJB/SOAP/HTTP/Whatever and you have a real nice foundation for automating imporant infrastructure like CRUD, sorting, filtering, etc.

    /Ragnar

  5. #15
    Join Date
    Aug 2004
    Location
    Germany, Magdeburg
    Posts
    279

    Default

    This is quite spot on with what I am trying to do in my own Swing framework. I have TableView and TreeView etc and the point is to just hand them List collections of domain model objects an after that treat them in a uniform way to the extent possible.
    List is to special. :-) List is just a collection. In JFace it is up to the viewer sorters to do some ordering. So collections is enough. Also a List is a special case of a tree (tree of depth one). But the viewer shouldn't care about the structure also. Just expect what is needed.

    I for example didn't understand why the ITreeContentProvider (structured content provider?) distincts between the input element and the children/parent?

    This would be enough I guess:

    Code:
    type ContentProvider {
        Object [] getRelatedObjects(Object object);
    }
    Would made it as a tree/table/list content provider. Maybe the UML would provide a better picture:

    Code:
    type ContentProvider {
        Object [] getAssociatedObjects(Object object); //direct association ordering!
    }
    Maybe a parent would be an useful information, but I am deeply in doupt since the viewer should also know its tree and just update it according to referesh signals.

    So everything tends to come down to one single content provider method. That would be very good. It just starts with the input object, which can be null but symbolizes an empty structure (close world assumption).

    Well a hasAssocatedObjects method would be needed to minimize the resource footprint. But I always implemented it this way:

    Code:
    boolean hasAssociatedObjects(Object object) {
        return getAssociatedObjects(object).length>0;
    }
    The idea is to make the viewer (Tree, table etc) what it should be. Something being dumb. Watch things go by and just translate, what it sees into something, what it displays. No domain related logic, nothing, sip. The only thing that needs to be specified is the way it can see.

    The selction API should also feature a selection provider of cause. This would ease things I guess. Also a single selection event / selection may be enough for the basic cases.

    The basic API should be quite simple and easy to use at least nothing compared to the MVC approach of Swing.

    One thing that would also be great is a context menu being used depending on the object that the viewer is displaying (which is selected). But this is Spring RPC stuff. I guess I saw something like that, but I am not sure.

    Let's wait what Peter can provide. I guess we will throw all of our code and knowledge together and build something comparitive to a special model adapter (like JFace incooperates it).


    Cheers,

    Martin (Kersten)

  6. #16
    Join Date
    Dec 2004
    Location
    Oslo, Norway
    Posts
    17

    Default

    List is to special. :-) List is just a collection. In JFace it is up to the viewer sorters to do some ordering. So collections is enough
    Ok, I understand. But I don't see the point other than supporting a more general case and I'm a bit worried it complicates things unnecessarily. I would say that a List is sufficient as a placeholder for my domain objects. And I wonder how JFace knows how to handle all types of collections. Is there any difference in how JFace displays my data when I
    give it a List and for example a HashMap ?

    Also a List is a special case of a tree (tree of depth one).
    That one I liked! Thats just my view on it. In my framework, if I create a CustomerView it will be a list of Customers (but I do show the root node) at first level in the tree. Likewise, if I create a OrderView its a list of Orders at first level. But if I create a CustomerView and submit a OrderView in its constructor, then I get a Tree with Customers at first level and Orders at second level (for each Customer node). With their 1:M relationship "automatically" managed.

    Btw, I handle tables in a similar manner, making it possible to add subview's for related objects. JTree is a pesky thing though, and TreeView subvies needs special treatment (yes, my TreeView is not fully sorted out :-) )

    Your constant talk about JFace make me curious, Martin. So I searched the net and the Eclipse site, but could not find it. Can you give me a link to it?

    Cheers!

    /Ragnar

  7. #17
    Join Date
    Dec 2004
    Location
    Buenos Aires, Argentina
    Posts
    73

    Default JFace Primer


  8. #18
    Join Date
    Aug 2004
    Location
    Germany, Magdeburg
    Posts
    279

    Default

    @gfaerman

    Thanks for the primer but saidly it is not about the IContentProvider issue. But this reminded my about this article:

    http://eclipse.org/articles/treeview...werArticle.htm

    It contains some usefull example how the tree viewer is used.

  9. #19
    Join Date
    Aug 2004
    Location
    Germany, Magdeburg
    Posts
    279

    Default

    That one I liked! Thats just my view on it. In my framework, if I create a CustomerView it will be a list of Customers (but I do show the root node) at first level in the tree. Likewise, if I create a OrderView its a list of Orders at first level. But if I create a CustomerView and submit a OrderView in its constructor, then I get a Tree with Customers at first level and Orders at second level (for each Customer node). With their 1:M relationship "automatically" managed.
    That is the diffrent now. Your view is not about a list of customers in first place. It is about your domain model having customers and orders. It is about a domain model being compost of customers and offers. A view is just a way to display parts of the domain model in a diffrent way. But by composing a list and give the list to the viewer, you are decoupling the viewer from the thing it should really display, the part of the domain model.

    So semantically you try to do this:

    Viewer --- displays ---> domain model

    but actually you realise this requirement by doing:

    Viewer --- display ---> List of customers --- which contains parts of ---> domain model.

    You see you put something in between. You shouldn't care about this being a list. It's up to the viewer to decide what the internals are. It is not your concern. You are the user. Tell the viewer what to do and let it do its work.

    Ok, I understand. But I don't see the point other than supporting a more general case and I'm a bit worried it complicates things unnecessarily. I would say that a List is sufficient as a placeholder for my domain objects. And I wonder how JFace knows how to handle all types of collections.
    By not using a list but describing a general purpose structure we go some levels up in the type hierarchy. By describing a general purpose structure you can provide List, Map or like a custom made domain model or map a database as a input of the same viewer. All you change is the needed adapters (content and label providers). And those adapters are cheap as hell. There is not much going on here so they are easy to test. No fuzz with models of viewers anymore.

    Is there any difference in how JFace displays my data when I
    give it a List and for example a HashMap ?
    up to you. Think about this:
    Situation:
    Map domainModel

    Task:
    Display all customers contained in the domain model

    Code:
    realisation MyContentProvider {
        Object [] getAssociatedObjects(Object object) { //get children
            if(object==domainModel) {
                return domainModel.getAllCustomers(); //first idea
                //or
                return domainModel.values(); //plus using a filter to filter out customers
                //or 
                return (List)domainModel.get("customers"); //silly
            }
           else
               return new Object [0];
        }
    }
    Plain and simple. But now you can use List, Map, Set, Collection or more preferable something like DomainModel, DatabaseModel or ResultSet. It is a matter of the content provider not of the view anymore. The freedom is yours.

    Also you can write a content provider for providing the input for many diffrent views. All you do is set diffrent input element (root) for each viewer.

    For example:

    Model consists of CustomerRepository, OfferRepository

    Code:
    realisation MyContentProvider {
        Object [] getAssociatedObjects(Object object) {
            if(object instanceof Model) {
                Model model=(Model)object;
                return new Object []{ 
                       object.getCustomerRepository(),
                       object.getOfferRepository() };
            }
            else if(object instanceof CustomerRepository) {
                return ((CustomerRepository)object).getAllCustomers();
            }
            else if(object instanceof OfferRepository) {
                return ((OfferRepository)object).getAllOffers();
            }
            else
                return new Object[0];
        }
    }
    
    realisation MyLabelProvider {
        String getText(Object object) {
            if(object instanceof Model)
                return "Domain Model";
            else if(object instanceof CustomerRepository) 
                return "Customers";
            else if(object instanceof OfferRepository) 
                return "Offers"
            else if(object instanceof Customer)
                return ((Customer)object).getName();
            else if(object instanceof Offer) 
                return ((Offer)object).getDescription();
            else
                return null;
       }
    }
    See plain and simple. Now you can use it this way:

    Code:
    createTreeViewer {
        TreeViewer viewer=new TreeViewer(...);
        viewer.setContentProvider(new MyContentProvider());
        viewer.setLabelProvider(new MyLabelProvider());
    }
    
    +
    
    showModel {
        viewer.setInput(domainModel);
    }
    showCustomers {
        viewer.setInput(domain.getCustomerRepository());
    }
    showOffers {
        viewer.setInput(domainModel.getOfferRepository());
    }

    Easy isn't it? No talk about a List or a Map. Just what it does. Adapt the domain model to the viewer. Plain and simple. Now you can add a sorter and a filter and you have a powerfull viewer enabling you to build powerfull views / GUI applications.


    Cheers,

    Martin (Kersten)

  10. #20
    Join Date
    Dec 2004
    Location
    Oslo, Norway
    Posts
    17

    Default

    Code:
    realisation MyContentProvider {
        Object [] getAssociatedObjects(Object object) { //get children
            if(object==domainModel) {
                return domainModel.getAllCustomers(); //first idea
                //or
                return domainModel.values(); //plus using a filter to filter out customers
                //or 
                return (List)domainModel.get("customers"); //silly
            }
           else
               return new Object [0];
        }
    }
    Plain and simple. But now you can use List, Map, Set, Collection or more preferable something like DomainModel, DatabaseModel or ResultSet. It is a matter of the content provider not of the view anymore. The freedom is yours.
    First, your syntax is confusing. Where does this "realisation" thing come from and what is it?

    And who's going to call the getAssociatedObjects() method?

    Is it the View?
    In that case you seem to have decided that a pure object array is the right thing for the View and not a Collection which I assumed you meant earlier?

    If the ContentProvider is in fact the generic domain model API as seen from the View, that's fine. I have a similar API which hides any kind of data source and they can of course use any collection type they want.

    But I don't see that your solution is any more generic or very different from using:

    Code:
    List getAssociatedObjects(Object object)
    Personally I prefer to use the List instead of Object[] for reasons like flexibility, easy sorting and filtering etc. But it really is no big deal, I can of course convert the object array to a List inside the View anyway.

    Easy isn't it? No talk about a List or a Map. Just what it does. Adapt the domain model to the viewer. Plain and simple. Now you can add a sorter and a filter and you have a powerfull viewer enabling you to build powerfull views / GUI applications.
    Well, no easier than my solution, just a tad different. It seems to me you convert any collection to Object[] when submitting your domain data to the View.

    Please correct me if I'm wrong, but it seems to me we were talking a bit past each other and we don't really disagree that much on this issue.


    Code:
    realisation MyLabelProvider { 
        String getText(Object object) { 
            if(object instanceof Model) 
    		return "Domain Model"; 
            else if(object instanceof CustomerRepository) 
    		return "Customers"; 
            else if(object instanceof OfferRepository) 
    		return "Offers" 
            else if(object instanceof Customer) 
    		return ((Customer)object).getName(); 
            else if(object instanceof Offer) 
    		return ((Offer)object).getDescription(); 
            else 
    		return null; 
       }
    This I do not like! :-)

    I would not have a labelprovider that is potentially tied to all my domain objects. Besides, using a Provider for simply setting a label seems like overkill. And you need labels for your Customer fields too. How do you handle those?

    I prefer having all labels and some other config info for each domain object in separate classes.
    In my framework I use reflection to get all fields from a domain model class using what I call a BeanPicker:

    Code:
    BeanPicker customerConfig = new BeanPicker(Customer.class);
    That's basically all. The BeanPicker is then submitted to the View that displays all its properties and using the Customer class name as a label.


    Code:
    View customerTreeView = new TreeView(customerConfig);
    View customerTableView = new TableView(customerConfig);
    But since using reflection often means getting more of the class's properties than I want to display and the property names are probably not what I want to use for field labels etc, I can submit an array of mappings in the constructor, telling the right labels to use for each property, and at the same time specify their order and which one to include and exclude. Like this:

    Code:
    String[][] propertyLables = { 
    	{ "name" , "Name" },
    	{ "id" , "Identifier" },
    	{ "address" , "Address" },
    Any properties of the class not included here will be silently ignored as will any included but not recognised by the reflection mechanism.

    Then I do:

    Code:
    BeanPicker customerConfig = new BeanPicker(Customer.class, propertyLabels);
    For the labels that you mention I have:

    Code:
    customerConfig.setSingularLabel("Customer");
    customerConfig.setPluralLabel("Customers");
    The BeanPicker has a few other methods like setting which property is editable etc.


    /Ragnar

Similar Threads

  1. Replies: 37
    Last Post: Dec 6th, 2007, 10:02 AM
  2. Replies: 1
    Last Post: Mar 13th, 2006, 07:53 PM
  3. Replies: 9
    Last Post: Nov 1st, 2005, 10:36 PM
  4. adding a model to the success view
    By mariuss in forum Web
    Replies: 8
    Last Post: Sep 1st, 2005, 09:28 PM
  5. Replies: 0
    Last Post: Jun 10th, 2005, 05:44 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •