gtk-databindings work blog and ramblings

gtk-databind

patch in second stage

by matooo on Jul.23, 2009, under gtk-databind

second stage of stetic patch. first public version which is commonly usable. patch is made against 2.0 release of monodevelop and I don’t plan to test it with trunk. next stable release is the first version which will receive my attention as I simply don’t have time to compile md daily and even less time to be annoyed with daily regressions (those are simply must be when you use work in progress). using bleeding edge just isn’t my game anymore.

what:
- disabled hardlinking to my assemblies (I needed that to test usage and loading)
- added code which resolves if assembly is gac based and then reloads it the hard way

stetic now works with real instances of widgets if they were added from gac assembly.

next?
Property editors… based on MS specs.

Download:
Patch

1 Comment : more...

ffs, finally…

by matooo on Jul.21, 2009, under gtk-databind

Don’t get me wrong, I actually like designing in stetic if I use classic widgets… But its design and internals scare the s*** out of me as I work with custom widgets 99% of time whenever I only think about working with it.

First the good… and why stetic is really great
1) Designing complex widgets, kudos and a beer keg
2) Really sensible interface and nice layout, again kudos

But why is stetic completely unusable for me?
(Which is completely different than my opinion about the rest of the Monodevelop. Monodevelop is in my eyes best IDE since sliced bread was invented and all my kudos with additional beer keg to developers.)
1) objects.xml overrides .Net attributes. This is not serious, actualy quite simple to correct
… now the really bad things (but knowing how much work it would take to fix this, I know why everyone is avoiding this like a plague. There is no time which is probably the first reason. The second reason is providing remoting service which can communicate all functionalities to IDE and back. Major work
2) any usage of class outside of gtk lib. you either get a wrapper with base class inside… uaaaaahhh. Or you get even worse result, stetic simply decides base widget has 0,0 size and widget disappears into nothing. Even wrapper approach is bad (for example, you set property value and there is no visual feedback on the form)
3) works trough cecil for everything outside base gtk-sharp library, which CAN’T invoke your widget and you end up with some wrapper c*** again.
4) No custom property designers

Number 1 probably derives from the fact that original designer didn’t even look at .Net framework but rather reinvented the whole wheel completely against .Net. Well, actual problem is just the priority where description is first taken. It should be attributes not xml. xml should be used for possible additional information. No more than 1 hour of work.

Now… 2, 3 and 4 all derive from the same problem. .Net can’t unload assembly. So what to do… For real soluion? Nope, there is no time. But providing simple but crippled solution… Yep more than possible. Personally, I don’t even see any crippling. And neither has anyone I talked to about this.

About patch

Well if one can’t unload assembly… He can unload IDE. But if references are only made to libraries referenced from GAC? Those can’t get recompiled, those can’t change. so worst case scenario is MD reload when I want to edit that library (or rather work on it as separate user in my case). Which is really rare.

Ok, so… rather than constantly bitching for next few years, I started patching stetic to fill my needs.

and goal 1 is achieved. Stetic now shows real widgets instead of fakes. and even more… they are live as seen here

Here is my DateEntry inside of stetic (for information… this is not combo box. It is derived from DrawingArea)
widgets

And these are properties. One widget has them set on false, one on true. Basically, you see what you design. Hell, you can even edit value if you want and it is stored back to stetic.
propertygrid

What is left to do?

Second step is to figure out which references are GAC based and pass only those to stetic instead of hardlinking as I did to be able to test invokation. This shouldn’t take long.

And last 3rd step is checking on solution load if solution is already loaded and… if it is simply exit monodevelop with exit code and rerun from script with new solution. This might take more time.

Bah, I know solution is far from perfect… but losing 3-4 seconds per project change instead of losing time working with invisible forms or forms without feedback? I don’t see the problem.

1 Comment more...

Ok, finally… release 2 almost out

by matooo on Jul.18, 2009, under gtk-databind

I completely stopped working on 1 and there were no more updates. Version 2 would already be out if there weren’t few showstoppers. But now I simply decided it is not important to me anymore as I can’t really do anything about fixing them.

New things in version 2…
- Real MVC approach to TreeModels with QueryModelAttribute and shells from which one can derive its own models by simply overriding 3-5 methods which provide data. QueryModelAttribute is far more than just attribute. It registers your model with specific data type and this means auto creation of it as soon as one specifies ItemsDataSource=myData
- Query models for arrays, lists, DataView, DataTable
- Registration of views for data so treeview column mapping can now simply be {MyType} #viewname# and it reads attribute description for that type and gets its columns defined by that view
- Sort and Filter observable lists (both generic and non generic ones). Simply connect Filter to some Observable list and here is live filtering, same goes for sorting
- DbObservableList, simply wraps DataTable or DataView and you use it like ordinary list, which is in effect compatible with filter and sort lists
- TypedDataTable, generic variant of DataTable
- Complete widget creation framework (by using drawing cells). Complex widget creation as in monodevelop mostly sucks because you’re imposing complex windowing architecture and thus your application consumes more ram and cpu. Same cells are reusable with reports in cairo, cellrenderers and classic widgets
- Widget style cells, which enable one to draw entry or button look alike in matter of one line.
- Various description attributes
- Various new widgets (like for example, usable DateEntry)
- Widget and Cell Factory for autogeneration of widgets based on property description
- DataAutoWidget, which generates its workings based on the property it edits
- Few cell renderers
and so on, practically this is just few changes, not all…
Basically v2 and v1 differ for more than 100% of functionallity and this is the reason why I stopped working on v1 and worked silently on v2. V2 will maybe need few lines edited, but otherwise is 99.99% compatible with v1

Showstoppers I don’t care about:
https://bugzilla.novell.com/show_bug.cgi?id=510176
https://bugzilla.novell.com/show_bug.cgi?id=523306

First one simply doesn’t allow full functionality for databinding to be effective as there is no correct delegating.
Second one is already in progress of fixing

Now I just have to clean up some things and v2 is out.
Plan after v2? v2.1
- LESS FUNCTIONALITY, MORE DOCUMENTATION…
- fixing things if needed
- AutoLayoutContainer (sharing the same workings as TreeView columns)
- Property grid
- More cellrenderers and more custom widgets (now that drawing cell approach is working… easy)
- Preparing for Gtk#3

1 Comment more...

Ok, job finished

by matooo on Mar.02, 2009, under gtk-databind

So now I finally have time to finish up some things. Like developing linear only ListStore (will be much more suited to create DataGrid like solution), not that now it doesn’t work, but code could be much simpler and event resolving much easier with faster filling.

So, probably sunday I’ll finally upload new things to svn as soon as I clean up my prototyping out of my branch.

On the other hand, I’m getting a lot of thank you messages here, so I wonder if people are using gtk-databind-lib. I know for a fact that at least 10 commercial apps will use/uses gtk-databindings (3 of those are mine and I can say without one single hickup, not even one case of crashing in 4 months of use). But strangely,… I don’t know even one piece of free software using it. Which is kinda strange, I wrote it as OSS for that specific purpose mostly.

3 Comments more...

DateEntry pre-rambling

by matooo on Feb.24, 2009, under gtk-databind

DateEntry as it is now in my personal branch:

Widget

3 clickable parts (Calculator, Clear and Picker) and one editable part. Every widget part should be able to activate with keyboard.

Press ‘+’ or ‘-’ and calculator pops up. Calculator is nothing but a simple SpinButton

calculator

Now with calculator you either control Spin with up and down or simply enter number by keyboard. Result on parent widget should be alive as calculator needs to handle both Esc and Enter. Press Esc and parent widget reverts back to what it was or press Enter and apply calculation.

Clear is a bit trickier. The biggest mistake every widget does is that it clears data. Not that it is always stupid, but in case of date? Yes, it is. DateEntry invokes ClearData event. By default it means revert to today. But what if you want to handle something like Due pay. By default, clear data would either mean setting it to the same date as the bill or (bill date + customers default due pay time).

This is a lot related to editing. DateEntry doesn’t have cursor (for its editing it uses Label not entry). Always selects complete part you’re editing. For example if you edit day and enter 4? There in no double digit day starting with 4. So it simply skips to next part, but if separator is pressed after this widget ignores it as it was already handled. Same goes with month the only double digit months are starting with 1, anything else skips to next part. But year is a little different. Its prediction has to be good enough when widget exits. Enter 0-9? obvious 2000, but only now, when we will be 2010? 0 will have to mean 2010 not 2000. 1 on the other hand is a bit trickier (if we’re entering this on december 2010? yes it should predict 2011… well this prediction is one of the things I’m still working on). And so on prediction should select most sensible year. Keys Left and right simply walk between day, month and year.

And last one thing? Picker, yes the only viable use for default gtk date selector.

Ok, so why all this? Simply because now CellRenderer to edit date is possible. And good CellRenderer classes are the only thing that separate people from having DataGrid.

Well, there is another annoying thing. The only widget that specifies Editable is Entry. All others only have Sensitive, but… wtf? Sensitive makes it disabled according to theme and mostly makes widgets unreadable. Every Widget should have editable not only one. Same as ClearData event. Another example for ClearData. Financial entry specifying cost of item? You calculate it differently, but then decide you’d go with original price… press Del and instead of setting it to zero? invoke a lookup in inventory and set default price or default price with calculated customers default prices? There is a little lesson. Some widget just don’t need Insert editing mode and some should control it by default for most sensible use. But if you want to go level above normal stupidity, the only way is to go with more sensible data editing.

Leave a Comment more...

Lack of posts

by matooo on Feb.22, 2009, under gtk-databind

No, it isn’t dead. I just went into custom widget prototyping and searching for perfect interaction with some really needed widgets.

Most notable example… How the hell can you use Date Widget in GTK in some financial application. Takes whole lot of space. Works awful with keyboard, not to mention entering the date manually is impossible. Same for financial numbers, etc…

It will also be the nicest explanation why converters and validators are deprecated in my opinion.

That will be part of the next upload in svn. As soon as I fix problem or two. Next blog post will feature DateEditor Widget, its use and a little screencast to go with it.

This is one of long overdue needs to create really cool DataGrids and such. Widgets which is usable to enter date in CellRenderer, but with more than perfect layout, control and features. Working nice with mouse and keyboard. And as long as I talk about usability, there will be a bit of brainstorming on my part why some things should be completely rethinked and redone to make applications perfect for users by default.

And please… if you respond to this… FFS, DON’T EVEN MENTION MASKEDEDIT!!!!! It is most horrible widget ever. Allowing you to solve something, but whenever you solve that with using it, solution is less worth than most crippled solution. MASKEDEDIT IS THE MOST HORRIBLE IDEA EVER!

Leave a Comment more...

Plans for 2.0

by matooo on Jan.05, 2009, under gtk-databind

For first and obvious plan is to squash as many bugs as they’re found.

Other plans (more serious)

  • Add Bind(object, object, *property mapping*[]) to DataBinder - this will allow to bind to many properties simultaneously
  • Remove Boundary***, since DataBinder allows just this and in the end it showed as not so usable as I thought at first, removal is very possible
  • Add IReadOnly interface - since there is only one widget that actually has readonly defined (Gtk.Entry) there is too much hassle to provide readonly gui interface. It would be so much nicer if one could simply say (Dialog, Window or Container).ReadOnly = true and widgets are not editable
  • Sanitize source with regions - SDB is a lot of source, and could be much more mainainable if regions would be specified
  • Speedup with using generics in main engine - At first I wanted to stay 1.1 compatible, but now I ask my self where is the sense in that decision. Gtk doesn’t run on 98… so???
  • DataDialog and DataWindow as templates in MD - Now I had to provide DataSource property in source manually when creating it in stetic, by being able to define those two, well… not needed anymore and the fact that forms would be extended if those two would be
  • CellRenderers - Well, I seriously hope I’ll get help on those by public, currently TreeView is very cumbersome to edit. Mainly because editors don’t exist
  • Custom Widgets - Again I hope on external help. For example date editing in Gtk??? Simply sucks. I don’t want some crippled masked edit like usual, they never worked. Main part of work (ComplexEdit - aka. HBox that draws it self as Entry and provides place for entry widgets along with pre and post widgets, for example [[CheckBox Active[]] [Entry,Label,Entry,Label,Picture,Entry] [Label,Picture]]) is already done, just not in svn yet.
  • Widget Flasher - Again already done in basic form and provides custom flashing of widgets (infinite or nr. of flashes with time interval), mostly because it would be really nice to e able to provide more sensible and visible interface
  • Interactor, IDataEditor, GenericDataEditor and DataEditorAttribute - Auto usage of gui by saying for example Interactor.Edit (mydata) and correct dialog with correct posting method would be auto invoked would be really nice
  • A little FAQ

    Ok, so now to explain something that I was asked quite a few times. “How can I help?”. Like first by starting providing help on CellRenderers and Custom Widgets, this work requires the least knowledge of any SDB part. Make workable widget class and then either provide Gtk.DataBindings aware extension (even if extension id not provided, work is so simple that it’ll take me few minutes to make that data widget data aware). Same goes for CellRenderers, example of how to make it data aware is in sample1.

    Another thing people ask is “I would need this or that”, one way is to hack it your self and ask if you need help on parts you don’t know. Maybe,… maybe…. if idea is good I might even hack it my self. And FFS! Don’t as me to help you with something it is not SDB and GDB related.

    The more annoying part is “MS has this and that”, MS databindings are also plagued by insanity. Main feature of Data bindings is to separate gui code from data code. Last thing you want is to have form code as large as ms can become by simple databinding. By that, first provide with problem, don’t start hacking some solution

    And most heard continuation of previous argument is “Tried hacking into your source, but couldn’t find anything, so I started writing my solution”. Well, before you start doing that, try asking.

    Nicest example are converters and validators.

    private DateTime somedate = DateTime.Now;
    public DateTime SomeDate {
      get { return (somedate); }
      set {
        if (somedate == value)
          return;
        somedate = value;
        if (PropertyChanged != null)
          PropertyChanged (this, new PropertyChangedEventArgs("SomeDate"));
      }
    }

    // Every .Net editor can fold this region
    #region SOMEDATE_CONVERTERS

    public int Day {
      get { return (somedate.Day()); }
      set {
        // insert validation if you want
        if (somedate.Day == value)
          return;
        SomeDate = new DateTime(somedate.Year, somedate.Month, value);
      }
    }

    public string Month {
      get { return (MonthNames[somedate.Month]); }
      set {
        int i = MonthNames.IndexOf(value);
        if ((i == -1) || (i == somedate.Month))
          return;
        SomeDate = new DateTime (somedate.Year, i, somedate.Day);
      }
    }

    public string SomeDateAsString {
      get { return (SomeDate.ToString()); }
    }

    #endregion SOMEDATE_CONVERTERS

    public string StatusDate {
      get { return ("Today is " + SomeDateAsString); }
    }

    note,… all properties are alive and boundable. And all widgets are updated when you change any of those. All code is validated, and everything is converted correctly according to your needs.

    Although data Converter/Validator is really simple to integrate (and I might even allow it as it doesn’t enforce any strain on user, but then again promotes having whole bunch of non-sense code). But I won’t be writing one single line of code for them, because they are non sense in my eyes.

    And what about widget validation? Simple solution, when writing for example DateEntry, DON’T USE HALF ASSED APPROACH by using some MaskedEntry, make widget really usable and specifically for Date editing.

    1 Comment more...

    INotifyPropertyChanged and PropertyChangedEventHandler support

    by matooo on Dec.25, 2008, under gtk-databind

    Ok, so I hacked a little and complete Adaptor support for INotifyPropertyChanged and PropertyChangedEventHandler is finished. In fact, not only the way MS did it.

    This solution first checks if object being connected is INotifyPropertyChanged. If it is then it connects its own delegate method which calls Notificator.ObjectChangedNotification(object). But if it is not, then it rechecks all events specified in that class for PropertyChangedEventHandler type and adds same delegate to those. This enables for much more flexibility in class planing.

    ;) If luck is on my side and I succeed to connect same to ObserveableList then support will land in svn the same minute I check the results.

    Data class source (Note: for the nature how SDB works, Name is just as alive as other two properties)
    using System;
    using System.ComponentModel;

    namespace msevent_sample1
    {
      ///


      /// Sample specifying INotifyPropertyChanged
      ///

      public class SampleData : INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;

        private string firstname = "";
        ///
        /// Property defined as usual property according to MS.DataBinding
        ///

        public string FirstName {
          get { return (firstname); }
          set {
            if (firstname == value)
              return;
            firstname = value;
            if (PropertyChanged != null)
              PropertyChanged (this, new PropertyChangedEventArgs(”FirstName”));
          }
        }

        private string lastname = "";
        ///
        /// Property defined as usual property according to MS.DataBinding
        ///

        public string LastName {
          get { return (lastname); }
          set {
            if (lastname == value)
              return;
            lastname = value;
            if (PropertyChanged != null)
              PropertyChanged (this, new PropertyChangedEventArgs(”LastName”));
          }
        }

        ///


        /// This is read only property, but it will act alive same as others
        ///

        public string Name {
          get { return (FirstName + ” ” + LastName); }
        }

        public SampleData()
        {
        }

        public SampleData (string fname, string lname)
        {
          FirstName = fname;
          LastName = lname;
        }
      }
    }

    And code for assignation testing (stripped out the scwl code)
    SampleData data = new SampleData ("John", "Smith");
    Adaptor a = new Adaptor();
    Adaptor b = new Adaptor();
    a.Target = data;
    b.Target = data;
    b.Target = null;
    a.Target = null;

    And since screenshot is impossible for this test, here is console output which takes care of connection and disconnection (and the fact that only single one is activated)

    :) OUTPUT :)
    Starting connection
    ==========================================
    Connecting 1st adaptor
    *** Connecting MS.Events
    Connected INotifyPropertyChanged
    ==========================================
    Connecting 2nd adaptor
    *** Connecting MS.Events
    Denied connection MS.Events (already connected)
    ==========================================
    Disconnecting 2nd adaptor
    *** Disconnecting MS.Events
    Denied disconnection MS.Events (connection is still needed)
    ==========================================
    Disconnecting 1st adaptor
    *** Disconnecting MS.Events
    Disconnected INotifyPropertyChanged

    On the other hand
    I also implemented BaseNotifyPropertyChanged class for a simple convenience. It has already specified PropertyChanged event and added method
    OnPropertyChanged (string PropertyName)
    I used PropertyName so everything can be compatible with standard DataBinding

    Summary
    Strangely, as much as I spit over some things MS did wrong. Implementing this actually presented as really good thing. SDB was already very carefully designed on memory and needs, but I have to admit that this will improve speed even more. Now instead of notifying SDB internals about every change, only changes when delegate connection is active will go through, otherwise it simply returns on if (PropertyChanged != null). Meaning notification queue will have much less to process.

    Well, why not? Life can sometimes play nice with something like this free gift of gaining improvement elsewhere by doing something completely different ;)

    6 Comments more...

    Adaptors (part 1 - Basics)

    by matooo on Dec.20, 2008, under gtk-databind

    Well, for the start first thing that should be explained is the difference and commonality between Adaptor and DataSource terms. Like first DataSource is commonly used property which specifies object that will provide data. And Adaptor? Adaptor is a class which specifies object that will provide data. wtf? That is the same? Well, yes and no. Like first one is property and one is a class.

    Remember old fashioned pointers pointer can point to pointer, which can point to another pointer which points to data. A simple linked list. But we could always access end of the chain. Like every pointer list, Adaptor list can have multiple start points all converging at the same finish Target. But, in the need to be explanatory, I need to explain basic Adaptor innards.

    For end user only two properties are needed to know how to use. Target and FinalTarget. And as it was already explained with pointer chain…

  • FinalTarget returns exactly that. End of chain or null if end of chain is IAdaptor type with (Target == null).
  • Target on the other hand is world writeable and specifies next in chain line.
  • When resolving FinalTarget, Target simply checks if Target is IAdaptor. If it is it simply does return ((Target as IAdaptor).FinalTarget), otherwise it simply returns its own Target. Which means FinalTarget CAN NOT be IAdaptor.

    Now, the harder to understand part. Widgets actually don’t care what type its DataSource is (Just to brag a little, even list widgets like DataTreeView don’t care about that. It has optimized property transfer for default type, but if type processed is of another type, it will simply use what it can and avoid what it has, but more on this latter when explaining DataTreeView). Don’t even care is Property with mapped name is. By default Gtk part of System.Data.Bindings simply disables that widget if (DataSource == null) or property with mapped name doesn’t exists in object mapped as DataSource.

    As widgets DataSource you can specify any object including Adaptor and as you’ll see later, probably even preferably if you specify Adaptor as DataSource, as it offers something static data sources can’t. Flexibility and by flexibility, I really mean FLEXIBILITY.

    Adaptor posts changes trough event messages to all interested parties which also includes all chain connected Adaptors. Messages as in normal language are “Hey, data changed” and “Hey, my target changed”. Which simply means that all Adaptors in chain will resolve their FinalTarget asap after TargetChanged message has been dispatched.

    Last thing important to know about adaptor is DoGetFinalTarget(). By overriding this method you can specify another FinalTarget based on parameters. Just as in case of MappedAdaptor. MappedAdaptor resolves its data target differently. Instead of providing FinalTarget like usual Adaptor, MappedAdaptor resolves the usual way and then after that resolves mapped property. Here is a nice example of such data classes:

    class Person {
      ....
    }

    class Company {
      ....
      Person Manager { .... }
    }

    Which is following the mapping code:

    Adaptor a = new Adaptor();
    MappedAdaptor ma = new MappedAdaptor();
    ma.Mappings = "Manager";
    ma.Target = a;

    So, what do we have here now? Lets say we have company1 and company2 objects pointing at two different data.
    By simply pointing
    a.Target = company1;
    all widgets connected to either a or ma adaptors will reflect change and display/edit new data. As easy as that. Practically same as “xxx.xxx” type of property mapping, except that it is all part of one same engine, which means it works the same as everything else Adaptor based.

    There is one another big difference between MS data bindings and SDB+GDB. All widgets can have InheritedDataSource, which simply means it will inherit DataSource from first container specifying its own DataSource, but if that container specifies InheritedDataSource = true; then it will inherit it from its parent container and so on.

    By using Adaptor, MappedAdaptor, InheritedDataSource and Mapping correctly, you can simply map gui into one big living thing. Specify data source once and all gui will reflect it. Never connect or disconnect. All that connection/disconnection is happening automatically.

    Which concludes Adaptor (part 1 - Basics)

    1 Comment more...

    Another short “why not”

    by matooo on Dec.19, 2008, under gtk-databind

    One of the questions that were raised once too often is why I didn’t support complex mapping to subproperty something like “Manager.Name”. Well, I did… But not like that, no matter how much I wished to make this work like this, it never was 100%. Either memory lacked, was not flexible enough, didn’t work as it should. So I decided on another bulletproof solution called MappedAdaptor. For now, the only important thing is the fact that it works, but explanation will follow today or tomorrow when I’ll tackle with the explanation what Adaptor is, how to use it, how it works and how to make specialized adaptor subclasses.

    Leave a Comment more...

    Looking for something?

    Use the form below to search the site:

    Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

    Visit our friends!

    A few highly recommended friends...

    Archives

    All entries, chronologically...