Re: RFC: Model-View-Controller
On Nov 16, 2011, at 9:22 PM, Benjamin Otte wrote: On Wed, Nov 16, 2011 at 9:37 AM, Kristian Rietveld k...@loopnest.org wrote: If there are multiple views, which are changed by which controller? What complicates thinking about this for me is that in MVC as I know it, there is 1 Model, 1 View and 1 Controller for each thing. I think this is where the misunderstanding is. I probably shouldn't have mentioned MVC in the email and named it actions and actors and just used the clutter terminology. That is very likely ;) I now also understand that all these objects would be allowed to do drawing for the widget they are connected to, etc. Still it is a very good idea to get some prototyping going to get a feel for this and to see how much code it would save in the end. I like the examples put forward by Federico: GtkButton/GtkScrollbar and text selection. you'd write a GtkTreeViewView object that'd draw a treeview. That's indeed kinda very useless. If one would do *real* MVC, then something like a GtkButtonView does make sense and is definitely not useless. The point is then that you have different implementations of GtkButtonView for e.g. normal displays, small displays, touch screen/tablet. You would also have different implementations of a GtkButtonController according to the input method used (mouse vs. touchscreen is a good example). regards, -kris. ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: RFC: Model-View-Controller
On Fri, 2011-11-11 at 15:55 +0100, Benjamin Otte wrote: [Talking about GtkButton] And it'd have those Controllers: (- Hover) - Click - Activate (- Focus) - KeyPress/Release I just took a quick look at ClutterClickAction and ClutterDragAction. They are certainly interesting. I wonder how things would look once you have widgets with complex behavior. Let me reintroduce something I talked about during the Desktop Summit - form languages and pattern languages. The way I see things, you want to encapsulate common actions as controllers, and common drawing idioms as views, so we can compose them into final widgets. I.e. you want to make the form language finer-grained and richer, so it will allow us to implement patterns more easily. Think of an app that lets you select graphical objects and move them by dragging. How would you implement something that needs both clicks (quick press/release with no movement) and drags (long press-move-release)? Do you need to somehow tie together a ClickController and a DragController, or do you have a generic PressMoveReleaseController, on top of which you implement the other two? As you said, for GTK+ it probably makes sense to start by abstracting out simple views and controllers. Exercise: do that in a branch for buttons and clicks, and refactor GtkButton and GtkScrollbar's arrow buttons to use that. See how the code looks. Then you may want to tackle GtkEntry's clickable icons in terms of the click controller as well. A much harder view/controller would be for selectable text. GtkEntry picks out the first PangoLayoutLine from the PangoLayout, and runs pango_layout_line_x_to_index() on it. However, GtkLabel does a direct pango_layout_xy_to_index(). No idea why GtkEntry does it like that; maybe it wants to explicitly ignore everything but the first line in the text. GtkEntry has scrolling offsets, but GtkLabel doesn't... etc. No idea how a SelectableTextController would look :) Federico ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: RFC: Model-View-Controller
hi Federico; On 17 November 2011 18:50, Federico Mena Quintero feder...@gnome.org wrote: On Fri, 2011-11-11 at 15:55 +0100, Benjamin Otte wrote: [Talking about GtkButton] And it'd have those Controllers: (- Hover) - Click - Activate (- Focus) - KeyPress/Release Think of an app that lets you select graphical objects and move them by dragging. How would you implement something that needs both clicks (quick press/release with no movement) and drags (long press-move-release)? Do you need to somehow tie together a ClickController and a DragController, or do you have a generic PressMoveReleaseController, on top of which you implement the other two? no, there's no base class, and there's no need for one. ClickAction and DragAction (and basically all event-related code in Clutter) do not use grabs: they use the capture phase of the event delivery cycle, and they will not stop the event propagation, so you can assign them both. the capture phase is far less destructive of event handling in complex scenarios than a X11 grab; gtk+ should get a ::captured-event signal as well in the near future. DragAction also uses the drag-threshold setting, so it will be able to detect a drag after a certain amount of space has been covered by the pointer with the BUTTON1 mask set. Lucas used ClickAction and DragAction inside his Board project, to be able to interact with the items on the board, as well as repositioning them around. aside from ClickAction and DragAction, Clutter also has a GestureAction that allows you to implement gesture recognisers, and cancel gestures in progress to pass the control flow to the next action; these gestures will be used more as soon as the multi-touch support in X11 lands, so we can have a common implementation across OSX, X11, and Wayland. ciao, Emmanuele. -- W: http://www.emmanuelebassi.name B: http://blogs.gnome.org/ebassi/ ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: RFC: Model-View-Controller
Hi, I share the concerns Mitch has raised. It is obvious that a redesign would help the organization of widget code and several people have thought about ways this can be done (e.g. Rapicorn and I also vaguely recall somebody trying to do pure MVC with GTK+). Some more comments and thoughts below. On Nov 9, 2011, at 7:12 PM, Benjamin Otte wrote: - widget complexity Our widgets - even the simple ones - are hellishly complex objects. Without reorganization of the code they'll get unwieldable. Here's the 5-digit source files in the gtk sources: 10464 gtkfilechooserdefault.c 10482 gtkentry.c (10947 gdkwindow.c) 13857 gtkwidget.c 16439 gtktreeview.c Of the widgets you list I don't think GtkFileChooserDefault belongs there, because it is a composite widget where the others are not. We need a way to make that code readable again. Also, those files generally have lots of interactions and a high cyclomatic complexity[1], which makes it hard to understand what they do. This in turn leads to people being afraid of touching them. And that starts a vicious cycle. About the interactions, does the MVC approach proposed really solve this and doesn't it lead to people being afraid to touch the class hierarchies and interactions between the different views and controllers? In the simple examples in your other e-mail, there are already quite some connections between objects involved. I'm proposing a Model-View-Controller split for widgets.[2] I want to split the source code for widgets into three parts. This is mostly an internal cleanup and should not affect applications that use widgets. It would however change the way widgets are coded. So this is mostly relevant for our own gtk/ directory, but would also be interesting for other widgets ike the evo calendar, EMap, the WebKitWebView, GtkSourceView, you name it. So if I understand correctly, you want to re-do the implementation of widgets without changing the outside interface? But you also want to expose the MVC objects to the outside to be used in third-party widget implementations. I am wondering whether this won't get very confusing/messy. The reasons why objects are currently so large are: 1) View and Controller are combined in the same class, as has already been pointed out. 2) Objects are often too specific to allow re-use; granularity is wrong. If I would apply pure MVC to GtkTreeView, then we will still end up with a huge view and a huge controller class. We already have the model class. To achieve the desired simplification GtkTreeView will have to be split up into pieces, pieces which can be better re-used. I see this transformation as a separate one from the transition to MVC. So what you are actually proposing is both introducing MVC and splitting up the objects (albeit in an API compatible fashion). I would argue that with just introducing the splitting and not doing MVC, we can already gain the majority of the code clean up. I explicitly say majority, not all, because your approach, if feasible, would further increase code re-use. You might indeed want to split out rubberbanding into a separate class to not have to re-implement it in both an item container and somewhere else. Whether we should then call this a rubberbanding Controller is something I am unsure about. For GtkTreeView a start was made by pushing code into GtkCellArea, but much more is necessary. In an earlier thread, I have once sketched plans to have a generic item container which would implement click handling, rubberbanding, drag and drop, keyboard handling, etc, etc. Subclasses can then plug in specific layouting algorithms which make them a GtkTreeView or GtkIconView. The other point to make here is that the above sketch for GtkTreeView is one possible way to do it. The main problem with point 2) is picking the right granularity, there are multiple thoughts about this (e.g. the micro widget approach from Rapicorn) and making this decision can turn out to not be that easy. Sounds like a plan? My feeling is that in order to come up with a solid plan, prototyping has to be done to figure out whether this is feasible and how things will look like. regards, -kris. ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: RFC: Model-View-Controller
On Wed, Nov 16, 2011 at 9:37 AM, Kristian Rietveld k...@loopnest.org wrote: If there are multiple views, which are changed by which controller? What complicates thinking about this for me is that in MVC as I know it, there is 1 Model, 1 View and 1 Controller for each thing. I think this is where the misunderstanding is. I probably shouldn't have mentioned MVC in the email and named it actions and actors and just used the clutter terminology. The whole idea has nothing to do with classical MVC. It's all about splitting common interactions into separate objects - like click, drag or rubberband - that you can then the controller would probably emit events that you can hook into if you want or let it do its default thing (draw a blue selection rectangle) if you don't want to. Of course, you want to connect to the finished signal for events to update the widget. The same thing for the view thing, it's more about making drawing operations stateful and giving them objects. So instead of gtk_render_background(), you'd instantiate a GtkBackground object and it'd do whatever needs doing to get it onto the screen. It's not like you'd write a GtkTreeViewView object that'd draw a treeview. That's indeed kinda very useless. Benjamin ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: RFC: Model-View-Controller
Hi Benjamin, I am sorry but this sounds like a lot of things, but not like a plan. - are our widgets a more-or-less huge mess? yes. - do we need to do something about it? yes - is MVC a well tested way to improve things? yes - does it always work? NO Sorry, but you are actually stating the obvious here, but fail to provide *any* example, outline, not even a simple diagram. Without any small example-ish thing to see what you mean here, this is pretty much hot air :( But I surely don't want to sound discouraging, please give a small example. Regards, --Mitch On Wed, 2011-11-09 at 19:12 +0100, Benjamin Otte wrote: Hey, so I've been thinking about this for a bit, and I think it's a good idea, but I wanted to see if other people have an opinion about it. And I wanted to get it into people's minds before we sit down for a hackfest. So this idea is a result of the mainly the following things: - Clutter integration Clutter has the concepts in some form or another. It doesn't use the definitions I'm about to use, but it has the objects I want. - widget complexity Our widgets - even the simple ones - are hellishly complex objects. Without reorganization of the code they'll get unwieldable. Here's the 5-digit source files in the gtk sources: 10464 gtkfilechooserdefault.c 10482 gtkentry.c (10947 gdkwindow.c) 13857 gtkwidget.c 16439 gtktreeview.c We need a way to make that code readable again. Also, those files generally have lots of interactions and a high cyclomatic complexity[1], which makes it hard to understand what they do. This in turn leads to people being afraid of touching them. And that starts a vicious cycle. - functionality duplication A lot of widgets duplicate functionality. Treeview and iconview have rubberbanding. Entries have progress bars and icons. Notebooks, treeviews, expanders and whatnot have buttons. We do not only duplicate the code here, but also behavior and policies. So if we decide to change the states on buttons or the way rubberbanding does autoscroll, we need to fix all of the widgets individually. And as we are currently in a process of reinventing large parts of the toolkit - both for UI design and for form factor reasons, we need to be able to change these things quickly. And currently we can't even get rid of underallocations. So what am I actually talking about? I'm proposing a Model-View-Controller split for widgets.[2] I want to split the source code for widgets into three parts. This is mostly an internal cleanup and should not affect applications that use widgets. It would however change the way widgets are coded. So this is mostly relevant for our own gtk/ directory, but would also be interesting for other widgets ike the evo calendar, EMap, the WebKitWebView, GtkSourceView, you name it. The first thing I want to do is to create View objects. So instead of having a huge draw() function, the widget would create a bunch of View objects. We would provide a few common ones (probably one per gtk_render_foo() function we currently have) and widgets would put them where they belong in the size_allocate() function. After that, they would take care of drawing themselves and all the stuff associated with looking cool based on CSS and their surroundings. In Clutter terms this is what ClutterActor is. Of course, they would probably provide other information, too, like sizing or the actual layout of text. And once we have that, we can attach additional information to these objects, like animation state, effects, caches and so on without the widgets having to care. The second thing I want to is create Controller objects. So instead of having input events handled on the widget, we add a bunch of controllers to the widget that take care of handling events and emitting signals for when the user did interact with the widget. These would go from very simple things like click, doubleclick or scroll controllers to more complex things like rubberband or dnd controllers. The Clutter equivalent here is ClutterAction. Of course, the actions will probably require a bunch of properties and will also emit quite some signals that widgets will use, but they can do things like keeping track of the device they're interacting with and things like that. And once we have that, we can attach lots of new controllers, like gesture controllers, or even switch controllers based on input method used. And of course, we have less place where we can control things like dnd threshold, double-click time, rubberband and dnd scrolling speed and gesture definitions. That leaves the widget itself as the Model (I think the correct term would be Application in the MVC context here, but bear with me, this makes it sound cooler). So the widget's job moves further away from GDK (or Cairo, Clutter or whatever the backend is) and more into the realm of being the manager between the application and the person in front of the screen. It
Re: RFC: Model-View-Controller
On Fri, Nov 11, 2011 at 2:47 PM, Michael Natterer mi...@gimp.org wrote: Hi Benjamin, [snip typical German ecouragement talk] please give a small example. (disclaimer: just to illustrate the idea, might change a lot) So, a GtkButton is kinda complex from the input perspective, but simple for drawing. It would have these Views: - Background - Child It would inherit those from GtkBin, so it wouldn't have any drawing code at all. And it'd have those Controllers: (- Hover) - Click - Activate (- Focus) - KeyPress/Release Not sure if hover and focus should be default or separate controllers. What they'd do is toggle the :focus and :hover state on the widget and nothing else. The click controller would capture mouse presses, take a grab, and on release it'd make the button emit clicked. Same as the KeyPress/Release controller (which would only capture space, return and whatever else activates a button). And the Activate controller would respond to gtk_widget_activate(). A GtkLabel would have these Views: - Background (or not - it'd have it in GTK4, maybe not in GTK3, where labels have no background) - Text and it'd have probably these Controllers: - Rubberband - Click - DoubleClick - Drag - KeyPress/Release I wanted to call Rubberband Drag, but that'd confuse people with DND. What I mean is pressing the mouse, holding it and releasing it elsewhere. Consider the name a work in process. All of them would only be active if the label was selectable. Rubberband would be used to do a selection, drag would allow DND'ing the selected text. The KeyPress/Release controller(s) would be used for the general selection handling in text, as would the Click and DoubleClick ones. (I suppose we would have one that'd be shared between all the text-handling widgets that ensured all our keybindings were identical and the selection behavior consistent - try double-clicking between words in different widgets for some fun.) Now for some fun widget, the notebook. We'd have these views: - Background - Child (for the active widget) - per action and arrow button: - Background - Icon per tab: - Background - Child And these actions: - Drop (for tabs maybe?) - per action and arrow button: - Click - Focus - Hover - KeyPress/Release - per tab: - Click - Focus - Hover - KeyPress/Release - Drag (to drag tabs elsewhere) - Drop (for tabs) - Activate (for keybindings) - per close button on the tab: - Click - Focus - Hover - KeyPress/Release You would probably be able to limit actions to certain areas/views of the widget, so the hover/focus actions would be setup to only apply to the ones they are about. It'd at least solve all our bugs with focus, hover and whatnot not working properly on notebooks that get filed and fixed regularly. Or we would make the notebook have real buttons, at which point the actions would be setup by the button. Then we'd just have to solve attaching the DND actions to the button. But with such an approach, the notebook code would look less scary (apart from the setup code...). We'd just move some views around in size_allocate and connect some signals and that'd be that. I'm not even going to try to imagine the setup for the treeview here... That said, you can see that the number of different views and controllers is quite small. It's just that we duplicate their functionality over and over and over again. And you can maybe start to imagine what would happen when people started adding gestures etc to the notebook code... Benjamin ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: RFC: Model-View-Controller
On Wed, 2011-11-09 at 19:12 +0100, Benjamin Otte wrote: The first thing I want to do is to create View objects. ... In Clutter terms this is what ClutterActor is. ... The second thing I want to is create Controller objects. ... The Clutter equivalent here is ClutterAction. How about just using Clutter's Actor / Action terminology in GTK? Might make things a bit simpler. The three terms in MVC brings a bit of its own conceptual baggage and meanwhile we already have TextView and TreeModel going on; the overload on view and model might get annoying. {shrug} AfC Vancouver ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
RFC: Model-View-Controller
Hey, so I've been thinking about this for a bit, and I think it's a good idea, but I wanted to see if other people have an opinion about it. And I wanted to get it into people's minds before we sit down for a hackfest. So this idea is a result of the mainly the following things: - Clutter integration Clutter has the concepts in some form or another. It doesn't use the definitions I'm about to use, but it has the objects I want. - widget complexity Our widgets - even the simple ones - are hellishly complex objects. Without reorganization of the code they'll get unwieldable. Here's the 5-digit source files in the gtk sources: 10464 gtkfilechooserdefault.c 10482 gtkentry.c (10947 gdkwindow.c) 13857 gtkwidget.c 16439 gtktreeview.c We need a way to make that code readable again. Also, those files generally have lots of interactions and a high cyclomatic complexity[1], which makes it hard to understand what they do. This in turn leads to people being afraid of touching them. And that starts a vicious cycle. - functionality duplication A lot of widgets duplicate functionality. Treeview and iconview have rubberbanding. Entries have progress bars and icons. Notebooks, treeviews, expanders and whatnot have buttons. We do not only duplicate the code here, but also behavior and policies. So if we decide to change the states on buttons or the way rubberbanding does autoscroll, we need to fix all of the widgets individually. And as we are currently in a process of reinventing large parts of the toolkit - both for UI design and for form factor reasons, we need to be able to change these things quickly. And currently we can't even get rid of underallocations. So what am I actually talking about? I'm proposing a Model-View-Controller split for widgets.[2] I want to split the source code for widgets into three parts. This is mostly an internal cleanup and should not affect applications that use widgets. It would however change the way widgets are coded. So this is mostly relevant for our own gtk/ directory, but would also be interesting for other widgets ike the evo calendar, EMap, the WebKitWebView, GtkSourceView, you name it. The first thing I want to do is to create View objects. So instead of having a huge draw() function, the widget would create a bunch of View objects. We would provide a few common ones (probably one per gtk_render_foo() function we currently have) and widgets would put them where they belong in the size_allocate() function. After that, they would take care of drawing themselves and all the stuff associated with looking cool based on CSS and their surroundings. In Clutter terms this is what ClutterActor is. Of course, they would probably provide other information, too, like sizing or the actual layout of text. And once we have that, we can attach additional information to these objects, like animation state, effects, caches and so on without the widgets having to care. The second thing I want to is create Controller objects. So instead of having input events handled on the widget, we add a bunch of controllers to the widget that take care of handling events and emitting signals for when the user did interact with the widget. These would go from very simple things like click, doubleclick or scroll controllers to more complex things like rubberband or dnd controllers. The Clutter equivalent here is ClutterAction. Of course, the actions will probably require a bunch of properties and will also emit quite some signals that widgets will use, but they can do things like keeping track of the device they're interacting with and things like that. And once we have that, we can attach lots of new controllers, like gesture controllers, or even switch controllers based on input method used. And of course, we have less place where we can control things like dnd threshold, double-click time, rubberband and dnd scrolling speed and gesture definitions. That leaves the widget itself as the Model (I think the correct term would be Application in the MVC context here, but bear with me, this makes it sound cooler). So the widget's job moves further away from GDK (or Cairo, Clutter or whatever the backend is) and more into the realm of being the manager between the application and the person in front of the screen. It has an often simple model (for GtkEntry or GtkLabel this is a string), some additional information about the model (word-wrap, editability, etc) and manages how people in front of the screen, developers and possibly IPC interact with it. Sounds like a plan? Benjamin 1: http://en.wikipedia.org/wiki/Cyclomatic_complexity 2: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: RFC: Model-View-Controller
On Wed, 2011-11-09 at 19:12 +0100, Benjamin Otte wrote: Hey, so I've been thinking about this for a bit, and I think it's a good idea, but I wanted to see if other people have an opinion about it. And I wanted to get it into people's minds before we sit down for a hackfest. Please don't take Model-View-Controller paradigm too literal. It can help when designing things; but at the same time it can be overly complex if implemented. If you don't believe me, take a look at libmeegotouch [LMT]. It's MVC in its purest form, and everyone hated it in the end. regards, Michael [LMT] https://meego.gitorious.org/meegotouch/libmeegotouch ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list