|
>So where does the misunderstanding come from? It comes from recent changes in how developers (ab-)use GUI frameworks. I haven't full grokked how this came about, but it seems to be part (a) widget toolkits (b) horrible drawing APIs and (c) the iPhone with LayerKit/CoreAnimation. This change has been that for example, when there is just some dynamic text to draw, people have been using text-label widgets instead of just drawing the damn text in drawRect. So suddenly you have people constructing, adding and removing views at runtime as a matter of course, rather than as something done in exceptional circumstances, which I gather is what you (rightly) object to. However, this is not the "programming model" of GUI frameworks, it is an abuse of those GUI frameworks. Not sure when your "recent" (in "recent changes") refers to. That's how GUI frameworks have worked at least since they've provided a widget hierarchy (with labels, containers, buttons, and so on). Delphi was like that, Swing was like that, QT was like that, GTK was like that, NeXT GUI lib was like that, Cocoa was like that, the old Mac OS 8 lib up to 8 was like that, and so on. Heck, even Athena was like that. The GUI programmers and frameworks that have been "drawing the damn text in drawRect" are in the absolute minority, not since CoreAnimation, but since forever. In fact, you even mention "I haven't full grokked how this came about, but it seems to be part (a) widget toolkits (b) horrible drawing APIs and (c) the iPhone with LayerKit/CoreAnimation.". The first of those things, (widget toolkits) is 30+ year old, and has been synonymous with GUI development since forever, at least in the desktop application space. >However, this is not the "programming model" of GUI frameworks, it is an abuse of those GUI frameworks. Yeah, not really. Not only this is prevalent and common sense understanding of "GUI framework" in the last 3+ decades, but merely having some drawRect and co (without a Widget set) wouldn't even qualify as a "programming framework" at all, people call those "a graphics library". "drawRect" has not been the main GUI programming tool since forever, except when a developer wanted to make their own custom widgets. Whole GUI apps never once call drawRect (or its equivalent in their lib) directly. |
However, I am not sure where you got the idea that I denied the existence or use of widget toolkits, since they are central to the whole development. However, I don't buy your claim that the existence of widgets meant that nobody ever implemented drawRect::. That's just a false dichotomy.
For example, I just googled "open source Mac app", then went to the source for the first entry, Adium (https://github.com/adium/adium/tree/master/Source) and the first 3 implementation files I looked at all had an implementation of drawRect:: Second entry is Disk Inventory X. Includes a TreeMap framework, 5 classes, in is a view with a drawRect::.
In general, my experience is that you typically use a custom view for whatever your app is centrally about. For example, a drawing app has a custom Drawing view. A word processor has a view for the text, a spreadsheet for the central table. At the very least. Around the central view you would arrange tools and other chrome built out of the widgets of the toolkit.
The widgets are, however, not really part of the MVC pattern, they are tools you use to interact with the model, they rarely reflect the model itself (except maybe for being enabled/disabled).
In terms of horrible text drawing API, I don't know about other platforms, but for NeXTstep/Cocoa that happened with the transition away from DisplayPostscript. With DPS, text drawing was trivial and malleable. With the OSX/Quartz transition, text-drawing was delegated to ATS, with some of the most arcane, inconsistent and difficult to use APIs I've had the displeasure to use. And alas these were not built on top of the much saner Quartz APIs, which were bottom-most for everything else, but instead the Quartz text APIs were trivial and very limited convenience wrappers for underlying ATS calls. Sigh.
(And I realise that this is quite a while ago. (a) Yes, I'm old (b) I don't think the text APIs becoming horrible was a trigger, they already were when things changed)
The type of app that only used the widget set definitely also existed: these were the business/database apps or the like that just interfaced with textual/numerical data/tables. Those you often could build using just the widgets as-is, without ever creating a custom view. Apple concentrated a lot on those use-cases in their public communication, because NeXT's focus had been business apps and they made for great "look ma, no code!" demos.
Of course, these widgets aren't really connected to a wider model, they contain their own little model and MVC triad. In the case of Apple, they tried to fix that with bindings[1], but that was only a partial success. So the ViewControllers (which already existed, I think) jumped in and the "update view" part of MVC became "set the content object of this widget". This can actually work fairly well, if you really treat the ViewController as a View (this is entirely permissible, MVC describes roles, not objects) and really, really only do that update when you get a notification that the model has changed. Alas, that isn't enforced or even supported much, so you get arbitrary cross-view modification. Sigh. Slightly better support would probably help here, for example Notification Protocols[2].
So that leaves addSubview, adding and removing subviews for dealing with dynamic data. I'd still maintain that this is a fairly recent development as a major way of achieving UI dynamism, and I also think that its rise roughly coincides with the rise of the iPhone. And I also think that, even though this technique is now widely used, the basic widget sets aren't really well equipped to deal with that way of working, or with helping developers not make a hash of things. Because that's not how they were designed. They were designed to deal with fairly static hierarchies of views that manifest themselves and any dynamic content on the display using drawRect::.
[1] https://blog.metaobject.com/2014/03/the-siren-call-of-kvo-an...
[2] https://blog.metaobject.com/2018/04/notification-protocols.h...