You can make throw an error if a function is called without expected arguments, but not if a function is called with more arguments than expected.

I think maybe fixes this by allowing "void" as an argument type? I don't yet have a system with PHP8 on it, though, so I don't actually know.

If it doesn't, then this is a .

"open file" dialogs that hide dot-files/folders and don't give you any option to key in a path manually

I'm not sure whose fault this is, but I encounter it trying to open a ssh keyfile in MySQL Workbench under .

Also... no right-click options at all?? That's ridiculous.

Right-clicking on the desktop should give you access to the display configuration.

(It used to, but I can't remember if this was under a Linux distro or Windows 98SE. Either way, current behavior -- which only gives you access to the wallpaper and other aesthetic stuff -- is a step backwards.)

Also, when you can't copy one file (e.g. because it's a device and can't be copied), "skip all" should not mean "skip all the rest of the files even if you can copy them just fine". That operation is more commonly referred to as "cancel".

Show thread

"Cancel without requesting confirmation" should never be the default option when a key is pressed.

(lookin' at you, file-copying dialog box)

Minor-ish (setting a somewhat higher bar than usual)

  • Yes, you can plug in two monitors and get two different workspaces.
  • Yes, you can switch the "main" workspace from one to the other, so your menu and taskbar appear on either one.
  • No, you can't set it up so both of them have menus and taskbars.

I have two monitors on different sides of the room, attached to the same PC but facing in different directions for different tasks -- namely (a) music recording stuff and (b) everything else -- but when I'm at monitor 2, I just get a wallpaper with no controls, unless I launch something on monitor 1 and drag it over before going over there myself.

I'm using . Is there maybe a desktop package which handles this better/properly?

I think I've figured out one of the problems I'm running into with traits in .

Background

The canonical usage of a trait is to define a set of behaviors that work together -- a feature that classes can use, basically.

That often requires initializing some stuff within the trait.

If it's just a matter of setting initial values for member-variables, you can do that when those members are declared... but if it involves picking up information from the host-object[1] , then some code needs to be executed before trying to access any of the trait's functionality.

There are a couple of ways to handle this.

A. The trait can declare a constructor, if it knows enough about the potential host classes[2] to do that gracefully (i.e. without interfering with their construction processes) to execute the initialization code.

B. The base class can define an initialization event (I usually define function OnCreate() : void) for the trait to implement.

C. The trait can check itself for initialization every time any of its methods are called. (This probably works, but hurts my optimizing-squirrel's soul.)

Minor Obstacle

It starts to get tricky if the host-class also needs to do some initialization, because if class A uses trait B and they both define function X(), A::X() can't call parent::X() to access B::X()... but there's a syntax for hosting traits which allows their functions to be aliased to another name when hosted, so you could rename B::X() to B::Trait_X(), and then call that.

...which means that whenever you host the trait, you also have to remember to do the aliasing.

The Problem

The real problem is when I have a set of traits that all get hosted together.

...and they all need initialization.

So say you have class A which needs traits B,C, and D, each of which has its own OnCreate() function that needs calling.

I guess it can be done by aliasing OnEvent() in each one (OnEventB(), OnEventC(), OnEventD()), then explicitly calling those each individually from A::OnEvent()... but that seems messy and easy to get wrong. There's too much stuff that needs to be done manually.

I guess it can be slightly tidied by declaring OnEvent() under a different name in each trait -- basically pre-aliasing them -- so the only messy part is that you have to explicitly call the aliased OnEvent()s from A::OnEvent()... but it still seems like this kind of breaks how class-inheritance is supposed to work.

You should be able to just use a trait, and not worry about initialization.

I should be able to just call parent::OnEvent() from A::OnEvent() to get D::OnEvent(), which would then call parent::OnEvent() to get C::OnEvent()... and so on, up to B::OnEvent() calling parent::OnEvent() to get A's parent class's OnEvent()[3] .

A way to kluge that desired behavior, I suppose, would be to have a series of intermediate classes:

class AB hosts trait B
class AC hosts trait C and extends AB
class AD hosts trait D and extends AC
class A extends AD

...in which case calling up the parent chain would work as needed.... but again, that's kind of messy: more code to manually include.

I'm not sure which of those last two solutions creates the least technical debt, and I keep feeling like there's got to be a better solution, even without changing how PHP handles traits.

I guess I'll try some things and see how deep a pit I end up digging myself into...

(is this a , or something else?)

Notes

  1. When I say "host class", I mean a class that has used a trait. If class A has use B;, then A is hosting B. Similarly, a "host object" is an instantiation of a class that is hosting a trait.
  2. This is one of the reasons I wish traits could "require" their host-class to be of a certain class-family, so a trait can prevent itself from being used by a class-family that it's not designed to work with.
  3. ...or it could work the other way: functions in hosted traits could take precedence over the host-class's functions -- so if class A hosts trait B, and class C extends A, and they all declare OnEvent(), then C calling parent::OnEvent() would call B::OnEvent() and B calling parent::OnEvent() would call A::OnEvent() -- that would be fine too.

I just love it when web sites set up their login page so web browsers don't recognize the password field, and I have to go look up my password because the browser won't fill it in.

Sometimes they even disable pasting.

Both of these make me inclined to use a less-secure password, so I can remember it and type it easily.

Nice , guys.

Also, if trait A and trait B both have a function X(), and I use both of them in the same class, why not just use the X() from whichever trait is named last?

Show thread

Fatal error: Trait method FieldCollective has not been applied, because there are collisions with other trait methods on greenmine\workferret\cCommonTable in /home/htnet/site/git/greenmine/dropins/WorkFerret/lib/base.php on line 25

Ya know, , it would be reeeally helpful if you could tell me what methods are colliding, rather than just mentioning one that isn't.

Whyizzit that both Kate and KDevelop know how to load a folder when it's on the local drive, but don't know how to load it when it's on a remote?

KDevelop does a decent job of mapping out classes in a project, but does nothing at all for traits or interfaces.

Just so you don't think my tendency to is a recent thing, possibly due to becoming old middle-aged growned-up and cranky, here's one I wrote in 1997 as a mere stripling of 32!

One thing that drives me crazy on a regular basis is that well-known graphical user interface convention, the double click.

Certain screen widgets only respond to double clicks; however, the GUI (whether it be Windows, Mac, or Other) is pretty picky about the timing of these clicks, and I often find myself double-clicking over and over again with no response. Click too slowly, and the widget sees two single clicks -- it highlights itself and then goes back to sleep. Click too quickly, however, and some helpful code buried deep in the OS decides the mouse must have a dirty switch contact, and you really meant a single click. The OS may also be getting confused about which clicks are "paired"; e.g. was this click the second part of a double-click or the first part of the next double-click?

I could go off about how there ought to always be a way to adjust the minimum time (the “dirty single-click” ceiling) to accommodate users who click quickly sometimes and slowly other times, but really I think the whole double-click concept was poorly conceived in the first place. I'm convinced that GUIs ought to discard the double-click concept and instead respond to what I call state-based clicking.

So let's go back in time a little bit. We're designing the first GUI. We have widgets on the screen, and we have a mouse to point at them and a button to push (click). We find pretty quickly that there are two major things you might want widgets to do in response to a button push: select themselves (for inclusion in a set to be operated on by another control e.g. the keyboard or an application), or execute themselves (i.e. open a file or run a program).

So how do you signal which of two actions you want using only one button? Somebody decided that if you click twice in rapid succession, that should mean the more "active" of the two options, i.e. execute. Fair enough. But how about this: click once, the object selects itself. Click on a selected widget -- whether 0.025 seconds later or tomorrow morning -- and the widget executes.

Potential problem #1: what happens when you want to move a selected object? Possible solution: an object must not be selected before it is grabbed. If you accidentally select it first, de-select it by clicking anywhere else. Potential problem #2: what about dragging multiple widgets, which must be selected in order to be part of the drag-group? Solution: when more than one widget is selected, only dragging is possible.

I implemented this solution as part of a custom-made file-open dialog for an image processing program, and found it quite satisfactory. I never had to stop myself from clicking madly, wait a full second, and then carefully click in a deliberate and methodical way in order to load a file. (The other custom-made part was that the file dialog stayed open after the file was loaded -- but that's another rant.)

I'll be solving more of what's wrong with computers as time permits, and then we’ll start in on death and taxes. Happy clicking!

Bonus for those who read this far: here is the original, complete with deadname! ^.^

Mouse operations have obviously become a lot more complex since then, not to mention touchscreen stuff, but I always felt like we kind of went down the wrong path by making duration semantically significant in GUI interactions -- and the whole "press-and-hold" paradigm (now popular with power-switches and smartphones) feels like further digging in.

...but of course there are many more-obviously-terrible choices that computing has made since then, so this is kind of nitpicky anymore.

If you have to click outside of a drop-down or popup to make it go away, that same click shouldn't also trigger an action on what's behind it.

@nextcloud takes, like, half an hour just to scan for new changes in our main fileset. There's got to be a better way, surely? (provisional)

It's annoying that in I can't declare an interface with very general terms (e.g. a class that handles some kind of variable, type unspecified, in various ways) and then implement it with more specific terms (e.g. this class handles strings in the same ways, this other class handles objects of a certain class family...).

So, I get a popup saying my system drive is nearly full. (Understandable; it's this 256 GB SSD drive about the size of half a business card.)

I run FileLight and find there's a log file taking up about 95 GB -- so I delete that.

Still 0 GB.

I try emptying the Trash folder, but... apparently that isn't a thing when you're running Caja (MATE flle manager) under KDE. There is no right-click option to empty it.

I run FileLight again and find where the Trash folder is located. I go there and use CLI (well, okay, a Caja action I set up which uses rm) to delete the file from Trash.

Still 0 GB... though FileLight now says I'm only actually using up about half the drivespace, 123 GB. Both df and Caja say no space free, even though the 95 GB file is no longer in evidence.

I had to reboot before the free space would finally show up. This seems like maybe a design flaw in the filesystem API? Like, apparently a block of space can remain allocated for the remainder of a session even when the file attached to it has been deleted.

So, I get a popup saying my system drive is nearly full. (Understandable; it's this 256 GB SSD drive about the size of half a business card.)

I run FileLight and find there's a log file taking up about 95 GB -- so I delete that.

Still 0 GB.

I try emptying the Trash folder, but... apparently that isn't a thing when you're running Caja (MATE flle manager) under KDE. There is no right-click option to empty it.

I run FileLight again and find where the Trash folder is located. I go there and use CLI (well, okay, a Caja action I set up which uses rm) to delete the file from Trash.

Still 0 GB... though FileLight now says I'm only actually using up about half the drivespace, 123 GB. Both df and Caja say no space free, even though the 95 GB file is no longer in evidence.

Never make "cut" the first option in the menu. Never make something destructive, or anything that changes the data in some way, the easiest option to use accidentally. Even if there's an undo. Just don't.

"copy" should come first, always.

Show more

Woozle Hypertwin's choices:

Toot.Cat

The social network of the future: No ads, no corporate surveillance, ethical design, and decentralization! Own your data with Mastodon!